Skip to content

Instantly share code, notes, and snippets.

@greggirwin
Forked from maximvl/poor-mans-scopes.red
Last active April 6, 2017 18:03
Show Gist options
  • Save greggirwin/9521866b110b3fbb3ee55fce1ff89556 to your computer and use it in GitHub Desktop.
Save greggirwin/9521866b110b3fbb3ee55fce1ff89556 to your computer and use it in GitHub Desktop.
Dynamic variables in Red
Red [
author: ["Maxim Velesyuk" "Gregg Irwin"]
description: "Dynamic variables implementation for Red"
notes: {
http://www.gigamonkeys.com/book/variables.html
TBD: Better names.
}
]
dynamic-ctx: context [
; This will be a collection of `word [values]` pairs, where the
; last value in the values block is the most local binding of
; the word.
bindings: copy #()
set 'get-dynamic function [
"Returns a dynamic word's value"
'word
/safe "Return none if word isn't set, instead of causing error"
][
either values: bindings/:word [last values][
either safe [none][
cause-error 'script 'no-value [to path! reduce ['dynamic word]]
]
]
]
; Need to think about this. It may not help.
; mod-bindings: function [
; words-values [block!]
; set-blk [block!] "Do this if the word is set"
; unset-blk [block!] "Do this if the word is not set"
; ][
; foreach [word val] words-values [
; do either bindings/:word set-blk unset-blk
; ]
; ]
set 'with-dynamic function [
"Execute body with dynamically bound words"
words-values
body
][
; If there are already values for a word, add this one to
; the end. If not, add a block for this word, with the
; current value in it.
foreach [word val] words-values [
either values: bindings/:word [append values val][
put bindings word reduce [val]
]
]
; Bindings are all set, so now we can do the body.
do body
; Undo what we did at the top of the func. Remove the last
; value for each word. If there are no values left, remove
; the key for that word from our list of bindings.
foreach [word val] words-values [
if values: bindings/:word [
take/last values
if empty? values [put bindings word none]
]
]
]
]
; Example
f: does [ print [get-dynamic a get-dynamic b get-dynamic c] ]
with-dynamic [a 1 b 2] [
print [get-dynamic a get-dynamic b]
with-dynamic [a 5 c 6] [
f
with-dynamic [b 3 c 10] [ f ]
f
]
print [get-dynamic a get-dynamic b]
;print dynamic c ; show error case
]
; output:
; 1 2
; 5 2 6
; 5 3 10
; 5 2 6
; 1 2
a: 1
aa: does [a]
with-dynamic [a 2][print [a aa]]
with-dynamic [a: 3][with-dynamic [a: 2][print a] print a]
halt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment