return page history
α-wwwiki
::
history/dipert/20130623-051648.txt
editor : alpha [82.248.89.116] 2013/06/23 05:16:48 _h2 15 lines for a very small lisp _p Following [[psil2]], this is a very very small lisp (s-expressionss) interpreter written in 15 lines. The code is adapted from [[Alan Dipert|http://alan.dipert.org/post/7193534410/discover-lisp-in-your-web-browser-with-javascript]] who gives a very clean and clear explanation about the lisp fundamental principle. In this tiny code, there are no defines, no lambdas, nothing but the 4 basic operators "+,-,*,/", the Javascript Math functions ... and any user function predefined in Javascript. From this point of view, it's endless, powerful and evil (because eval). You may : _ul copy a line from the examples, _ul paste it into the field below, _ul and click on the button "evaluate". {input {@ id="input" type="texte" value="['Math.sqrt', ['+', ['*',3,3], ['*',4,4]]]" style="width:100%; font:normal 1em courier; color:red;" }} {input {@ type="submit" value="evaluate" onclick="°° // LISP CODE START : var operators = {'+':0, '-':0, '*':0, '/':0}; // the basic dictionary var evaluate = function(expression) { // ['*',1,2,3,4,5,6] , ['Math.sqrt', 2] or ['+', ['*',3,3], ['*',4,4]] if (!Array.isArray(expression)) return expression.toString(); var func_name = expression[0]; // * , Math.sqrt var func_args = expression.slice(1); // [1, 2, 3, 4, 5, 6] , or [2] var compiled_args = []; for (var i=0; i< func_args.length; i++) compiled_args.push( evaluate( func_args[i] ) ); // ['1', '2', '3', '4', '5', '6'] or ['2'] , ['3*3', '4*4'] if (operators.hasOwnProperty(func_name)) // it's in the dictionary return compiled_args.join(func_name); // 1*2*3*4*5*6 else // it's a JS math function return func_name + '(' + compiled_args.join(',') + ')'; // Math.sqrt(2) } function do_evaluate(input) { return eval(evaluate(eval(input))); } // LISP CODE END // user functions can be called function fac (n) { return (n< 2)? 1 : n*fac(n-1); } function hypo (a,b) { return Math.sqrt( a*a + b*b ); } // ... getId('output').innerHTML = do_evaluate(getId('input').value); °°"}} {pre {@ id="output"}} _h3 some examples to copy/paste {pre ['+',1,2,3,4,5,6] ['*',1,2,3,4,5,6] ['+', ['*',3,3], ['*',4,4]] ['Math.sqrt', 2] ['Math.pow',2,8] ['Math.sqrt', ['+', ['*',3,3], ['*',4,4]]] ['hypo',3,4] ['fac',6] ... and so on. } _h3 lisp code _p Here are the 15 lines of Javascript : {pre °° var operators = {'+':0, '-':0, '*':0, '/':0}; var evaluate = function(expression) { if (!Array.isArray(expression)) return expression.toString(); var func_name = expression.shift(); var func_args = expression; var compiled_args = []; for (var i=0; i< func_args.length; i++) compiled_args.push( evaluate( func_args[i] ) ); if (operators.hasOwnProperty(func_name)) return compiled_args.join(func_name); else return func_name + '(' + compiled_args.join(',') + ')'; } function do_evaluate(input) { return eval(evaluate(eval(input))); } °°} _h3 bug {pre 1) ['+', ['*',3,3], ['*',4,4]] gives the good result : 25 2) ['*', ['+',3,3], ['+',4,4]] gives a bad result : 19 and not 48 because : 1) computes (3*3)+(4*4) = 9+16 = 25 2° computes 3+(3*4)+4 = 3+12+4 = 19 and not (3+3*(4+4) = 48 Some work to do ... }