Hi Tomas, as a general rule I would state:
Only functions which evaluate all of their arguments should be passed to 'apply'. For other functions the result is undefined. > : (de hi @ (println (rest))) > -> hi > : (de hello L (println L)) > -> hello > : (hi 1 2 3) > (1 2 3) > -> (1 2 3) > : (hello 1 2 3) > (1 2 3) > -> (1 2 3) > : (apply hi (1 2) 3) > (3 1 2) > -> (3 1 2) This is ok so far. > : (apply hello (1 2) 3) > NIL > -> NIL As 'hello' is not evaluating its arguments, it is not a good candidate for 'apply'. 'apply' is a bit tricky internally. It actually behaves similar to the normal interpreter. It looks at the function being passed, and prepares the (evaluated) arguments in a suitable way: - If the function is a Lisp function with a list of parameter symbols, 'apply' binds the successive list elements to those symbols. - If the function is a Lisp function with an '@' parameter (variable number of arguments), the environment is set up appropriately. - If it is a Lisp function with a single symbolic parameter (non-evaluating), that parameter is simply bound to NIL (as you observed). - If it is a function pointer (C-function), things get tricky. A data structure (as shown in "doc/apply") is set up and maintained, consisting of list cells and symbols (the lowest row), where the successive list elements are inserted. Then the whole list is passed to the internal function which then believes to have a list of symbols as an argument, where it can happily "evaluate" each symbol to retrieve the inserted value. > : (and 1 2 3) > -> 3 > : (apply and (1 2) 3) > -> 2 Note, here too, that 'and' is not really suited for 'apply', as it does not always evaluate all of its arguments. But, ok for now ... > : (de and L > (loop > (NIL (setq @ (eval (car L) 1))) > (NIL (pair (setq L (cdr L))) @) ) ) > # and redefined > : (and 1 2 3) > -> 3 This implementation of 'and' is not completely right. It does, for example, not correctly handle the '@' symbol: : (and (+ 3 4) (+ @ 1)) !? (+ @ 1) b -- Number expected If we look at the C implemenetation: any doAnd(any x) { any a; x = cdr(x); do { if (isNil(a = EVAL(car(x)))) return Nil; val(At) = a; } while (isCell(x = cdr(x))); return a; } then we could do an analog Lisp function (de and L (use A (loop (NIL (setq A (eval (pop 'L) 1))) (up @ A) (NIL (pair L) A) ) ) ) This can be simplified a little, by taking advantage of '@': (de and L (loop (NIL (eval (pop 'L) 1)) (up @ @) (NIL (pair L) @) ) ) So this seems correct: : (and (+ 3 4) (+ @ 1)) -> 8 'apply' of course does not work, for the reasons explained above. > What is the fundamental difference between > > (de lfn L ...) > > and > > any cfn(any ex) {...} Probably the fact that Lisp functions do not receive the full runtime expression, but only the arguments. The C-function 'and' recieves the list (and (+ 3 4) (+ @ 1)) while the Lisp function only recieves ((+ 3 4) (+ @ 1)) Therefore, a Lisp function cannot access the function symbol (here 'and'). > Does it mean that there is a certain class of functions that can only be > implemented in C and not in picolisp? Hmm, I'm not sure. There might always be a way to get around this limitation. Cheers, - Alex -- UNSUBSCRIBE: mailto:picol...@software-lab.de?subject=unsubscribe