This Question is Assumed Answered

1 "correct" answer available (5 pts) 15 "helpful" answers available (3 pts)
6 Replies Last post: May 18, 2008 9:07 AM by rshiplett

Goal-oriented Curl or GoCurl

Feb 15, 2008 12:26 PM

Click to view rshiplett's profile MVP rshiplett 36 posts since
Oct 17, 2007

I am hoping there might be some interest in discussing which aspects of ICON-style backtracking as found in UNICON and CONVERGE ( and possibly Godiva Goal-OrienteD JaVA ) could be possible in Curl.

In CONVERGE expressions are expected to return a value, and when they don't, backtracking occurs.

Perhaps there is someone at Cambridge Square with an old hankering for pattern-matching post-SNOBOL ....

Links of interest might be

Clinton Jeffrey and http://www.cs.nmsu.edu/~jeffery/godiva/godiva.html

Laurence Tratt and http://convergepl.org/

ICON homepage http://www.cs.arizona.edu/icon/index.htm

UNICON homepage http://unicon.sourceforge.net/

I am wondering about such an ICON-like facility initially only being available to XCURL scripts or RCURL scripts (future serveR-side Curl scripts)

The use of ICON-style matching becomes very appealing when the data is already CURL

Click to view cbarber's profile Curl cbarber 124 posts since
Sep 27, 2007
1. Re: Goal-oriented Curl or GoCurl Feb 20, 2008 2:04 PM

It may be a while before I can dig through all those papers for the relevant parts.

Do you have a simple example of something you would like to do that you can express using curlish syntax?

Click to view rshiplett's profile MVP rshiplett 36 posts since
Oct 17, 2007
2. Re: Goal-oriented Curl or GoCurl Feb 23, 2008 8:43 AM
in response to: cbarber
In my years in Smalltalk (while wishing I was doing Prolog) a lasting issue was our continued vulnerability to array bounds errors.

In Curl, {value {{String "full string too short"}.substr 8, 9}} succeeds (evaluation can proceed forward) whereas {value {{String "full string too short"}.substr 8, 42}} raises an Array bounds exception.

However in Curl

{value
{for str:String in {{String "www.curl.com"}.split split-chars = {CharClass ","}} do

|| we only have a comma char in our CharClass init string
{text str}
}
}

does not 'fail' even though the string cannot "succeed" in splitting into parts.

In a language for which a String is just an array of char, (i.e. a byte) this is understandable.

In Icon, if I had some strings and the one I look at is not the right length, I step back and look at the next item

If none is the right length ( excuse the Pythonic pun) and if I can step back from that expression, then I step back.

This backtracking is not unlimited: it is based on the success or failure of evaluated expressions.

A previous success where a variable was bound will stop the backtracking ( unlike the prolog strategy of unification )

This {eval expr} strategy is able to replace many "statement-like" switch/case and if/then/elseif/else with some very simple expressions.

In today's Curl, I know of nothing comparable to Python's slice, which does not raise an exception for "test"(1:13) (pretend those are square brackets)

In Curl, { {String "test"}.find 'Z', starting-index = 42 } raises an ArrayBoundsException

We have {try } but do not have, say, an {attempt } on which the expressions within the attempt expression do not raise exceptions.

Suppose you could have a container of strings and you could 'look' at each, as Turing might have said, and attempt to see the 42nd character.

On day n1, the list has only short strings ( where short means less than 42 ) We capture this test expression with, say, a tilde-operator

( item.zero-based-length ~< Universe . answerLength )

or with some other syntactic sugar to indicate that the expression may succeed or may fail ( does not resolve to a boolean value but to a choice: proceed or try to backtrack). In a future Curl we might have this way of evaluating an expression:

