Friday, December 10, 2010

Beautiful Curl

The Curl language can have a strange beauty: consider that when mixing positional and keyword arguments to a method or procedure that the positions of the former need only be in relative order and that duplicate keyword arguments are permitted.

With access to the Curl AST and the power of Curl macros - and the fact that the  Arguments object is still part of Curl - a fascinating avenue opens for unusual programming paradigms.

Just consider the bug-bear of any Prolog which is the fact that the serial order of clauses and facts is critical and drives the need for cut.  But just imagine the kind of quasi-forward-chaining that can be done by parsing Arguments based on relative positions: remember that the keyword arguments can be in any order and can be duplicated.  Not only that, rest arguments can be given a type at compile time such as anonymous func {proc-type} (but in that case ... may not contain keyword arguments.)

My first experiments are simply

  {clausal goal, 1, clause: procC, clause: procB, 2, clause: procA , asserted-working-mem}

where {clausal} is just
{define-proc {goal:{proc-type}, branch:int, leaf:int, ...}(result:bool, depth:int, breadth:int)
Notice that in my example the rest keyword arg clause: is preceding the positional leaf arg!  There is order relied upon - but it is our order in our code-as-data.

But {define-proc} is itself a Curl macro ... which makes implementing logic in Smalltalk look like really hard work in comparison ...

My convention above is (Goal, [guard-clauses],branch,[clauses],leaf,[clauses],WM)

Anonymous Curl functions close-over their context and are first-class, so I do not explicitly return a solution set.  And of course I can pass in a logic procedure.

What is remarkable is to inspect rest arguments and lo-and-behold there are the multiple keyword arguments.  The convention is that a Curl function cascades to take the last of the duplicate keyword arguments - but now we place our own macro in the body of our clausal proc and proceed to evaluate, parse, ...

Immediately someone says 'But look at the performance hit!'  But if your problem is hard and your solution is elegant, performance will not be the issue - better an answer in 90 seconds or 42 minutes than in 90 centuries or more.

The next nay-sayer: 'But we have a C library that does this!'  And the answer is that we needed a dynamic solution responsive to the user's hunches and advice.  And we wanted a useful, debuggable trace, not a trace that now needs to be parsed and even then may not be useful.  And we want it to be more readable than LISP.

My point is only this: I can get this richness out of the macro {define-proc} itself.  And thankfully Curl 7.0 retained its Arguments class - unlike the fate proposed for Arguments in a harmonized ECMAScript5+ as it moves to its rest arguments convention.  To quote as AS3 author
The catch is to remember that the ...(rest) keyword can be defined only after explicit parameters because required parameters must come before optional ones
Now where had we seen that before ...

No comments: