thanks for your answers, Alex

On Sun, Jan 29, 2017 at 9:48 AM, Alexander Burger <a...@software-lab.de>
wrote:

>
> > >    (if (testSomething) (doSomething1) (doSomething2) (doSomething3))
> > ...
> > but this also means the only way to indicate several executable
> expressions
> > in the "then-clause" is to surround them between parens, i.e.  (if (= 2
> 2)
> > ((print "equal") (print "2")) (print "not equal") (print "not 2"))   I
>
> No. This gives a crash (try it, and think about why ;).
>


I tried and it crashes with a segmentation fault, I was thinking about what
could be the reason and my guess is it is related with 'eval' function. I
think when the body of "if" function tries to eval the any2 expression it
fails with sementation fault if it is a list of lists, that is, the first
item of any2 expression is a list:

(eval 1)  -> 1
(eval (1)) -> (1)
(eval ((1))) ---- segmentation fault

My guess is eval tries to evaluate its parameter, thus when being a number
it evaluates to itself and an atom evaluates to its value:

(setq A 1)
(eval A) -> 1
(eval B) --- B is not defined

But when the parameter to evaluate is a list, eval tries to evaluate the
list which means to apply the function call represented by the list, with
special case of lists of numbers

(de f (X) (+ X 1))
(eval (f 1)) -> 2   # eval tries to evaluate the list viewed as a function
call so it applies function f to parameter 2 and gets the returned value as
the result of eval
(eval (1 2)) -> (1 2)  # the same as above but exploiting the special
treatment picolisp give to list of numbers in order to avoid quoting it

The problem appears when you pass eval a list of lists (or a list with a
first item which is also a list), in this case eval tries to evaluate but
doen't know how to eval a item list, it could be a function call because it
is not an atom. Using the analogy of stack when eval gets a simple list it
pops the first item which being an atom means it must be a function name so
two possible cases it's a defined function or it is not defined, if it is
defined but it's not a function but it also fails with segmentation fault
because you cannot apply an atom if it's not a function (and evaluating a
list means it must be a function call  --or a list of numbers--)

(de f (X) (* X X))
(setq A 1)
(eval (f 2)) -> 4
(eval (A 2)) --- segmentation fault
(eval f)  --- X undefined
(eval 'f)  -> ((X) (* X X))
(eval (f)) -> NIL # strangely in this case it doesn't say X undefined but
returns NIL

The problem seems to be only when eval expects an atom to be a function or
an undefined symbol and what it gets is an defined atom which is not a
function symbol:

(eval B) -> NIL
(eval (B)) --- B undefined
(eval (B 1)) --- B undefined
(eval ((B))) --- B undefined
(eval ((B 1))) --- B undefined
(setq B 2)
(eval B) -> 2
(eval (B)) --- segmentation fault
(eval (B 1)) --- segmentation fault
(eval ((B))) --- segmentation fault
(eval ((B 1))) --- segmentation fault

Also eval evaluates recursively the list passed as arguments

(de g (X) (+ X 1))
(de f (X) 'g)
(eval ((f 99) 2 )) -> 3

So my conclusion is eval always expect a list to be a valid function call
(or a list of numbers) and if it is not then fails with segmentation
fault.  And the reason for "if" to fail in a similar way is it tries to
eval the "then-clause" (any2)

If so what I don't understand is why to cause a segmentation fault, I think
it could easily avoid if eval phase in REPL simply detect a first item in a
list being a defined atom but not a function and throw an error (in a
similar way of "not defined" errors in previous examples) or even even
evaluating the atom to its value when it detects it is not a function (even
being the first item in a list).

What I mean is maybe a desiderable behaviour of eval would be:

(setq A 1)
(de f (N) (+ N 1))
(eval A) -> 1
(eval (f 1)) -> 2
(eval (A 2)) --- A is not a function  # case 1, eval knows it is not a
function
(eval (A 2)) -> 1   # case 2, even when it seems a function call since A is
not a function but a defined symbol resolve to its value
(eval ((A))) -> 1  # case 2, but could also be implemented as case 1 too

Is it my reasoning right?  or maybe I'm saying a nonsense?

Anyway I see the segmentation fault messages includes some numbers, are
they anyhow setted by picolisp or are they totally system dependent?

[1]    863 segmentation fault  ./pil +
 ^     ^^^
 |______|____ this numbers


regards

Reply via email to