lambdaway
::
meta10
6
|
list
|
login
|
load
|
|
_h1 meta10 | [[meta11]] | [[JS|meca/JS.js]] {input {@ type="button" value="page editor" style="position:fixed; top:10px; left:10px;" onclick="LAMBDATANK.toggle_display('page_editor')"}} {macro '\(((W|S|A)\.(length|get|slice)|A\.disp)\s to '(
$1
} {META.eval ;; CAUTION: round braces must be exclusively used for expressions !!! {{block} _h2 introduction _p {b META} is a fork of {b lambdatalk} - {i and entirely independant of it} - coming with {b 5} special forms, [{code fun, def, if, quote, let}], and a very minimal set of {b 12} carefully choosen primitives. {table {tr {td } {td NEW} {td EQUALITY} {td LENGTH} {td GET} {td SLICE} {td DISP}} {tr {td WORDS} {td _} {td W.equal?} {td W.length} {td W.get} {td W.slice} {td _}} {tr {td SENTENCES} {td _} {td _} {td S.length} {td S.get} {td S.slice} {td _}} {tr {td ARRAYS} {td A.new} {td _} {td A.length} {td A.get} {td A.slice} {td A.disp}} } _p Expressions are written using standard round braces {b '()} contrary to lambdatalk where there are written using curly braces {b '{}}. In this page the {b META} code is embedded inside a single {b META.eval} container where round braces must be exclusively used for expressions, or at least protected. _p In the spirit of what can be seen in [[le premier lisp|https://www.lrde.epita.fr/~raph/docs/lisp/first_lisp.pdf]], the goal is to build and explore on top of these 12 primitives a set of user functions dealing with {b words, sentences & arrays}. _p About the empty slots in the table: _ul {b NEW}: words and sentences don't need any building primitives, they are simply written as they are. _ul {b EQUALITY}: because sentences are sequences of words written without any enclosing delimiters they can't be compared. For arrays only their names can be compared and {b W.equal?} is used in this case. _ul {b DISP}: words and sentences are displayed as they are. Arrays are displayed via {b A.disp}. _p As an example of application we will build {b pairs} and {b lists} from {b arrays}. In {b META} pairs & lists are optional because {b arrays} can be given functions making them usable as lists, A.first, A.rest, ... _p We have added a small bunch of operators, {b =, +, *, -, /, %, pow, sqrt, ...} needed in some examples of code. _p So, in the following, we will build on top of these primitives an extendable set of user defined functions extending the primitive set, theoretically {i ad libitum}. _p This exploration is endless, the current document is in construction and your help is welcome. } ;; end block {{block} _h2 WORDS {pre '(def W hello_world) -> (def W hello_world) '(W) -> (W) 1. primitives '(W.equal? hello hello) -> (W.equal? hello hello) '(W.equal? hello world) -> (W.equal? hello world) '(W.length (W)) -> (W.length (W)) '(W.length ) -> (W.length ) '(W.get 0 (W)) -> (W.get 0 (W)) '(W.slice 1 (- (W.length (W)) 1) (W)) -> (W.slice 1 (- (W.length (W)) 1) (W)) 2. user defined '(def W.first (fun (:w) (W.get 0 :w))) -> (def W.first (fun (:w) (W.get 0 :w))) '(def W.rest (fun (:w) (W.slice 1 (- (W.length :w) 1) :w))) -> (def W.rest (fun (:w) (W.slice 1 (- (W.length :w) 1) :w))) '(def W.last (fun (:w) (W.get (- (W.length :w) 1) :w))) -> (def W.last (fun (:w) (W.get (- (W.length :w) 1) :w))) '(def W.butlast (fun (:w) (W.slice 0 (- (W.length :w) 2) :w))) -> (def W.butlast (fun (:w) (W.slice 0 (- (W.length :w) 2) :w))) '(W.first (W)) -> (W.first (W)) '(W.rest (W)) -> (W.rest (W)) '(W.last (W)) -> (W.last (W)) '(W.butlast (W)) -> (W.butlast (W)) '(def W.reverse (fun (:w) (if (= (W.length :w) 1) then :w else (W.reverse (W.rest :w))(W.first :w)))) -> (def W.reverse (fun (:w) (if (= (W.length :w) 1) then :w else (W.reverse (W.rest :w))(W.first :w)))) '(W.reverse (W)) -> (W.reverse (W)) } _p Should be added some others: W.sort, ... } ;; end block {{block} _h2 SENTENCES {pre '(def S hello brave new world) -> (def S hello brave new world) '(S) -> (S) 1. primitives '(S.length (S)) -> (S.length (S)) '(S.length ) -> (S.length ) '(S.get 0 (S)) -> (S.get 0 (S)) '(S.slice 1 (- (S.length (S)) 1) (S)) -> (S.slice 1 (- (S.length (S)) 1) (S)) 2. user defined '(def S.first (fun (:s) (S.get 0 :s))) -> (def S.first (fun (:s) (S.get 0 :s))) '(def S.rest (fun (:s) (S.slice 1 (- (S.length :s) 1) :s))) -> (def S.rest (fun (:s) (S.slice 1 (- (S.length :s) 1) :s))) '(def S.last (fun (:s) (S.get (- (S.length :s) 1) :s))) -> (def S.last (fun (:s) (S.get (- (S.length :s) 1) :s))) '(def S.butlast (fun (:s) (S.slice 0 (- (S.length :s) 2) :s))) -> (def S.butlast (fun (:s) (S.slice 0 (- (S.length :s) 2) :s))) '(S.first (S)) -> (S.first (S)) '(S.rest (S)) -> (S.rest (S)) '(S.last (S)) -> (S.last (S)) '(S.butlast (S)) -> (S.butlast (S)) '(def S.reverse (fun (:s) (if (= (S.length :s) 1) then :s else (S.reverse (S.rest :s)) (S.first :s)))) -> (def S.reverse (fun (:s) (if (= (S.length :s) 1) then :s else (S.reverse (S.rest :s)) (S.first :s)))) '(S.reverse (S)) -> (S.reverse (S)) '(def S.serie (fun (:a :b) (if (= :a :b) then :a else :a (S.serie (+ :a 1) :b)))) -> (def S.serie (fun (:a :b) (if (= :a :b) then :a else :a (S.serie (+ :a 1) :b)))) '(S.serie 1 10) -> (S.serie 1 10) '(def S.map (fun (:f :s) (if (= (S.length :s) 1) then (:f :s) else (:f (S.first :s)) (S.map :f (S.rest :s))))) -> (def S.map (fun (:f :s) (if (= (S.length :s) 1) then (:f :s) else (:f (S.first :s)) (S.map :f (S.rest :s))))) '(S.map (fun (:x) (* :x :x)) (S.serie 1 10)) -> (S.map (fun (:x) (* :x :x)) (S.serie 1 10)) '(S.map ((fun (:x :y) (pow :x :y)) 2) (S.serie 1 10)) -> (S.map ((fun (:x :y) (pow :x :y)) 2) (S.serie 1 10)) '(S.reverse (S.map W.reverse (S))) -> (S.reverse (S.map W.reverse (S))) '(def S.in? (fun (:w :s) (if (= (S.length :s) 1) then (W.equal? :w :s) else (if (W.equal? :w (S.first :s)) then true else (S.in? :w (S.rest :s)))))) -> (def S.in? (fun (:w :s) (if (= (S.length :s) 1) then (W.equal? :w :s) else (if (W.equal? :w (S.first :s)) then true else (S.in? :w (S.rest :s)))))) '(S.in? x (S)) -> (S.in? x (S)) '(S.in? brave (S)) -> (S.in? brave (S)) } _p Should be added some others: S.reduce, S.replace, S.sort, ... } ;; end block {{block} _h2 ARRAYS {prewrap '(def A (A.new 10 20 30 40 50)) -> (def A (A.new 10 20 30 40 50)) '(A.disp (A)) -> (A.disp (A)) 1. primitives '(A.length (A)) -> (A.length (A)) '(A.length (A.new)) -> (A.length (A.new)) '(A.get 0 (A)) -> (A.get 0 (A)) '(A.disp (A.slice 1 (- (A.length (A)) 1) (A))) -> (A.disp (A.slice 1 (- (A.length (A)) 1) (A))) 2. user defined '(def A.first (fun (:a) (A.get 0 :a))) -> (def A.first (fun (:a) (A.get 0 :a))) '(def A.rest (fun (:a) (A.slice 1 (- (A.length :a) 1) :a))) -> (def A.rest (fun (:a) (A.slice 1 (- (A.length :a) 1) :a))) '(def A.last (fun (:a) (A.get (- (A.length :a) 1) :a))) -> (def A.last (fun (:a) (A.get (- (A.length :a) 1) :a))) '(def A.butlast (fun (:a) (A.slice 0 (- (A.length :a) 2) :a))) -> (def A.butlast (fun (:a) (A.slice 0 (- (A.length :a) 2) :a))) '(A.first (A)) -> (A.first (A)) '(A.disp (A.rest (A))) -> (A.disp (A.rest (A))) '(A.last (A)) -> (A.last (A)) '(A.disp (A.butlast (A))) -> (A.disp (A.butlast (A))) '(def A.reverse (fun (:a) (A.new (S.reverse (A.toS :a))))) -> (def A.reverse (fun (:a) (A.new (S.reverse (A.toS :a))))) '(A.disp (A.reverse (A))) -> (A.disp (A.reverse (A))) '(def A.concat (fun (:a :b) (A.new (A.toS :a) (A.toS :b)))) -> (def A.concat (fun (:a :b) (A.new (A.toS :a) (A.toS :b)))) '(A.disp (A.concat (A) (A.reverse (A)))) -> (A.disp (A.concat (A) (A.reverse (A)))) '(def A.map (fun (:f :a) (S.toA (S.map :f (A.toS :a))))) -> (def A.map (fun (:f :a) (S.toA (S.map :f (A.toS :a))))) '(A.disp (A.map sqrt (A))) -> (A.disp (A.map sqrt (A))) } _p Should be added some others: A.in?, A.duplicate, ... and some more introducing mutations {code A.set!, A.addlast!, A.sublast!, A.addfirst!, A.subfirst!, A.reverse!, A.sort!, A.swap!, ...} } ;; end block {{block} _h2 PAIRS & LISTS _p As an example of application we redefine as a special case of arrays a structure called a {b pair}, [{b cons, car, cdr}], a 2-cells array with its two accessors, on which were built {b lists} invented in the fifties at the birth of {b LISP}. {pre '(def cons (fun (:a :b) (A.new :a :b))) -> (def cons (fun (:a :b) (A.new :a :b))) '(def car (fun (:p) (A.get 0 :p))) -> (def car (fun (:p) (A.get 0 :p))) '(def cdr (fun (:p) (A.get 1 :p))) -> (def cdr (fun (:p) (A.get 1 :p))) '(def P (cons hello world)) -> (def P (cons hello world)) '(car (P)) -> (car (P)) '(cdr (P)) -> (cdr (P)) '(def L (cons hello (cons brave (cons new (cons world nil))))) -> (def L (cons hello (cons brave (cons new (cons world nil))))) '(def nil? (fun (:l) (W.equal? :l nil))) -> (def nil? (fun (:l) (W.equal? :l nil))) '(nil? (L)) -> (nil? (L)) '(nil? (cdr (cdr (cdr (cdr (L)))))) -> (nil? (cdr (cdr (cdr (cdr (L)))))) '(def L.disp ;; ⟨ ⟪ ⟫ ⟩ (def L.disp.r (fun (:l) (if (nil? :l) then else (car :l) (L.disp.r (cdr :l))))) (fun (:l) « (L.disp.r :l)»)) -> (def L.disp (def L.disp.r (fun (:l) (if (nil? :l) then else (car :l) (L.disp.r (cdr :l))))) (fun (:l) ⟨ (L.disp.r :l)⟩)) '(L.disp (L)) -> (L.disp (L)) '(def L.length (fun (:l) (if (nil? :l) then 0 else (+ 1 (L.length (cdr :l)))))) -> (def L.length (fun (:l) (if (nil? :l) then 0 else (+ 1 (L.length (cdr :l)))))) '(L.length (L)) -> (L.length (L)) SERIE & MAP '(def L.serie (fun (:a :b) (if (= :a :b) then (cons :a nil) else (cons :a (L.serie (+ :a 1) :b))))) -> (def L.serie (fun (:a :b) (if (= :a :b) then (cons :a nil) else (cons :a (L.serie (+ :a 1) :b))))) '(L.disp (L.serie 1 10)) -> (L.disp (L.serie 1 10)) '(def L.map (fun (:f :l) (if (nil? :l) then nil else (cons (:f (car :l)) (L.map :f (cdr :l)))))) -> (def L.map (fun (:f :l) (if (nil? :l) then nil else (cons (:f (car :l)) (L.map :f (cdr :l)))))) '(L.disp (L.map (fun (:x) (* :x :x)) (L.serie 1 10))) -> (L.disp (L.map (fun (:x) (* :x :x)) (L.serie 1 10))) '(L.disp (L.map ((fun (:x :y) (pow :x :y)) 2) (L.serie 1 10))) -> (L.disp (L.map ((fun (:x :y) (pow :x :y)) 2) (L.serie 1 10))) and finally: '(def HANOI (fun (:n :from :to :via) (if (= :n 0) then else (HANOI (- :n 1) :from :via :to) '{br} move disc :n from tower :from to tower :to (HANOI (- :n 1) :via :to :from)))) -> (def HANOI (fun (:n :from :to :via) (if (= :n 0) then else (HANOI (- :n 1) :from :via :to) {br} move disc :n from tower :from to tower :to (HANOI (- :n 1) :via :to :from)))) '(HANOI 5 A B C) -> (HANOI 5 A B C) } } ;; end block {{block} _h2 TRANSTYPING {center {table {tr {td } {td word} {td sent} {td arra} {td list}} {tr {td word} {td .} {td W.toS} {td W.toA} {td W.toL}} {tr {td sent} {td S.toW} {td .} {td S.toA} {td S.toL}} {tr {td arra} {td A.toW} {td A.toS} {td .} {td A.toL}} {tr {td list} {td L.toW} {td L.toS} {td L.toA} {td .}} }} _p These functions transtyping words, sentences, arrays and lists help avoid useless redondances, for instance the {b sort} exists for arrays and can be used to sort characters in words, words in sentences and elements in lists. {pre === from words '(def W.toS (fun (:w) (if (= (W.length :w) 1) then :w else (W.first :w) (W.toS (W.rest :w))))) -> (def W.toS (fun (:w) (if (= (W.length :w) 1) then :w else (W.first :w) (W.toS (W.rest :w))))) '(W.toS abcd) -> (W.toS abcd) '(def W.toL (fun (:w) (if (= (W.length :w) 1) then (cons (W.first :w) nil) else (cons (W.first :w) (W.toL (W.rest :w)))))) -> (def W.toL (fun (:w) (if (= (W.length :w) 1) then (cons (W.first :w) nil) else (cons (W.first :w) (W.toL (W.rest :w)))))) '(L.disp (W.toL abcd)) -> (L.disp (W.toL abcd)) '(def W.toA (fun (:w) (A.new (W.toS :w)))) -> (def W.toA (fun (:w) (A.new (W.toS :w)))) '(A.disp (W.toA abcd)) -> (A.disp (W.toA abcd)) === from sentences '(def S.toW (fun (:s) (if (= (S.length :s) 1) then :s else (S.first :s)(S.toW (S.rest :s))))) -> (def S.toW (fun (:s) (if (= (S.length :s) 1) then :s else (S.first :s)(S.toW (S.rest :s))))) '(S.toW a b c d) -> (S.toW a b c d) '(def S.toL (fun (:s) (if (= (S.length :s) 1) then (cons (S.first :s) nil) else (cons (S.first :s) (S.toL (S.rest :s)))))) -> (def S.toL (fun (:s) (if (= (S.length :s) 1) then (cons (S.first :s) nil) else (cons (S.first :s) (S.toL (S.rest :s)))))) '(L.disp (S.toL a b c d)) -> (L.disp (S.toL a b c d)) '(def S.toA (fun (:s) (A.new :s))) -> (def S.toA (fun (:s) (A.new :s))) '(A.disp (S.toA a b c d)) -> (A.disp (S.toA a b c d)) === from lists '(def L.toW (fun (:l) (if (nil? :l) then else (car :l)(L.toW (cdr :l))))) -> (def L.toW (fun (:l) (if (nil? :l) then else (car :l)(L.toW (cdr :l))))) '(L.toW (cons a (cons b (cons c (cons d nil))))) -> (L.toW (cons a (cons b (cons c (cons d nil))))) '(def L.toS (fun (:l) (if (nil? :l) then else (car :l) (L.toS (cdr :l))))) -> (def L.toS (fun (:l) (if (nil? :l) then else (car :l) (L.toS (cdr :l))))) '(L.toS (cons a (cons b (cons c (cons d nil))))) -> (L.toS (cons a (cons b (cons c (cons d nil))))) '(def L.toA (fun (:l) (A.new (L.toS :l)))) -> (def L.toA (fun (:l) (A.new (L.toS :l)))) '(A.disp (L.toA (cons a (cons b (cons c (cons d nil)))))) -> (A.disp (L.toA (cons a (cons b (cons c (cons d nil)))))) === from arrays '(def A.toW (fun (:a) (if (= (A.length :a) 0) then else (A.first :a)(A.toW (A.rest :a))))) -> (def A.toW (fun (:a) (if (= (A.length :a) 0) then else (A.first :a)(A.toW (A.rest :a))))) '(def A.toS (fun (:a) (if (= (A.length :a) 0) then else (A.first :a) (A.toS (A.rest :a))))) -> (def A.toS (fun (:a) (if (= (A.length :a) 0) then else (A.first :a) (A.toS (A.rest :a))))) '(def A.toL (fun (:a) (if (= (A.length :a) 1) then (cons (A.first :a) nil) else (cons (A.first :a) (A.toL (A.rest :a)))))) -> (def A.toL (fun (:a) (if (= (A.length :a) 1) then (cons (A.first :a) nil) else (cons (A.first :a) (A.toL (A.rest :a)))))) '(A.toW (A.new h e l l o)) -> (A.toW (A.new h e l l o)) '(A.toS (A.new 10 20 30 50)) -> (A.toS (A.new 10 20 30 50)) '(L.disp (A.toL (A.new 10 20 30 40 50))) -> (L.disp (A.toL (A.new 10 20 30 40 50))) } } ;; end block {{block} _h2 conclusion _p At the end of the current page the dictionary contains the following primitives & user defined functions {prewrap (lib) } _p To be compared with the set of words, sentences and arrays primitives in {b lambdatalk}: {prewrap {W.lib} {S.lib} {A.lib} {P.lib} } _p {b Lambdatalk} can be seen as a foreign dialect of the {b λ-calculus}, taking benefit of its strong foundations and clear concepts. With {b META} we go on exploring how can be defined the set of primitives. We have highlighted {b 12} fondamental primitives dealing with words, sentences and arrays, trying to follow this citation of Saint Exupery {center " {i La perfection est atteinte {br}non pas quand il n'y a plus rien à ajouter {br}mais quand il n'y a plus rien à enlever.} "} _p {i Alain Marty 2021/07/01} } ;; end block {script var META = (function() { var DICT = {}, FUN_num = 0, regexp = /\(([^\s()]*)(?:[\s]*)([^()]*)\)/g; var evaluate = function(s) { s = pre_processing(s); s = eval_specials(s, "quote", eval_quote, null); s = eval_specials(s, "let", eval_let, null); s = eval_specials(s, "fun", eval_fun, null); s = eval_specials(s, "if", eval_if, null); s = eval_specials(s, "def", eval_def, true); s = eval_forms(s); s = post_processing(s); return s; }; var eval_forms = function(s) { while ( s !== (s = s.replace(regexp, eval_form))) ; return s; }; var eval_form = function() { var f = arguments[1] || "", r = arguments[2] || ""; if (DICT.hasOwnProperty(f)) return DICT[f].apply(null, [r]) else return f + " is unknown"; }; var eval_specials = function(s, special, eval_special, env) { // sequence of (nested) special forms var exp = special_catch(special, s); // (special exp) -> exp if (exp === "none") { // no more special forms return s } else { var one = "(" + special + " " + exp + ")"; var two = eval_special(exp, env); s = s.replace(one, two); return eval_specials(s, special, eval_special, env) } }; var eval_fun = function(s, env) { // eval a (nested) lambda var index = s.indexOf(")"), argStr = supertrim(s.substring(1, index)), args = argStr === "" ? [] : argStr.split(" "), body = supertrim(s.substring(index + 2)), ref = "_FUN_" + FUN_num++; body = eval_specials(body, "fun", eval_fun, env); // recurse inside DICT[ref] = function() { var valStr = supertrim(arguments[0]), vals = valStr === "" ? [] : valStr.split(" "), bod = body; if (vals.length < args.length) { // 1) partial call for (var i = 0; i < vals.length; i++) bod = bod.replace(RegExp(args[i], "g"), vals[i]); var _args_ = args.slice(vals.length).join(" "); bod = eval_fun("(" + _args_ + ") " + bod, env); } else if (vals.length === args.length) { // 2) total call for (var i=0; i < args.length; i++) bod = bod.replace( RegExp(args[i], "g"), vals[i] ); } else { // 3) extra in the last one var _vals_ = vals.slice(0,args.length); _vals_[args.length-1] = vals.slice(args.length-1,vals.length).join(' '); for (var i=0; i < args.length; i++) bod = bod.replace( RegExp(args[i], "g"), _vals_[i] ); } bod = eval_specials(bod,'if',eval_if); return eval_forms(bod); }; return ref; }; var eval_def = function(s, env) { s = eval_specials(s, "def", eval_def, false); var index = s.search(/\s/); var name = s.substring(0, index).trim(); var body = s.substring(index).trim(); if (body.substring(0, 5) === "_FUN_") { DICT[name] = DICT[body]; // an alias } else { body = eval_forms(body); DICT[name] = function() { return body; }; } return env ? name : ""; }; var eval_if = function(s) { s = eval_specials(s,'if',eval_if); var index1 = s.indexOf( 'then' ), index2 = s.indexOf( 'else' ), bool = s.substring(0,index1).trim(), one = s.substring(index1+5,index2).trim(), two = s.substring(index2+5).trim(); return (eval_forms(bool) === 'true')? one : two }; var eval_let = function(s,env) { s = eval_specials(s,"let",eval_let); s = supertrim(s); var varvals = special_catch("(",s); var body = supertrim(s.replace(varvals, "")); varvals = varvals.substring(1, varvals.length - 1); var avv = [], i = 0; while (true) { avv[i] = special_catch("(",varvals) if (avv[i] === "none") break; varvals = varvals.replace(avv[i], ""); i++; } for (var one = "", two = "", i = 0; i < avv.length - 1; i++) { var index = avv[i].indexOf(" "); one += avv[i].substring(1, index) + " "; two += avv[i].substring(index + 1, avv[i].length - 1) + " "; } return "((fun (" + one + ") " + body + ") " + two + ")"; }; var eval_quote = function(s) { return "«" + s.replace( /\(/g, "«" ).replace( /\)/g, "»" ) + "»" }; var special_catch = function(symbol, str) { var d1=0, d2=1, nb=1, index; if (symbol !== "(") { symbol = "(" + symbol + " "; d1 = symbol.length; d2 = 0; } var start = str.indexOf(symbol); if (start == -1) return "none"; index = start; while (nb > 0 && index < 1000000) { // && index < 1000000 while debug index++; if (str.charAt(index) == "(") nb++; else if (str.charAt(index) == ")") nb--; } return str.substring(start + d1, index + d2); }; var pre_processing = function(s) { s = s.replace( /'\(/g , "(quote " ) return s }; var post_processing = function(s) { FUN_num = 0; s = s.replace( /«/g, "(" ).replace( /»/g, ")" ) return s }; var supertrim = function(s) { return s.trim().replace(/\s+/g, " ") }; DICT["lib"] = function() { var str = "", index = 0; for (var key in DICT) { if (DICT.hasOwnProperty(key) && key.substring(0, 5) !== "_FUN_") { str += key + ", "; index++; } } return "DICT: [" + index + "] [" + str.substring(0, str.length - 2) + "]"; }; var balance = function(s) { var strt = s.match(/\(/g), stop = s.match(/\)/g); strt = strt ? strt.length : 0; stop = stop ? stop.length : 0; return { left: strt, right: stop }; }; return { // public functions DICT:DICT, evaluate:evaluate, supertrim:supertrim, balance:balance } })(); // end META //// Lambdatank interface: {eval any META expression} LAMBDATALK.DICT["META.eval"] = function() { var args = arguments[0].trim(); var bal = META.balance(args); var infos = '['+bal.left+'|'+bal.right+']'; if (bal.left === bal.right) args = META.evaluate( args ); return '
'+infos+'
' + args }; //// starting populating the DICTionary //// WORDS META.DICT["W.equal?"] = function() { var a = META.supertrim(arguments[0]).split(" "); return a[0] === a[1] }; META.DICT['W.length'] = function() { var args = arguments[0].trim(); return args.length; }; META.DICT['W.get'] = function () { var args = META.supertrim(arguments[0]).split(' '), i = parseInt(args.shift()); return args.join(' ').charAt(i); }; META.DICT['W.slice'] = function() { var args = META.supertrim(arguments[0]).split(' '), i0 = parseInt(args.shift()), i1 = parseInt(args.shift())+1; return args.join(' ').slice(i0,i1); }; //// SENTENCES META.DICT['S.length'] = function () { var args = META.supertrim(arguments[0]); return (args === '')? 0 : args.split(' ').length }; META.DICT['S.get'] = function () { var args = META.supertrim(arguments[0]).split(' '); return args[args.shift()]; }; META.DICT['S.slice'] = function() { var args = META.supertrim(arguments[0]).split(' '), i0 = parseInt(args.shift()), i1 = parseInt(args.shift())+1; return args.slice(i0,i1).join(' '); }; //// ARRAYS var ARR = (function() { var ARRA = {}, ARRA_num = 0; META.DICT['A.new'] = function () { // (A.new 12 34 56) -> [12,34,56] var args = META.supertrim(arguments[0]); var ref = '_ARRA_' + ARRA_num++; ARRA[ref] = (args != '')? args.split(' ') : []; return ref; }; var isARRA = function (z) { return (z !== '' && z.substring(0,6) === '_ARRA_') }; META.DICT['A.length'] = function () { var args = arguments[0].trim(); // return (isARRA(args))? ARRA[args].length : 0; return ARRA[args].length }; META.DICT['A.get'] = function () { var args = META.supertrim(arguments[0]).split(' '); return (isARRA(args[1]))? ARRA[args[1]][args[0]] : args[1]; }; META.DICT['A.slice'] = function () { // (A.slice i0 i1 a) var args = META.supertrim(arguments[0]).split(' '), i0 = parseInt(args.shift()), i1 = parseInt(args.shift())+1; var ref = '_ARRA_' + ARRA_num++; ARRA[ref] = ARRA[args].slice(i0,i1+0); return ref; }; META.DICT['A.disp'] = function () { // (A.disp z) var args = arguments[0].trim(), str = ''; var rdisp = function( a ) { for (var i=0; i
lambdaway v.20211111