diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-09 23:58:27 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-09 23:58:27 -0500 |
| commit | a34b02006527d28db5df5c6553be804770b81f79 (patch) | |
| tree | 526fe400e5a8c34b32a3d93439197db09c7f84ad | |
| parent | edc3b0640f1b773e185550448e2086279f7b1a7f (diff) | |
| download | mal-a34b02006527d28db5df5c6553be804770b81f79.tar.gz mal-a34b02006527d28db5df5c6553be804770b81f79.zip | |
Fix metadata on functions.
- Don't use metadata to store ast, env, params data.
- In Clojure, store metadata on the :meta key of the real metadata.
This also allows using any datatype as metadata.
37 files changed, 184 insertions, 140 deletions
diff --git a/clojure/src/core.clj b/clojure/src/core.clj index 23dfc55..27599c0 100644 --- a/clojure/src/core.clj +++ b/clojure/src/core.clj @@ -4,6 +4,16 @@ (defn mal_throw [obj] (throw (ex-info "mal exception" {:data obj}))) +;; Metadata +;; - store metadata at :meta key of the real metadata +(defn mal_with_meta [obj m] + (let [new-meta (assoc (meta obj) :meta m)] + (with-meta obj new-meta))) + +(defn mal_meta [obj] + (:meta (meta obj))) + + ;; Atoms (defn atom? [atm] (= (type atm) clojure.lang.Atom)) @@ -54,8 +64,8 @@ ['apply apply] ['map #(doall (map %1 %2))] - ['with-meta with-meta] - ['meta meta] + ['with-meta mal_with_meta] + ['meta mal_meta] ['atom atom] ['atom? atom?] ['deref deref] diff --git a/clojure/src/step0_repl.clj b/clojure/src/step0_repl.clj index 7a050c7..f6201dd 100644 --- a/clojure/src/step0_repl.clj +++ b/clojure/src/step0_repl.clj @@ -12,13 +12,12 @@ (eval (read-string ast))) ;; print -(defn PRINT [exp] - exp) +(defn PRINT [exp] exp) ;; repl (defn rep [strng] (PRINT (EVAL (READ strng), {}))) -(defn -main [& args] +(defn -main [& args] (loop [] (let [line (readline/readline "user> ")] (when line diff --git a/clojure/src/step1_read_print.clj b/clojure/src/step1_read_print.clj index 31b2ac6..f15131a 100644 --- a/clojure/src/step1_read_print.clj +++ b/clojure/src/step1_read_print.clj @@ -19,7 +19,7 @@ ;; repl (defn rep [strng] - (PRINT (EVAL (READ strng), {}))) + (PRINT (EVAL (READ strng) {}))) (defn -main [& args] (loop [] diff --git a/clojure/src/step2_eval.clj b/clojure/src/step2_eval.clj index 581bf3f..c34a1ae 100644 --- a/clojure/src/step2_eval.clj +++ b/clojure/src/step2_eval.clj @@ -46,7 +46,7 @@ '/ /}) (defn rep [strng] - (PRINT (EVAL (READ strng), repl-env))) + (PRINT (EVAL (READ strng) repl-env))) (defn -main [& args] (loop [] diff --git a/clojure/src/step3_env.clj b/clojure/src/step3_env.clj index 449bf79..7358b49 100644 --- a/clojure/src/step3_env.clj +++ b/clojure/src/step3_env.clj @@ -55,7 +55,7 @@ (def repl-env (env/env)) (defn rep [strng] - (PRINT (EVAL (READ strng), repl-env))) + (PRINT (EVAL (READ strng) repl-env))) (defn _ref [k,v] (env/env-set repl-env k v)) (_ref '+ +) diff --git a/clojure/src/step4_if_fn_do.clj b/clojure/src/step4_if_fn_do.clj index b36f482..d332a14 100644 --- a/clojure/src/step4_if_fn_do.clj +++ b/clojure/src/step4_if_fn_do.clj @@ -71,7 +71,7 @@ (def repl-env (env/env)) (defn rep [strng] - (PRINT (EVAL (READ strng), repl-env))) + (PRINT (EVAL (READ strng) repl-env))) (defn _ref [k,v] (env/env-set repl-env k v)) diff --git a/clojure/src/step5_tco.clj b/clojure/src/step5_tco.clj index 7739029..f4f0107 100644 --- a/clojure/src/step5_tco.clj +++ b/clojure/src/step5_tco.clj @@ -58,11 +58,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) @@ -80,7 +81,7 @@ (def repl-env (env/env)) (defn rep [strng] - (PRINT (EVAL (READ strng), repl-env))) + (PRINT (EVAL (READ strng) repl-env))) (defn _ref [k,v] (env/env-set repl-env k v)) diff --git a/clojure/src/step6_file.clj b/clojure/src/step6_file.clj index a65b741..46bab16 100644 --- a/clojure/src/step6_file.clj +++ b/clojure/src/step6_file.clj @@ -58,11 +58,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) diff --git a/clojure/src/step7_quote.clj b/clojure/src/step7_quote.clj index e68a4cc..5e58e42 100644 --- a/clojure/src/step7_quote.clj +++ b/clojure/src/step7_quote.clj @@ -81,11 +81,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) diff --git a/clojure/src/step8_macros.clj b/clojure/src/step8_macros.clj index ed5638b..605e9d6 100644 --- a/clojure/src/step8_macros.clj +++ b/clojure/src/step8_macros.clj @@ -107,11 +107,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) diff --git a/clojure/src/step9_interop.clj b/clojure/src/step9_interop.clj index da37574..2fae3ca 100644 --- a/clojure/src/step9_interop.clj +++ b/clojure/src/step9_interop.clj @@ -110,11 +110,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) diff --git a/clojure/src/stepA_more.clj b/clojure/src/stepA_more.clj index 77b8cd7..30eb8a6 100644 --- a/clojure/src/stepA_more.clj +++ b/clojure/src/stepA_more.clj @@ -124,11 +124,12 @@ (recur a2 env))) 'fn* - ^{:expression a2 - :environment env - :parameters a1} - (fn [& args] - (EVAL a2 (env/env env a1 args))) + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) ;; apply (let [el (eval-ast ast env) @@ -80,10 +80,11 @@ Future Implementations: * JavaScript * Java * PHP - - C# + * C# * Python - C++ - Ruby + - http://www.ruby-doc.org/stdlib-1.9.3/libdoc/readline/rdoc/Readline.html * C - Objective-C - Perl @@ -116,8 +117,6 @@ Future Implementations: - https://github.com/tpope/timl - Common Lisp - Rust - - - Tier 4 - M (OpenM/MUMPS) - Factor (Stack-based) diff --git a/js/step5_tco.js b/js/step5_tco.js index d61e243..9ba7a98 100644 --- a/js/step5_tco.js +++ b/js/step5_tco.js @@ -69,9 +69,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/step6_file.js b/js/step6_file.js index 7bbb1b4..ab4ba2f 100644 --- a/js/step6_file.js +++ b/js/step6_file.js @@ -69,9 +69,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/step7_quote.js b/js/step7_quote.js index 60ae0e8..3125083 100644 --- a/js/step7_quote.js +++ b/js/step7_quote.js @@ -89,9 +89,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/step8_macros.js b/js/step8_macros.js index 5e39b5b..190cadc 100644 --- a/js/step8_macros.js +++ b/js/step8_macros.js @@ -113,9 +113,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/step9_interop.js b/js/step9_interop.js index 8aa8281..0fd7044 100644 --- a/js/step9_interop.js +++ b/js/step9_interop.js @@ -119,9 +119,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/stepA_more.js b/js/stepA_more.js index c37668a..6a2b949 100644 --- a/js/stepA_more.js +++ b/js/stepA_more.js @@ -130,9 +130,9 @@ function _EVAL(ast, env) { return types._function(EVAL, Env, a2, env, a1); default: var el = eval_ast(ast, env), f = el[0], meta = f.__meta__; - if (meta && meta.exp) { - ast = meta.exp; - env = new Env(meta.env, meta.params, el.slice(1)); + if (f.__ast__) { + ast = f.__ast__; + env = f.__gen_env__(el.slice(1)); } else { return f.apply(f, el.slice(1)); } diff --git a/js/types.js b/js/types.js index 6d7de0f..889e154 100644 --- a/js/types.js +++ b/js/types.js @@ -100,14 +100,14 @@ function _symbol_Q(obj) { return obj instanceof Symbol; } // Functions -function _function(Eval, Env, exp, env, params) { - var f = function() { - // TODO: figure out why this throws with 'and' macro - //throw new Error("Attempt to invoke mal function directly"); - return Eval(exp, new Env(env, params, arguments)); +function _function(Eval, Env, ast, env, params) { + var fn = function() { + return Eval(ast, new Env(env, params, arguments)); }; - f.__meta__ = {exp: exp, env: env, params: params}; - return f; + fn.__meta__ = null; + fn.__ast__ = ast; + fn.__gen_env__ = function(args) { return new Env(env, params, args); }; + return fn; } function _function_Q(obj) { return typeof obj == "function"; } Function.prototype.clone = function() { diff --git a/php/step5_tco.php b/php/step5_tco.php index 0bf55ee..cd4787e 100644 --- a/php/step5_tco.php +++ b/php/step5_tco.php @@ -72,16 +72,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/step6_file.php b/php/step6_file.php index 965ff88..95b3982 100644 --- a/php/step6_file.php +++ b/php/step6_file.php @@ -72,16 +72,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/step7_quote.php b/php/step7_quote.php index 450f2b5..8c407c6 100644 --- a/php/step7_quote.php +++ b/php/step7_quote.php @@ -95,16 +95,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/step8_macros.php b/php/step8_macros.php index 3dea855..c6c7173 100644 --- a/php/step8_macros.php +++ b/php/step8_macros.php @@ -120,16 +120,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/step9_interop.php b/php/step9_interop.php index a699109..3debdc4 100644 --- a/php/step9_interop.php +++ b/php/step9_interop.php @@ -122,16 +122,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/stepA_more.php b/php/stepA_more.php index 4b8a270..7478ee8 100644 --- a/php/stepA_more.php +++ b/php/stepA_more.php @@ -140,16 +140,14 @@ function MAL_EVAL($ast, $env) { break; case "fn*": return _function('MAL_EVAL', 'native', - _hash_map('exp', $ast[2], - 'env', $env, - 'params', $ast[1])); + $ast[2], $env, $ast[1]); default: $el = eval_ast($ast, $env); $f = $el[0]; $args = array_slice($el->getArrayCopy(), 1); if ($f->type === 'native') { - $ast = $f->meta['exp']; - $env = new Env($f->meta['env'], $f->meta['params'], $args); + $ast = $f->ast; + $env = $f->gen_env($args); } else { return $f->apply($args); } diff --git a/php/types.php b/php/types.php index fa57266..e3df3ac 100644 --- a/php/types.php +++ b/php/types.php @@ -59,31 +59,42 @@ class FunctionClass { public $func = NULL; public $type = 'native'; // 'native' or 'platform' public $meta = NULL; + public $ast = NULL; + public $env = NULL; + public $params = NULL; public $ismacro = False; - public function __construct($func, $type, $meta=NULL, $ismacro=False) { + public function __construct($func, $type, + $ast, $env, $params, $ismacro=False) { $this->func = $func; $this->type = $type; - $this->meta = $meta; + $this->ast = $ast; + #print_r($ast); + $this->env = $env; + $this->params = $params; $this->ismacro = $ismacro; } public function __invoke() { $args = func_get_args(); if ($this->type === 'native') { - $fn_env = new Env($this->meta['env'], - $this->meta['params'], $args); + $fn_env = new Env($this->env, + $this->params, $args); $evalf = $this->func; - return $evalf($this->meta['exp'], $fn_env); + return $evalf($this->ast, $fn_env); } else { return call_user_func_array($this->func, $args); } } + public function gen_env($args) { + return new Env($this->env, $this->params, $args); + } public function apply($args) { return call_user_func_array(array(&$this, '__invoke'),$args); } } -function _function($func, $type='platform', $meta=NULL, $ismacro=False) { - return new FunctionClass($func, $type, $meta, $ismacro); +function _function($func, $type='platform', + $ast=NULL, $env=NULL, $params=NULL, $ismacro=False) { + return new FunctionClass($func, $type, $ast, $env, $params, $ismacro); } function _function_Q($obj) { return $obj instanceof FunctionClass; } @@ -172,7 +172,7 @@ end } def % [obj] -> meta -> meta /meta { - 0 _nth /meta get + 0 _nth dup /meta known { /meta get }{ null } ifelse } def diff --git a/python/core.py b/python/core.py index 28d9c5e..5e2ef75 100644 --- a/python/core.py +++ b/python/core.py @@ -85,7 +85,10 @@ def mapf(f, lst): return List(map(f, lst)) # Metadata functions def with_meta(obj, meta): - new_obj = copy.copy(obj) + if type(obj) == type(lambda x:x): + new_obj = obj.__copy__() + else: + new_obj = copy.copy(obj) new_obj.__meta__ = meta return new_obj diff --git a/python/mal_types.py b/python/mal_types.py index 15e4b6b..74409c9 100644 --- a/python/mal_types.py +++ b/python/mal_types.py @@ -38,11 +38,16 @@ def _symbol(str): return Symbol(str) def _symbol_Q(exp): return type(exp) == Symbol # Functions -def _function(Eval, Env, exp, env, params): - def f(*args): - return Eval(exp, Env(env, params, args)) - f.__meta__ = {"exp": exp, "env": env, "params": params} - return f +def _function(Eval, Env, ast, env, params): + def gen_fn(): + def fn(*args): + return Eval(ast, Env(env, params, args)) + fn.__meta__ = None + fn.__ast__ = ast + fn.__gen_env__ = lambda args: Env(env, params, args) + fn.__copy__ = gen_fn + return fn + return gen_fn() def _function_Q(f): return type(f) == type(function_Q) # lists diff --git a/python/step5_tco.py b/python/step5_tco.py index 4335a96..d9d34bc 100644 --- a/python/step5_tco.py +++ b/python/step5_tco.py @@ -65,10 +65,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/python/step6_file.py b/python/step6_file.py index 9e0b8cd..f3847d2 100644 --- a/python/step6_file.py +++ b/python/step6_file.py @@ -65,10 +65,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/python/step7_quote.py b/python/step7_quote.py index 3ed6965..f57dc0a 100644 --- a/python/step7_quote.py +++ b/python/step7_quote.py @@ -87,10 +87,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/python/step8_macros.py b/python/step8_macros.py index 6e2bd45..5d9151a 100644 --- a/python/step8_macros.py +++ b/python/step8_macros.py @@ -107,10 +107,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/python/step9_interop.py b/python/step9_interop.py index 66a8c50..521a3c2 100644 --- a/python/step9_interop.py +++ b/python/step9_interop.py @@ -116,10 +116,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/python/stepA_more.py b/python/stepA_more.py index 7c6a5da..21c1641 100644 --- a/python/stepA_more.py +++ b/python/stepA_more.py @@ -127,10 +127,9 @@ def EVAL(ast, env): else: el = eval_ast(ast, env) f = el[0] - if hasattr(f, '__meta__') and f.__meta__.has_key("exp"): - m = f.__meta__ - ast = m['exp'] - env = Env(m['env'], m['params'], el[1:]) + if hasattr(f, '__ast__'): + ast = f.__ast__ + env = f.__gen_env__(el[1:]) else: return f(*el[1:]) diff --git a/tests/stepA_more.mal b/tests/stepA_more.mal index 456a092..54faa19 100644 --- a/tests/stepA_more.mal +++ b/tests/stepA_more.mal @@ -226,12 +226,18 @@ (meta [1 2 3]) ;=>nil +(meta (fn* (a) a)) +;=>nil + (with-meta [1 2 3] {"a" 1}) ;=>[1 2 3] (meta (with-meta [1 2 3] {"a" 1})) ;=>{"a" 1} +(meta (with-meta [1 2 3] "abc")) +;=>"abc" + (meta (with-meta (list 1 2 3) {"a" 1})) ;=>{"a" 1} @@ -242,16 +248,23 @@ ;;;(meta (with-meta (atom 7) {"a" 1})) ;;;;=>{"a" 1} -(def! lst (with-meta [4 5 6] {"b" 2})) +(def! l-wm (with-meta [4 5 6] {"b" 2})) ;=>[4 5 6] +(meta l-wm) +;=>{"b" 2} + +(meta (with-meta l-wm {"new_meta" 123})) +;=>{"new_meta" 123} +(meta l-wm) +;=>{"b" 2} + (def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1})) (meta f-wm) ;=>{"abc" 1} -(meta (with-meta f-wm "new_meta")) -;=>"new_meta" - +(meta (with-meta f-wm {"new_meta" 123})) +;=>{"new_meta" 123} (meta f-wm) ;=>{"abc" 1} @@ -260,6 +273,22 @@ (meta f-wm2) ;=>{"abc" 1} +;; +;; Make sure closures and metadata co-exist +(def! gen-plusX (fn* (x) (with-meta (fn* (b) (+ x b)) {"meta" 1}))) +(def! plus7 (gen-plusX 7)) +(def! plus8 (gen-plusX 8)) +(plus7 8) +;=>15 +(meta plus7) +;=>{"meta" 1} +(meta plus8) +;=>{"meta" 1} +(meta (with-meta plus7 {"meta" 2})) +;=>{"meta" 2} +(meta plus8) +;=>{"meta" 1} + ;; ;; Testing atoms |
