4 ms·
> (mapcar 'list) Thank you for sharing that, I didn't know that was possible. I also tried just doing 'list at the repl, and sure enough it gets recognized as
by kagevf 4y ago
> (mapcar 'list)
Thank you for sharing that, I didn't know that was possible.
I also tried just doing 'list at the repl, and sure enough it gets recognized as a function.
I thought I could break it by doing this:
(let ((list (list 1 2 3)))
(mapcar 'list list))
I even tried adding on (funcall 'list list) to that block and it still works the same as if I had used (funcall #'list list) ....
I guess it works because the list I bound in the LET isn't referenced as a symbol so FUNCALL etc can distinguish one as a symbol that has a function and the other as the name of a binding ...
Was not expecting these results, so I'll need to review symbols and namespaces ...
- kazinator 4y agoYou can't break it with LET because functions are in a separate namespace with variables, and because the function lookup done for 'LIST isn't in the lexical scope; it's done inside the mapcar function in another scope, or maybe in a lower-level function like funcall or apply. Because of separate namspaces, you can't break this either: (let ((list '(1 2 3))) (mapcar #'list ...)) But the following will break it: (flet ((list (x) 42))) ;; actually this is undefined behavior: see below (mapcar #'list ...)) #'list is (function list) which is lexically resolved, and so it refers to the local function flet. If we use 'list, that is unaffected; it goes to the global one. This is a bad example because redefining the standard list function in any scope is not well defined behavior. Implementations can allow it or diagnose it. Because it's undefined behavior, implementations don't have to worry about breakage of list uses which occur in macro expansions. E.g. if the syntax `(,foo ,bar) happens to compile to (list foo bar), and your redefinition of list has taken effect in that scope, then that syntax has broken. Oops!
- kagevf 4y ago> the function lookup done for 'LIST isn't in the lexical scope; it's done inside the mapcar function in another scope, or maybe in a lower-level function like funcall or apply Ah, OK, I think that's the key part I was missing ... that explanation also accounts for what I saw in the REPL ... thanks again! :)