lambdaway
::
levithan
5
|
list
|
login
|
load
|
|
{uncover http://epsilonwiki.free.fr/ELS_YAW/data/2CV_boule_et_bill.jpg 100 500 It's me with my pupils on the lambda way} {div {@ style="font:italic 2.0em courier; text-align:center; color:#fff;"}(+ 1 (* 2 3) (* 4 5) 6)} {hr} {div {@ style="font:italic 1.5em courier; text-align:center; color:#ff0;"}/\(([^\s()]*)(?:[\s]*)([^()]*)\)/g} _h1 nested expressions & one regExp {blockquote {@ style="transform:rotate(-2deg); padding:10px;"} {prewrap From: alain marty Sent: Sunday, August 28, 2022 1:35 AM To: steve levithan Cc: Ward Cunningham Subject: nested expressions & one regExp Hi Steven Levithan, I discovered years ago your code snippet about reverse-recursive-pattern, a single regular expression and a single line of Javascript - [[http://blog.stevenlevithan.com/archives/reverse-recursive-pattern|http://blog.stevenlevithan.com/archives/reverse-recursive-pattern]] Following this so small and smart idea I built an evaluator of sequences of words and nested prefixed parenthesized expressions - [[http://lambdaway.free.fr/lambdawalks/?view=levithan|http://lambdaway.free.fr/lambdawalks/?view=levithan]] which became "my" programming language - [[http://lambdaway.free.fr/lambdawalks/|http://lambdaway.free.fr/lambdawalks/]] Thank you again Alain Marty {hr} From: Steven Levithan Sent: Monday, August 29, 2022 0:19 AM To: Alain Marty Cc: Ward Cunningham Subject: RE: nested expressions & one regExp Hi Alain, That’s so cool that this line of code I shared inspired work that you’ve been building on for many years now. It seems like the simple, recursive JS parsing you get from it is a tiny, tiny part of the underlying work you’ve done, but it’s a huge compliment that you feel like this was nevertheless useful. Lots of cool ideas in your project. Mixing markup, styling, and scripting via simple parenthesized expressions is a neat trick! Best, Steven Levithan } } _p [[Lambdatalk|?view=start]] began when I discovered years ago in [[Steven Levithan, reverse-recursive-pattern|http://blog.stevenlevithan.com/archives/reverse-recursive-pattern]] this code snippet, a single regular expression, (regexp), and a single line of Javascript. _h2 from removing nested patterns ... _p This is an abstract of Levithan's post: {i _p " Here's a neat little trick I came up with for removing nested patterns from a string. {pre var str = "abc<1<2<>3>4>def"; while (str != (str = str.replace(/<[^<>]*>/g, ""))); // str -> "abcdef" } _p " Notice that the regex in this one-liner doesn't try to deal with nested patterns at all. The while loop's condition replaces instances of <…> (where angled brackets are not allowed in the inner pattern) with an empty string. This repeats from the inside out, until the regex no longer matches. At that point, the result of the replacement is the same as the subject string, and the loop ends. } _p Regular expressions don't like recursion very much, so here's how you can do without it. Very clever! _h2 ... to a nested expressions evaluator _p Following this so small and smart idea I built an evaluator of sequences of words and nested prefixed parenthesized expressions, each one being evaluated from inside out, until the expressions are reduced to simple words. _p In this page I build {b MINI}, which can be seen as [[lambdatalk|?view=start]] reduced to the minimum, a nested expressions evaluator. For instance the expression {b (+ 1 (* 2 3) (* 4 5) 6)} becomes {b (+ 1 6 20 6)} and finally {b 33}. Note that to avoid conflicts inside the current wiki driven by lambdatalk - using curly braces {b '{}} as delimiters - MINI uses here plain parentheses, {b ()}. _p So, in this wiki using lambdatalk, the evaluation is done via a {b mini} function. Writing {pre '{mini I say that 1+2*3+4*5+6 = (+ 1 (* 2 3) (* 4 5) 6) and 1*2*3*4*5*6 = (* 1 2 3 4 5 6) } } _p displays {pre {mini I say that 1+2*3+4*5+6 = (+ 1 (* 2 3) (* 4 5) 6) and 1*2*3*4*5*6 = (* 1 2 3 4 5 6) } } _p In any HTML document without lambdatalk evaluation is done in containers whose class is {b MINI}. Writing {pre <{span}pre class="MINI"> I say that 1+2*3+4*5+6 = (+ 1 (* 2 3) (* 4 5) 6) and 1*2*3*4*5*6 = (* 1 2 3 4 5 6) <{span}/pre> } _p displays {pre {@ class="MINI"} I say that 1+2*3+4*5+6 = (+ 1 (* 2 3) (* 4 5) 6) and 1*2*3*4*5*6 = (* 1 2 3 4 5 6) } _p {b Note that words and nested expressions are mixed without any particular precaution}, no need to protect the sequences of words between quotation marks, to concatenate strings and calculation blocks, we are not in a programming console, we are in a standard word processor ... that can calculate on demand. _p Finally, as a comparizon, in this wiki using lambdatalk, you would evaluate the same expression out of any container, anywhere in the page, just using curly braces instead of round parentheses {pre I say that 1+2*3+4*5+6 = '{+ 1 {* 2 3} {* 4 5} 6} and 1*2*3*4*5*6 = '{* 1 2 3 4 5 6} } _p to display {pre I say that 1+2*3+4*5+6 = {+ 1 {* 2 3} {* 4 5} 6} and 1*2*3*4*5*6 = {* 1 2 3 4 5 6} } _h2 JS code _p Here is the underlying JS code _h3 1) the MINI evaluator {pre °° var MINI = (function() { var pattern = /\(([^\s()]*)(?:[\s]*)([^()]*)\)/g, DICT = []; var evaluate = function(str) { while (str != (str = str.replace( pattern , apply ))) ; return str }; var apply = function() { var f = arguments[1] || "", r = arguments[2] || ""; return DICT.hasOwnProperty(f) ? DICT[f].apply(null, [r]) : // apply the function "[" + f + " " + r + "]"; // or some error message }; return { evaluate:evaluate, DICT:DICT } })(); °°} _h3 2) the MINI.DICTionary _p The dictionary is populated out of the kernel, on demand {pre °° MINI.DICT['myfunction'] = function() { 1) get arguments 2) do something with them 3) return some result }; // for instance: MINI.DICT['+'] = function() { var args = arguments[0].trim().split(" "); for (var res=0, i=0; i < args.length; i++) res += Number( args[i] ) return res }; MINI.DICT['*'] = function() { var args = arguments[0].trim().split(" "); for (var res=1, i=0; i < args.length; i++) res *= Number( args[i] ) return res }; and so on ... °°} _h3 3) the MINI interface _p In any HTML document, inside a script element {b <{span}script>...<{span}/script>} {pre °° setTimeout( function() { var minis = document.getElementsByClassName("MINI"); if (!minis) return for (var key in minis) minis[key].innerHTML = MINI.evaluate( minis[key].innerHTML ) }, 1 ); °°} _p In a wiki using lambdatalk, inside a script special form {b '{script ...}} {pre °° LAMBDATALK.DICT['mini'] = function() { return MINI.evaluate( arguments[0].trim() ) }; °°} _h2 next work _p As for lambdatalk the next work should be to add some special forms [{b lambda, def, if, let, quote, macro, style, script, require}], and much more primitives, and {b MINI} would become a functional programming language. _p But it's another story, the goal here was to show how the code snippet of Levithan can lead to an evaluator of S-expressions. _p You may also compare with [[lambdacode]] built on a standard AST. _p {i alain marty | 20220827} _p [[HN|https://news.ycombinator.com/item?id=35503089]] | [[HN|https://news.ycombinator.com/item?id=43429674]] {script // out of LAMBDATALK setTimeout( function() { var lcs = document.getElementsByClassName("MINI"); if (!lcs) return for (var key in lcs) lcs[key].innerHTML = MINI.evaluate( lcs[key].innerHTML ) }, 1 ); // inside LAMBDATALK LAMBDATALK.DICT['mini'] = function() { return MINI.evaluate( arguments[0] ) }; var MINI = (function() { var pattern = /\(([^\s()]*)(?:[\s]*)([^()]*)\)/g, DICT = []; var evaluate = function(str) { while (str != (str = str.replace( pattern , apply ))) ; return str }; var apply = function() { var f = arguments[1] || "", r = arguments[2] || ""; return DICT.hasOwnProperty(f) ? DICT[f].apply(null, [r]) : "[" + f + " " + r + "]"; }; return { evaluate:evaluate, DICT:DICT } })(); MINI.DICT['+'] = function() { var args = arguments[0].trim().split(" "); var res = 0; for (var i=0; i < args.length; i++) res += Number( args[i] ) return res }; MINI.DICT['*'] = function() { var args = arguments[0].trim().split(" "); var res = 1; for (var i=0; i < args.length; i++) res *= Number( args[i] ) return res }; } {style body, #page_frame, #page_content, .page_menu { background:#444; border:0; color:#fff; } pre { background:#333; padding:10px; color:#fff; } }
lambdaway v.20211111