;'<<SPEC'
<!--
Copyright (c) 2012-2024, Chris Pressey, Cat's Eye Technologies.
This file is distributed under a 2-clause BSD license. See LICENSES/ dir.
SPDX-License-Identifier: LicenseRef-BSD-2-Clause-X-Robin
-->
### `bind` ###
-> 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))))))