git @ Cat's Eye Technologies Robin / master stdlib / bind-vals.robin
master

Tree @master (Download .tar.gz)

bind-vals.robin @masterraw · history · blame

;'<<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-vals` ###

    -> Tests for functionality "Evaluate Robin Expression (with Stdlib)"

`bind-vals` is a fexpr for bindings the components of a possibly-deep list
to the identifiers given in another possibly-deep list (of symbols).

It is similar to `bind-args` but doesn't evaluate the values that are
being bound.

    | (bind-vals (a b) (literal (1 2))
    |   (list a b))
    = (1 2)

Expressions in the list of values are not evaluated.

    | (bind-vals (a b) (literal ((subtract 5 4) (subtract 10 1)))
    |   (list a b))
    = ((subtract 5 4) (subtract 10 1))

It handles deep lists.

    | (bind-vals (a (b c)) (literal (1 (2 3)))
    |   (list a b c))
    = (1 2 3)

This is how it might be used in a fexpr definition.

    | (bind add (fexpr (args env)
    |   (bind-vals (a b) args
    |     (subtract a (subtract 0 b))))
    |   (add 4 5))
    = 9

    | (bind add (fexpr (args env)
    |   (bind-vals (a b) args
    |     (subtract a (subtract 0 b))))
    |   (add 4 (add 5 6)))
    ? (abort (expected-number (add 5 6)))

    | (bind transducer (fexpr (args env)
    |   (bind-vals ((event-type event-payload) state) args
    |     (list state (list event-type event-payload))))
    |   (transducer (click (button 12345)) 0))
    = (0 (click (button 12345)))

'<<SPEC'

(define bind-vals
  (fexpr (args env)
    (let (
      (id-list       (head args))
      (val-list      (eval env (head (tail args))))
      (expr          (head (tail (tail args))))
      (bind-vals-r   (fexpr (args env)
        (let (
          (self     (eval env (head args)))
          (id-list  (eval env (head (tail args))))
          (val-list (eval env (head (tail (tail args)))))
          (expr     (eval env (head (tail (tail (tail args))))))
          )
          (if (equal? id-list ())
            expr
            (let ((id (head id-list)) (val (head val-list)))
              (if (list? id)
                (self self id val
                  (self self (tail id-list) (tail val-list) expr))
                (list (literal bind) id (list (literal literal) val)
                  (self self (tail id-list) (tail val-list) expr)))))))))
      (eval env (bind-vals-r bind-vals-r id-list val-list expr)))))