Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is absolutely possible! You're almost there. You just bumped into Common Lisp's dual namespaces, which can take a lot of getting used to. I hope I can say a thing or two to make Common Lisp's two namespaces a bit less confusing.</p> <p>Your code is almost correct. You wrote:</p> <pre><code>(defun foo (fn seq) (mapcar #'fn seq)) </code></pre> <p>But, what is that trying to do? Well, <em>#'</em> is shorthand. I'll expand it out for you.</p> <pre><code>(defun foo (fn seq) (mapcar (function fn) seq)) </code></pre> <p>So, <em>#'symbol</em> is shorthand for <em>(function symbol)</em>. In Common Lisp -- as you seem to know -- symbols can be bound to a function and to a variable; these are the two namespaces that Lispers talk so much about: the function namespace, and the variable namespace.</p> <p>Now, what the <em>function</em> special form does is get the function bound to a symbol, or, if you like, the value that the symbol has in the function namespace.</p> <p>Now, on the REPL, what you wrote would be obviously what you want.</p> <pre><code>(mapcar #'car sequence) </code></pre> <p>Would map the <em>car</em> function to a sequence of lists. And the <em>car</em> symbol has no variable binding, only a function binding, which is why you need to use <em>(function ...)</em> (or its shorthand, <em>#'</em>) to get at the actual function.</p> <p>Your <em>foo</em> function doesn't work because the function you pass it as an argument is being bound to a symbol <em>as a variable</em>. Try this:</p> <pre><code>(let ((fn #'sqrt)) (mapcar #'fn '(4 9 16 25))) </code></pre> <p>You might have expected a list of all those numbers' square roots, but it didn't work. That's because you used <em>let</em> to bind the square root function to <em>fn</em> as a variable. Now, try this code:</p> <pre><code>(let ((fn #'sqrt)) (mapcar fn '(4 9 16 25))) </code></pre> <p>Delightful! This binds the square root function to the <em>fn</em> symbol as a variable.</p> <p>So, let's go revise your <em>foo</em> function:</p> <pre><code>(defun foo (fn seq) (mapcar fn seq)) </code></pre> <p>That <em>will</em> work, because <em>fn</em> is a variable. Let's test it, just to make sure:</p> <pre><code>;; This will not work (foo sqrt '(4 9 16 25)) ;; This will work (foo #'sqrt '(4 9 16 25)) </code></pre> <p>The first one didn't work, because the square root function is bound to <em>sqrt</em> in the function namespace. So, in the second one, we grabbed the function from the symbol, and passed it to foo, which bound it to the symbol <em>fn</em> as a variable.</p> <hr> <p>Okay, so what if you want to bind a function to a symbol in the function namespace? Well, for starters, <em>defun</em> does that, permanently. If you want it to be temporary, like a <em>let</em> binding, use <em>flet</em>. <em>Flet</em> is, in my opinion, stupid, because it doesn't work exactly like let does. But, I'll give an example, just so you can see.</p> <pre><code>(flet ((fn (x) (sqrt x))) (mapcar fn '(4 9 16 25))) </code></pre> <p>will not work, because <em>flet</em> didn't bind the function to the symbol in the variable namespace, but in the function namespace.</p> <pre><code>(flet ((fn (x) (sqrt x))) (mapcar #'fn '(4 9 16 25))) </code></pre> <p>This will do what you expect, because <em>flet</em> bound that function to the symbol <em>fn</em> in the function namespace. And, just to drive the idea of the function namespace home:</p> <pre><code>(flet ((fn (x) (sqrt x))) (fn 16)) </code></pre> <p>Will return 4.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload