Hi Alex

> The classical curry in picolisp is what Alex has defined a few emails
> > before ;-)
> I never saw a use for the classical curry, so I (ab)used this catchy name
> :)
> Can you give an example where it is useful in PicoLisp?

I'm a newbie to picolisp I don't know enough picolisp to state what is
useful or not.

But curryfied functions are very useful in a lot of situations like
processing lists like mapping (mapcar),  folding...
They are also very useful in function composition which in turn is useful
again in list mapping and so on and also to define functions easier and
And also thery are useful in defining functons in terms of another
functions in a clear, comprehensive and sucint way.

Considering curry defined as Alex's ClassiCurry in terms of picolisp (let's
call it curri here)

  (de curri (Fun)
      (let Par (list (caar Fun))
         (list Par
            (cons 'curry Par (cdar Fun) (cdr Fun)) ) ) )

For example, consider a function like this:

(de task (Action A B) (Action A B))

and you provide a bunch of functions as interface to the previous one:

(de plus (A B) (task + A B))
(de minus (A B) (task - A B))
(de power (A B) (task ** A B))

with curry (really here curri) you can better define the interface
functions as:

(setq plus ((curri task) +))
(setq minus ((curri task) -))
(setq power ((curri task) **))

this way is shorter, clearer and less error-prone and easy to mantain
because if signature of function task changes the interface functions are
not affected at all (provided the first arg continues to be the action)

Also curry functions and partial application are useful to process elements
of a list with functions with many arguments, like

(mapcar ((curri **) 2)  (2 3 4))                # equivalent to (mapcar
'((X) (** 2 X)) (2 3 4))

(setq lstLen ((curri mapcar) length))           # equivalent to (de lstLen
(lst) (mapcar length lst))
(lstLen '((1) (2 3 4) (2 3)))
(((curri mapcar) length) '((1) (2 3 4) (2 3)))  # equivalent to (mapcar
'((L) (length L)) '((1) (2 3 4) (2 3)))

> > >    ((X) '((Y) (+ X Y)))
> > ...
> > The reason for this expression being completely useless in picolisp *I
> > think* is the use of quote as an alias for lambda thus in practise
> > protecting them from evaluation and binding
> This is not the reason. Quote and lambda are abselutely equivalent here.
> You could do
>    (setq lambda quote)
> and then
>       ((X) (lambda (Y) (+ X Y)))
I know that, but I pretend to mean another thing, sadly without clarity

and have the same result, i.e. a function returning ((Y) (+ X Y)), which is
> a
> correct, legal PicoLisp function accepting an single parameter Y and
> returning a
> sum. The quote (or lambda) is gone immediately when returning this
> function.
> It may seem useless to you because PicoLisp uses dynamic binding (X is
> evaluated
> when this function *runs*), but you expected static binding (X is bound to
> the
> value from the environment when this function is *built*).
> The latter is done in the 'classiCurry' example in my last mail using the
> PioLisp 'curry'.

yes, I have to study your classiCurry function to clearly understand how it
works and yes maybe I'm a bit confused about dynamic binding usefulness due
to my static binding background

But let me try to better explain myself...

Writing this code:

(let N 4 (print N))

binds symbol N to value 4 inside print expression and so it prints 4, this
is what we expect of let binding behaviour

same for this code:

(let N 4 (+ 1 N))

we expect to return 5

In a coherent way we expect this code:

(let N 4 ((X) (+ X N)))      # erroneus code, I know it!

to return a function which adds 4 to its parameter   (and it would do it if
it doesn't throw a X undefined error)

But here the problem is we cannot write an anonymous function (a lambda)
this way, we *must* quote it:

(let N 4 '((X) (+ X N)))

but now the quoting has the effect of not evaluating the lambda and thus
preserving it from let symbol binding, this is an undesiderable effect in
my opinion

So how to avoid this undesiderable side effect?  well, first, we have to
kow why it happens, i.e why we must quote the lambda? the answer to protect
it from calling

Calling is what happen to a function when its evaluated, so when let
expression is evaluated, eval see its a function and calls it but it finds
it needs one argument and there's none
so fails with X undefined error, the solution to avoid calling the function
is just avoid evaluating the function and thus the need of quotation with
the bad side effect we've just seen

So what to do? (from here I'm just reasoning loud) well, the key is to
separate function evaluation from function calling, what if there would be
a mark for type function?
in a way the steps in let expression evaluation were similar to this:

1- read the whole let expression
2- read-macros get executed inmmediately (really I think this is part of
step 1)
3- perform the bindings in "let prog" expression
4- evaluate the "let prog" in te context set by let bindings (due to step 3)

With this scheme when step 3 find a function it doesn't evaluate it but
defer evaluation to step 4, it just bind the symbols stated in let.
What is a function? only to possibilities, it is a number which is a
pointer to machine code or it is a lambda (= lisp defined function)
with or without name (usually the term lambda is reserved for anonymous
functions), so if it's a number nothing to do because you cannot
bind internal code but if its a lambda you perform the binding on function
body (function cdar in picolisp). The mark of function object is a list
of params in the caar, I don't know how to diferenciate this from a list
with a similar caar and cdar but suspect the rule is everthing with that
structure is meant to be a lambda, maybe would be useful to have a real
lambda symbol preceding each function definition which acts like
function type mark

Reply via email to