Hi Srini,

> I am trying to understand this example from the reference:
> (prog1  # Parallel background calculation of square numbers
>    (mapcan '((N) (later (cons) (* N N))) (1 2 3 4))
>    (wait NIL (full @)) )

> Could you please explain how it works, because it has many
> interrelated pieces: cons,mapcan, wait that I thought I understood
> individually but still I do not understand the example.

This call to 'prog1' executes two expressions, returning the result of
the first one, but _after_ executing the second one.

The first expression calls 'mapcan' on the list (1 2 3 4), by applying
the function

   ((N) (later (cons) (* N N)))

to each of the numbers. This function in turn returns the result of
'later'.

So the key here is 'later'. As the reference says,

   (later 'var . prg) -> var

'later' accepts a 'var' (i.e. a symbol or a list cell), and returns that
var. As a side effect, it takes a program (a 'prg' which is a list of
expressions), runs that in a child process, and stores the result of
that 'prog' in the 'var' at some later point when the child process is
done.

For a simple example, we can execute in the REPL

   : (later 'A (+ 1 2 3 4 5))
   -> A

We see that 'later' returs the variable 'A'. But if we look a moment
after that into the value of 'A'

   : A
   -> 15

we see that it has received the result of the calculation.


A single call to 'later' is not very useful, because we might instead
directly execute the expression.

But if one same expression has to be done in parallel (a typical use
case is starting a parallel database query on remote machines), then we
pass list cells instead of a single variable to 'later'.

This is done with the 'mapcan' and 'cons' above. Remember that (cons) is
just a shortcut of (cons NIL NIL), and that 'mapcan' concatenates the
returned results. Thus, the above call without 'later' gives:

   : (mapcan '((N) (cons NIL NIL)) (1 2 3 4))
   -> (NIL NIL NIL NIL)

However, if we have

   (mapcan '((N) (later (cons) (* N N))) (1 2 3 4))

Then as a side effect each call to 'later' receives its private, newly
'cons'ed list cell - i.e. a 'var' - which it duefully retunrs to
'mapcan' to be concatenated to the full list.

At the same time, each 'later' remembers its private cell, and stores
its result from the child process there.

Then 'wait' waits until ALL cells are filled (i.e. non-NIL).



> Another confusing thing is the "@". How does one find which of the
> previous functions updated the @, and which did not. I know that control

This is documented in "http://software-lab.de/doc/ref.html";. Exclusively
the (flow) functions listed there will modify '@'.

There's also a nice article by Thorsten: The many uses of @ in PicoLisp

   http://picolisp.com/wiki/?atmark

♪♫ Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to