View Source Document

bind.robin

;'<<SPEC'

    -> Tests for functionality "Evaluate Robin Expression (with literal and bind)"

`bind` binds a single identifier to the result of evaluating a single
expression, and makes that binding available in another expression which
it evaluates.

    | (bind x (literal hello)
    |   (prepend x (prepend x ())))
    = (hello hello)

    | (bind dup (fexpr (args env)
    |             (prepend (head args) (prepend (head args) ())))
    |   (dup g))
    = (g g)

    | (bind dup (fexpr (args env)
    |             (bind x (eval env (head args))
    |               (prepend x (prepend x ()))))
    |   (dup (literal g)))
    = (g g)

    | (bind dup (fexpr (args env)
    |             (bind x (eval env (head args))
    |               (prepend x (prepend x ()))))
    |   (dup (dup (literal g))))
    = ((g g) (g g))

`bind` can bind a recursive fexpr to a name.

    | (bind elem?-r
    |   (fexpr (args env)
    |     (bind self (eval env (head args))
    |       (bind target (eval env (head (tail args)))
    |         (bind items (eval env (head (tail (tail args))))
    |           (if (equal? items ()) #f
    |             (if (equal? (head items) target) #t
    |               (self self target (tail items))))))))
    |   (elem?-r elem?-r (literal c) (literal (a b c d e f))))
    = #t

`bind` expects exactly three arguments, or else an abort value will be produced.

    | (bind smoosh (fun (x y) (list y x)))
    ? abort

    | (bind smoosh)
    ? abort

    | (bind)
    ? abort

The identifier in a binding must be a symbol.

    | (bind 3 1 3)
    ? abort

`bind` is basically equivalent to Scheme's `let`, but only one
binding may be given.

'<<SPEC'

(define bind (fexpr (args env)
  (if
    (symbol? (head args))
    (eval
      (prepend
        (prepend (head args) (prepend (eval env (head (tail args)))
                                         ())) env)
      (head (tail (tail args))))
    (abort ((literal expected-symbol) (head args))))))