Page 1 of 1

what's wrong with the use of apply append

Posted: Tue Sep 03, 2019 6:26 am
by lyl
First example:

Code: Select all

(setq var "b")
(apply append '("a" var)) ;; I believe the result will be "ab", but what I get is error message.
Second example:

Code: Select all

(setq var "b")
(append "a" var);; -> "ab"
I think the two examples are equivalent, but it seems not. Why? And why the first example is a wrong way to use "append" and how to make "apply append" work?

Re: what's wrong with the use of apply append

Posted: Tue Sep 03, 2019 9:49 am
by rickyboy
What we were missing was the error message:

Code: Select all

> (setq var "b")
"b"
> (apply append '("a" var)) ;; I believe the result will be "ab", but what I get is error message.

ERR: string expected in function append : 'var
The problem is that in the expression '("a" var), var is getting quoted; so, you end up passing a symbol as the second argument to append and hence it complains (in the error message) that var (a symbol) is not something that it can do anything with.

(The subtle thing to notice at the end of the error message is the single quote character right before "var".)

Another way, the expression '("a" var) is a list of a string and a symbol:

Code: Select all

> '("a" var)
("a" var)
> (list '"a" 'var)
("a" var)
So, by substitution, these are equivalent:

Code: Select all

> (apply append '("a" var))

ERR: string expected in function append : 'var
> (apply append (list '"a" 'var))

ERR: string expected in function append : 'var
On the other hand, in the case of the expression (append "a" var), the evaluator gets a chance to evaluate var (an unquoted symbol) to its current runtime value ("b").

So, to answer your last question, something like this would work:

Code: Select all

> (apply append (list "a" var))
"ab"
Hope that helps.

Re: what's wrong with the use of apply append

Posted: Tue Sep 03, 2019 12:23 pm
by lyl
Thank you so much for this detail explaination.
As you say, "so, you end up passing a symbol as the second argument to append".
The symbol 'var which is passed to "append" has been binded to "b", why is the evaluator not able to see it?
Dose that mean each element of a list which will be passed to a function by "apply" must be evaluated first? And is this a mechanism from "lisp" or from "newlisp"?

Re: what's wrong with the use of apply append

Posted: Tue Sep 03, 2019 6:03 pm
by rickyboy
The symbol 'var which is passed to "append" has been binded to "b", why is the evaluator not able to see it?
The short answer is: because the quote prevents it from getting evaluated, as in:

Code: Select all

> (setq var "b")
"b"
> 'var
var
> var
"b"
Here, the single quote character (preceding var) prevents var from being evaluated (to its current value). Actually the expression 'var is shorthand for (quote var) and that *does* get evaluated -- it's just that the newLISP evaluator has a special rule for quote expressions: don't evaluate quote's argument, just return it exactly as it was given.

Code: Select all

> (quote var)
var
The newLISP evaluator is exposed to the user via the primitive eval; so, one could evaluate the above quote expression "manually" (although in general, it's not considered good practice).

Code: Select all

> (eval (quote var))
"b"
And is this a mechanism from "lisp" or from "newlisp"?
All the lisps that I know of have this same behavior. For example, take a Scheme:

Code: Select all

$ guile
guile> (define val "b")
guile> 'val
val
guile> (quote val)
val
guile> val
"b"
guile> (string-append "a" val)
"ab"
guile> (apply string-append '("a" val))

Backtrace:
In standard input:
   6: 0* [apply #<primitive-procedure string-append> ("a" {val})]
In unknown file:
   ?: 1  [string-append]
   ?: 2* [string-append "a" {val}]

ERROR: In procedure string-append:
ERROR: Wrong type (expecting string): val
ABORT: (wrong-type-arg)

guile> (apply string-append (list "a" val))
"ab"
Emacs Lisp:

Code: Select all

*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (setq val "b")
"b"
ELISP> 'val
val
ELISP> (quote val)
val
ELISP> val
"b"
ELISP> (concat "a" val)
"ab"
ELISP> (apply #'concat '("a" val))
*** Eval error ***  Wrong type argument: sequencep, val
ELISP> (apply #'concat (list "a" val))
"ab"

Re: what's wrong with the use of apply append

Posted: Wed Sep 04, 2019 11:53 am
by lyl
Oh, I understand it! @rickyboy And learn a lot from you. I will use "apply" more carefully.