{*attempt* {list item }

{ does item(Universe . answerLength)

|| ... "does" might be better "satisfies" ?
} } || note that this is not a WHILE or an UNTIL expression nor is it just a sugared {for do {if
|| because if this attempt is a possible step of another attempted goal, we may be back !
|| ( as if we handed them a proc-type of iterator whose NEXT returns a MORE until it returns a EMPTY )

In the classic Icon examples you would recognize Python generators with yield or our own Curl .to-Iterator

The prospect that I see is for much cleaner Curl code with fewer {for do} and far fewer {if then elseif }

Likely someone at Curl can say off-hand how much of the success | fail goal behavior could be implemented using a macro named {attempt } without introducing a type which is not boolean, say Outcome, with two values, succeed and fail.

My naive approach is to say that for any list of items for which to attempt the eval of an expr there could be an underlying list of uninitialized outcome values that resolve to true or false assignments as the evaluation of an expression succeeds or fails and the boolean evaluation of that 'list' corresponds to the result of a goal-attempt AND or OR for the list of items and the simulated generator. Because that list is indexed, you can backtrack from a failure subsequent to some indexed success s >= n > 0 to a previous indexed success at s < n > 0. Each of those could point back to another such list. Having no such underlying list for a given index s would amount to prior expressions being 'bound' ( limited backtracking ). Think of this as starting as (null, null, null) and progressing to (fail,success,success) to (fail, success,fail) to (fail,bound,fail) which would read that we backtracked into the second item and there found a final success. Or we might have ended in failure at (fail, fail,fail) or even had very early success terminating evaluation with (bound, null, null) such that we never re-enter to try evaluation of item(1) and item(2) Naturally on this approach an item cannot be bound until any underlying list has a bound item and does not fail until an underlying list has items all of which failed or we fail with an underlying list where we were branched off the last success, which thereby fails to bind and so back down the chain to a success where a bound assignment occurs or we fail. And there are interesting options to proceed breadth first or depth first { atttempt strategy = shallow, list, item

And so to my second cup of Saturday morning coffee. Note: Backtracking may be more often thought of as PROLOG. For the various efforts to meld prolog and Smalltalk see my page at aboutus.org or to see prolog in another multi-paradigm functional language see OZ, the language (for which there is a book which CURL might envy.) For typed-prolog, see http://www.pdc.dk/ or the Mercury project (where I believe someone now has Mercury running on top of Erlang - but where there is no UNICODE) PDC focussed on having an IDE and at the other end of the gamut, Mercury still has no IDE. Prolog evolved to PROLGIA clp and continues to evolve, significantly as XSB at xsb.sourceforge.net And for forward rather backward, see production systems, such as JESS, the Java interface to a PS. BTW, POPLOG remains active at U. Birmingham on the Greenwich side of the drink. For Windows, Strawberry Prolog is active in Sofia. For O-O Horn-clause backtracking+unification, the most interesting project to my mind is that at www.logtalk.org For a real curiosity there is EZY Prolog using dialogs ( analogies with Curl spring to mind - ah, there's the coffee now ... )

PS For Windows, if you attempt UNICON, install to C and save your icn files to UNICON\bin even after you set that in the PATH IFF you have problems.

Click to view rshiplett's profile MVP rshiplett 36 posts since
Oct 17, 2007
3. Re: Goal-oriented Curl or GoCurl Feb 23, 2008 8:19 AM
in response to: rshiplett

To see all this from another angle, look at Rebol and its parse dialect, such as the simple case of parse a string-sequence using a space character.

In Rebol you have to be aware that some expressions have a side-effect ( do not return a value ) e.g., output to a console.

At www.Rebol.org there is a prolog . r to load into Rebol as well ( and there is the quite mature SOUL for Cincom Smalltalk i.e. SOUL aka Smltk Open Unification Lang which was once QSOUL as in quasi-quoted SOUL as in Converge, the programming lang )

I find moving between REBOL and CURL very fruitful when looking at problems ( and if you see me posts in the Rebol world at altme.com you will know that I plug Curl regularly - my dream being to see www.qtask.com adopt Curl for the front-end ... ) just as I often look at Curl through my Smalltalk lenses. And as for going to the dark side ( from dexter to sinister ) years with the right-handed Smalltalk mouse have left me doing Curl left-handed ( for which do see the 3M mouse-stick (2 sizes) )

Click to view cbarber's profile Curl cbarber 124 posts since
Sep 27, 2007
4. Re: Goal-oriented Curl or GoCurl Feb 25, 2008 7:49 AM
in response to: rshiplett
It should be possible for you to implement a Curl syntax like your description of 'attempt'. I would simply use exceptions for backtracking to start with. I think I would go with a syntax like:

{first <item> in <list> where <condition>}

where <item> is an identifier, <list> is an expression evaluating to an iterator or iterable container and <condition> is a boolean expression. Here is a crude untested implementation:

{define-syntax public {first
                                          ?item:identifer in ?list:expression 
                                           where ?cond:expression
                                  }
    {return
        {expand-template
            {value
                let result:any
                {for ?item in ?list do
                      {try
                            {if ?cond then
                                 set result = i
                                 {break tag = outer}
                            }
                        catch ex:Exception do
                       }
                 }
                 {error "Can't find first with '%s'.", {cond.get-text}}
            }
            result
        }
    }
}

To make this real, I would throw a special exception instead of a generic Error and I would add code to infer the static return type from the container using SyntaxEnv.type-of and reflection.

You could also expand the syntax to allow a compile-time list to be provided, such as:


{first x in (a,b) where x != null}

which could expand into something with an inner loop like:

{while true do
    {do
        def x = a
        {if x != null then
            set result = x
           {break}
        }
    }
    {do
        def x = b
        {if x != null then
             set result = x
            {break}
        }
    }
    {error "Can't find first..."}
}
Click to view friedger's profile MVP friedger 108 posts since
Jan 13, 2008
5. Re: Goal-oriented Curl or GoCurl May 17, 2008 2:31 AM
in response to: rshiplett

Is there any code somewhere already available? I am interested in trying GoCurl out.

Friedger

Click to view rshiplett's profile MVP rshiplett 36 posts since
Oct 17, 2007
6. Re: Goal-oriented Curl or GoCurl May 18, 2008 9:07 AM
in response to: friedger

I am buried in Curl work just now ... I am getting together soon with Carl S. who is a committer to ICON 9.5 and I have tried to interest Laurie Tratt in NITRO. Later this summer I may be able to stop in Moscow Idaho and chat some about how Godiva is progressing. Tratt's Converge 1.0 is really interesting.

Btw, another language in need of a home is Strongtalk ...