Kaz Kylheku
4/28/2015 7:33:00 PM
On 2015-04-28, SergioBG BG <sergiobgar@gmail.com> wrote:
> El martes, 28 de abril de 2015, 20:43:55 (UTC+2), Kaz Kylheku escribió:
>> On 2015-04-28, SergioBG BG <sergiobgar@gmail.com> wrote:
>> > Hi , one question out of curiosity.
>> >
>> > I can see javascript , C++ , python etc are languages in evolution ,is lisp
>> > in this stage ?
>>
>> More language evolution happens in a typical project written in the Lisp
>> language, than what happens in Python, Javascript or C++.
>>
>> Javascript, Python and C++ users have to wait for the next release of the
>> compiler or interpreter.
>>
>> Moreover, the development is done behind closed doors, by people who don't
>> necessarily care what the users want or need. The ISO C++ process is
>> destroying the C++ language with garbage features, for instance.
>>
>> Lisp users just write the language features that they actually need, here and
>> now in their project, or borrow them from other people.
>> Language features are just library features. You can patch them easily
>> if you need to, remove stuff you don't want, change them to suit your project
>> and the like.
>>
>> On top of that, people are experimenting with new dialects like Clojure and
>> Racket.
>>
>> I'm innovating in small ways in a dialect of Lisp ebmedded into a data
>> munging tool called TXR.
>>
>> Just this week I made a release in which a new Lisp macro is featured, called
>> mlet ("magic let" or "mutual let"), which I invented. It goes one step beyond
>> Scheme's letrec.
>>
>> Fristly, under mlet, all variable initializations are delayed until the "first
>> use" of a variable:
>>
>> Example:
>>
>> (mlet ((a (progn (prinl "a inited") 1))
>> (b (progn (prinl "b inited") 2))
>> (c (progn (prinl "c inited") 3)))
>> (list c b))
>>
>> Here only c and b are accessed, so only those variables are initialized.
>> Moreover, they are accessed in that order -- c, then b -- and so
>> we will see
>>
>> "c inited"
>> "b inited"
>>
>> and the result will be the list (3 2). We do not see "a inited".
>>
>> Secondly, under mlet, all the init forms have all the variables in scope.
>> Therefore, this is possible:
>>
>> ;; Dependent calculations in arbitrary order
>> (mlet ((x (+ y 3))
>> (z (+ x 1))
>> (y 4))
>> (+ z 4)) --> 12
>>
>> The initialization of x looks forward to the variable y. z looks backward
>> to x. Everything is worked out.
>>
>> Lastly, if a lazy data structure constructor is used (like the lcons macro
>> in TXR Lisp to make a lazy cons), mlet allows for a cyclic reference:
>>
>> (mlet ((circ-list (lcons 1 circ-list)))
>> circ-list) -> (1 1 1 1 1 ....) ;; circular list, not lazy-infinite
>>
>> How this works is that the variable circ-list is referenced for the
>> first time in the body and so it is initialized at that time.
>> The (lcons ...) expression is evaluated. Now lcons is a macro which
>> delays the evaluation of its arguments, therefore the circ-list
>> argument isn't evaluated---which is a good thihg, because we haven't
>> finished initializing the variable. So without evaluating circ-list,
>> lcons yields a lazy cons cell, which then becomes the value of circ-list.
>> When the lazy cons cell's fields later materialize, its cdr field
>> will refer back to itself, creating a circular list.
>>
>> Ordinary eager circularity is erroneous and is detected:
>>
>> Firstly:
>>
>> $ txr -p '(mlet ((x (+ 1 y)) (y (+ 2 x))))'
>>
>> No problem here: why? Because x and y are not referenced in the body.
>> Let's add a reference to x:
>>
>> $ txr -p '(mlet ((x (+ 1 y)) (y (+ 2 x))) x)'
>> txr: unhandled exception of type eval-error:
>> txr: message: (string:1) force: recursion forcing delayed form (+ 1 y) (string:1)
>>
>> mlet is a small example of actual language evolution: it's code which
>> executes, today. Not some fucking ISO standard that will be coming
>> to everyone's compiler except for yours in 2017.
>>
>> I didn't discuss it with anyone. I designed it, coded it and pushed it out
>> the door.
>>
>> If someone wants it in their Lisp dialect, they can read my documentation,
>> study the code, if necessary and implement it in a compatible way.
>> To do that, they won't have to hack the Lisp implementation itself.
>>
>> Good luck getting the equivalent of mlet into Python, Javascript or
>> (LOL) C++.
> Aja I can see what you say , lisp is modifiable as you need ., but with
> macros?
Macros is pretty much all that the "other guys" have also. What Lisp calls
a macro is a "syntax rule" in C++. The Lisp programmer can write that in Lisp,
whereas the C++ programmer has to unpack the sources to GNU C++, and
write a new rule in the Yacc grammar, plus additional code to bring
about the translation scheme for that piece of grammar.
Lis macros aren't like C preprocesor macros; they are like phrase structure
rules in a C compiler. For instance "while (expr) statement" is a kind of
macro in the C compiler. The parser recognizes it, and builds some
abstract syntax tree. This might then undergo "macro expansion" into
an tree which just uses if, goto and a pair of generated labels, corresponding
to the code.
Original: while (expr1) { if (expr2) break; expr3; }
Expansion: L0001: if (expr1) { if (expr2) goto L0002; expr3; goto L0001 }
L0002: ;
The compiler-generated labels are just like "gensyms" in Lisp.
Look, the LOOP feature of Lisp is a macro. It's obviously a mini-programming
language for loops, featuring clauses with a varied grammar:
(macroexpand '(loop for x in '(1 2 3) and for y = 1 then (1+ y)
collect (list x y)))
Lisp macros are (or can be) "bullet-proof", like statements in Python or C++.
Also, the word "syntax" in Lisp usually refers to structure of macros
and special operators, rather than to the raw text which features things like
hash marks and parentheses. (That is called "read syntax").