git @ Cat's Eye Technologies Robin / master stdlib / unshadow.robin
master

Tree @master (Download .tar.gz)

unshadow.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
-->

### `unshadow` ###

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

`unshadow` is similar to `unbind`, but only removes the latest binding
for the given identifier; previously shadowed bindings, if any exist,
will be visible instead.

    | (unshadow yog-sothoth (if #t (literal x) (literal y)))
    = x

    | (unshadow if (if #t (literal x) (literal y)))
    ? abort (unbound-identifier if)

    | (bind if (literal what)
    |   (unshadow if (if #t (literal x) (literal y))))
    = x

    | (bind q 400
    |   (unshadow q q))
    ? abort (unbound-identifier q)

    | (bind q 200
    |   (bind q 400
    |     (unshadow q q)))
    = 200

    | (bind q 100
    |   (bind q 200
    |     (bind q 400
    |       (unshadow q (unshadow q q)))))
    = 100

    | (let ((q 100)
    |       (q 200)
    |       (q 400))
    |   (unshadow q (unshadow q q)))
    = 100

`unshadow` is something of a gimmick that shows off Robin's ability
to manipulate the evaluation environment.  In practice, the bindings
can be determined lexically, and a different identifier could always
be chosen instead.

'<<SPEC'

(define unshadow
  (fexpr (args env)
    (bind remove-binding-r (fun (self id li)
      (if (empty? li)
        li
        (if (equal? (head (head li)) id)
          (tail li)
          (prepend (head li) (self self id (tail li))))))
      (eval (remove-binding-r remove-binding-r (head args) env)
        (head (tail args))))))