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