Search code examples
racketalgebraic-data-types

How do you destructure values in a let binding using algebraic racket


I'm trying to work through the tutorial on delimited continuations here http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf using Racket instead of OCaml, but hitting snags when trying to express my program using Racket's algebraic data types so that my example code tracks closely to the tutorial.

Specifically, I cannot figure out how to bind the fields of an instance using a let form. In this simple example, I define a Tree sum type with two product types Empty and Node where each node will contain a left branch, a value, and a right branch.

#lang algebraic/racket/base
(require algebraic/function)

(data Tree (Empty Node))

(define tree1 (Node (Node Empty 1 Empty) 2 (Node Empty 3 Empty)))

(let ([(Node left value right) tree1]) value)

What I'd expect is that this expression would evaluate to 2 because value is bound to the value field of the root node, but instead it fails with let: bad syntax (not an identifier) in: (Node left value right). However if I understand the docs correctly, this is something that ought to be possible.

For example, I'm able to define the walk function to recursively visit each node in the tree and use pattern matching to bind the left and right sides of the tree and this works just great.

(define walk (function
 [Empty `done]
 [(Node left value right)
  (walk left)
  (println value)
  (walk right)]))

I just can't seem to do it in the context of let. Is my syntax wrong? Am I using the right version of let? Is this something you can even do?


Solution

  • It looks like algebraic/racket/base doesn't provide the syntax for let, and so its just getting it from vanilla racket/base. Not sure if that's intentional or a bug, but either way you can work around it by adding (require algebraic/racket/base/forms) to your code. Giving you:

    #lang algebraic/racket/base
    
    (require algebraic/racket/base/forms)
    (require algebraic/function)
    
    (data Tree (Empty Node))
    
    (define tree1 (Node (Node Empty 1 Empty) 2 (Node Empty 3 Empty)))
    
    (let ([(Node left value right) tree1]) value)
    

    Which evaluates to 2.