I keep reading how goal-driven execution model looks like, and while I really like natural feel of such condition:
if (a < b < c)
yesterday I found the piece of code which put me off. Consider printing out the just-read line in Icon:
read hits the
EOF it fails, and thus entire chain of expressions fails — here it means
write won’t be called. Let’s say you would like to catch the content of the line nevertheless, so you do a little rewrite:
line := read() write(line)
OK, we have 2 lines, but the code basically does the same thing… Wait, it does not. It is not even close. Now when
read hits the
EOF the chain of expressions ends at the assignment, so it will be omitted and
line will keep its previous value. Since the second line is completely unrelated it will be executed with the old
Sure, I am surprised, and maybe part of the surprise is because I am not used to the way Icon works. But I think transparency of adding temporary objects to keep intermediate results is pretty fundamental concept, and Icon breaks it — something I cannot like.
From that point there are two approaches — give up or design improved goal-driven model (it might the same path though).
As for giving up I went back to my old idea of returning tuple — pair of function outcome and error:
if ((success:@,value) = dict["hello"]).success then // we have direct access to value // success is dropped
The syntax has a lot to be desired, so how about adding
when construct which could handle exactly such cases:
when value = dict["hello"] then // we have direct access to value
This would be syntactic sugar only — pure internal rewrite to the
if presented above.
And then it struck me — forget about Lisp homoiconicity, uniformity stupid! Lispers have to struggle with ugly syntax:
(if (= 4 (+ 2 2)) (...
instead of clean “syntax for the masses”:
if 4 = 2+2 then...
but Lisp syntax is uniform, and because of that Lispers don’t have to wait for anyone to bring new construct to the language. They add their
when whenever they like — it blends in perfectly.
On the other hand in C-derivatives all you have is function-like expansion, you cannot add another
while. Any attempt to bring Lisp-macro to C world would require allowing the user to alter the grammar of the language.
I didn’t solve anything with goal-driven model — instead I added yet another puzzle for myself. What to sacrifice in the design to bring power of macros to Skila?
If you find this topic interesting, more readings for you — The Nature of Lisp, Homoiconicity isn’t the point and Lisp: It’s Not About Macros, It’s About Read.