Evaluating vs Non-evaluating Functions

This concept is central to PicoLisp.

An evaluating function is generally more powerful, while a non-evaluating one might be more convenient. You can always use the evaluating version instead of the non-evaluating one (at the expense of more writing), but not vice versa.

'set' vs 'setq'

The most obvious case is 'set' vs. 'setq'. A call to the (non-evaluating) 'setq'

   (setq A 123)

can be replaced with the (evaluating) 'set'

   (set 'A 123)

However, a call like

   (set (foo (bar)) 123)

cannot be replaced with 'setq', because the result of calling 'foo' must be found out by evaluation first

'let' vs 'bind'

Again, it is a matter of convenience:

   (let A (lines "lib.l")
      (* A A) )

If you wanted to use 'bind' for that, you could do

   (bind 'A
      (setq A (lines "lib.l"))
      (* A A) )


   (bind (list (cons 'A (lines "lib.l")))
      (* A A) )

'bind' is more flexible, as the symbols can be determined at runtime, while 'let' allows for a more readble code.

Note that in the Function Reference, evaluated arguments are marked with a quote. For example,

 : (doc 'let)

   (let sym 'any . prg) -> any
   (let (sym 'any ..) . prg) -> any


   : (doc 'bind)

   (bind 'sym|lst . prg) -> any

We see that 'let' doesn't evaluate 'sym', while 'bind' does.

'run' vs 'prog'

The same with the question of using 'run' or 'prog'.

'run' is a function which evaluates its argument, and then runs it

   : (run (list '(println 1) '(println 2)))
   -> 2

After evaluation, 'run' sees the list ((println 1) (println 2)), and executes it.

So instead of 'prog', you could always use 'run' with a quoted argument list (analog to the 'set' / 'setq' example above):

   : (prog (println 1) (println 2))
   -> 2

   : (run '((println 1) (println 2)))
   -> 2

That's the whole difference.


09apr17    erik