passing functions/applying nested lambdas

64 views
Skip to first unread message

dun...@cogitat.io

unread,
Apr 7, 2013, 1:07:39 AM4/7/13
to lisp-flavo...@googlegroups.com
So, I've been exploring the foundations of Lisp some more :-) Reading through the older papers (and new ones too) has been a great bit of fun. In particular, I've been translating lambda notation to LFE. But I've got a question about a difference I ran into between LFE and Lisp.

I defined some Church numerals (as functions, which only makes it a little more awkward than setting a variable in CL, but allows me to use the same code between CL and LFE):

(defun zero ()
  (lambda (s)
    (lambda (x) x)))

(defun one ()
  (lambda (s)
    (lambda (x)
      (funcall s x))))
                                                                                                                                                                                                                                          
(defun two ()
  (lambda (s)
    (lambda (x)
      (funcall s
        (funcall s x)))))

The "s" is where one should apply the successor function, and the "x" is where one should apply the value for zero.

I want to be able to check my work, so I was trying to map the Church numerals to integers. I did this with the following function:

(defun successor (n)
  (+ n 1))

After which I attempted to apply (per the terminology of the literature; it's more convenient to use funcall) in the following manner:

> (funcall (funcall (zero) 'successor) 0)
0
> (funcall (funcall (one) 'successor) 0)
exception error: #(badfun successor)

> (funcall (funcall (two) 'successor) 0)
exception error: #(badfun successor)

>

Now, in SBCL with the exact same definitions above, I get the following (expected) results in the REPL:

* (funcall (funcall (zero) 'successor) 0)

0
* (funcall (funcall (one) 'successor) 0)

1
* (funcall (funcall (two) 'successor) 0)

2
*

Iit's fairly clear why zero works in LFE ;-) (no call to successor) given that there's something wrong with the way I'm trying to pass successor in LFE.

Why doesn't the quoting of the function work in LFE? What's the best way to pass the function to the lambda's argument so that the apply/funcall will work?

Sorry if I'm missing the obvious... I feel like you've covered this already :-/

Thanks in advance for your insight/help!

d

dun...@cogitat.io

unread,
Apr 7, 2013, 1:09:15 AM4/7/13
to lisp-flavo...@googlegroups.com


On Saturday, April 6, 2013 10:07:39 PM UTC-7, dun...@cogitat.io wrote:
So, I've been exploring the foundations of Lisp some more :-) Reading through the older papers (and new ones too) has been a great bit of fun. In particular, I've been translating lambda notation

Whoops, typo there. I meant "lambda calculus notation" ...

Mats

unread,
Apr 7, 2013, 12:18:06 PM4/7/13
to lisp-flavo...@googlegroups.com
It looks like you missed a funcall.

> (funcall (funcall (funcall zero) successor) 0)
0
> (funcall (funcall (funcall one) successor) 0) 
1
> (funcall (funcall (funcall two) successor) 0) 
2


--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.
To post to this group, send email to lisp-flavo...@googlegroups.com.
Visit this group at http://groups.google.com/group/lisp-flavoured-erlang?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Duncan McGreggor

unread,
Apr 7, 2013, 3:18:35 PM4/7/13
to lisp-flavo...@googlegroups.com
Huh. Interesting. Why the difference with CL, I wonder? To my eyes (zero) calls the function in CL (which returns the outer-most lambda, iiuc)... why do you suppose it needs an apply/funcall in LFE?

Regardless -- thanks, Mats!

d

Duncan McGreggor

unread,
Apr 7, 2013, 3:45:47 PM4/7/13
to lisp-flavo...@googlegroups.com
Hey Mats,

I just tried the calls that you proved below, but they all return errors:


> (funcall (funcall (funcall one) successor) 0)
exception error: #(unbound_symb one)

Here's my church.lfe file:

(defmodule church                                                                                                                                                                                                                         
  (export all))


(defun zero ()
  (lambda (s)
    (lambda (x) x)))

(defun one ()
  (lambda (s)
    (lambda (x)
      (funcall s x))))

(defun two ()
  (lambda (s)
    (lambda (x)
      (funcall s
        (funcall s x)))))

(defun successor (n)
  (+ n 1))

And here's some example usage:

  > (slurp '"church.lfe")                        
  #(ok church)
  > (one)               
  #Fun<lfe_eval.10.53503600>
  > (two)
  #Fun<lfe_eval.10.53503600>
  > (funcall (funcall (zero) 'successor) 0)       
  0

  > (funcall (funcall (one) 'successor) 0)
  exception error: #(badfun successor)

How did you get your examples to work? Did you change the function definitions?

Thanks!

d




On Sun, Apr 7, 2013 at 9:18 AM, Mats <mats....@gmail.com> wrote:

Robert Virding

unread,
Apr 7, 2013, 3:57:18 PM4/7/13
to lisp-flavo...@googlegroups.com
That actually seems more correct, even if it generates errors. I think the problem is that you are passing in the *name* of a function, in this case successor, and then trying to call it. This is valid in CL but doesn't work in LFE. I am busy right now but will get back with a solution later. Try replacing 'succesor with (fun successor 1), which creates a lambda calling successor with one argument, and it should work. funcall only works on lambdas.

Robert

Mats

unread,
Apr 7, 2013, 4:17:38 PM4/7/13
to lisp-flavo...@googlegroups.com
Here is my script. 

bash-3.2$ erl -pa ebin -s lfe_boot -noshell -noinput
Erlang R16B (erts-5.10.1) [source] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

LFE Shell V5.10.1 (abort with ^G)
> (set zero (lambda ()
            (lambda (s) 
              (lambda (x) x)))))
#Fun<lfe_eval.21.102758147>
> (set one (lambda ()
           (lambda (s)
             (lambda (x)
               (funcall s x))))))
#Fun<lfe_eval.21.102758147>
> (set two (lambda ()
           (lambda (s)
             (lambda (x)
               (funcall s 
                        (funcall s x)))))))
#Fun<lfe_eval.21.102758147>
> (set successor (lambda (n)
                 (+ n 1)))
#Fun<lfe_eval.10.102758147>

Duncan McGreggor

unread,
Apr 7, 2013, 4:28:22 PM4/7/13
to lisp-flavo...@googlegroups.com
That did it, Robert -- thanks!

> (funcall (funcall (zero) (fun successor 1)) 0)
0
> (funcall (funcall (one) (fun successor 1)) 0) 
1
> (funcall (funcall (two) (fun successor 1)) 0)
2

I look forward to your notes on this :-)

d


On 4/7/13 12:57 PM, Robert Virding wrote:
That actually seems more correct, even if it generates errors. I think the problem is that you are passing in the *name* of a function, in this case successor, and then trying to call it. This is valid in CL but doesn't work in LFE. I am busy right now but will get back with a solution later. Try replacing 'succesor with (fun successor 1), which creates a lambda calling successor with one argument, and it should work. funcall only works on lambdas.

Robert

On 7 April 2013 21:45, Duncan McGreggor <dun...@cogitat.io> wrote:
Hey Mats,

I just tried the calls that you proved below, but they all return errors:


> (funcall (funcall (funcall one) successor) 0)
exception error: #(unbound_symb one)

Here's my church.lfe file:

(defmodule church                                                                                                                                                                   &nbsp ;                                                     

Duncan McGreggor

unread,
Apr 7, 2013, 4:30:54 PM4/7/13
to lisp-flavo...@googlegroups.com
Ah, yes -- that explains it. I'm not using the shell, rather I'm loading these functions from a file, so I don't have the luxury of using (set ...).

Thanks, though!

d
(defmodule church                                                                                                                                                                  & nbsp;                                                      

Robert Virding

unread,
Apr 7, 2013, 4:40:30 PM4/7/13
to lisp-flavo...@googlegroups.com
Mats, you were not really defining the functions zero/one/two/successor but binding variables with those names to lambdas. Which is not the same thing in LFE, though it would be in scheme.

I just recalled that there is a new syntax instead of (fun <name> <arity>) for making those lambdas. In CL you write #'successor to get the function binding and in LFE we can now do #'successor/1 to use in a funcall to call the function. Can also do #'mod:func/1 as well to an exported function in another module. This thanks to Klaus Trainer.

So the examples now look like:

> (funcall (funcall (zero) #'successor/1) 0)
0
> (funcall (funcall (one) #'successor/1) 0)
1
> (funcall (funcall (two) #'successor/1) 0)
2

which looks even better and more CL like. This is not yet documented in user_guide.txt though. Mea culpa.

Robert

Mats

unread,
Apr 7, 2013, 4:51:42 PM4/7/13
to lisp-flavo...@googlegroups.com
Ah, thanks. I have to sleep on this.


Off topic:
Robert, I just saw the rackspace interview when you mentioned "pipes".
What was pipes? 
Can we learn something from it? 
Nothing is more powerful than pipes..


Duncan McGreggor

unread,
Apr 7, 2013, 5:34:53 PM4/7/13
to lisp-flavo...@googlegroups.com
This is fantastic, Robert -- thanks!

I've updated the recursion WIP page here:
  http://lfe.github.io/user-guide/extra/1.html

I've added two ways of converting a Church numeral to an integer, depending upon how one wants to call the function (making use of Klaus Trainer's added feature).

That page is getting pretty long, though... I'll split it out into multiple pages eventually.

d
(defmodule church                                                                                                                                                                  &nb sp;&nbsp ;                                                     

Duncan McGreggor

unread,
Apr 7, 2013, 6:21:37 PM4/7/13
to lisp-flavo...@googlegroups.com

On 4/7/13 12:57 PM, Robert Virding wrote:
That actually seems more correct, even if it generates errors. I think the problem is that you are passing in the *name* of a function, in this case successor, and then trying to call it.
Yeah, passing the name was intentional (as I'm sure you knew).

I guess that in CL it's a bit smarter about args to apply, funcall, or anything else that should take a function? It's not being called in the arg, so it looks like it's in the variable namespace, but since it's being passed to something that expects a function, does it look in the function namespace instead?

If that's somewhat close to correct, then I would assume the "problem" in LFE is that it is just strict about variable vs. function namespace and doesn't do type (and parity) guessing?

d


This is valid in CL but doesn't work in LFE. I am busy right now but will get back with a solution later. Try replacing 'succesor with (fun successor 1), which creates a lambda calling successor with one argument, and it should work. funcall only works on lambdas.

Robert

On 7 April 2013 21:45, Duncan McGreggor <dun...@cogitat.io> wrote:
Hey Mats,

I just tried the calls that you proved below, but they all return errors:


> (funcall (funcall (funcall one) successor) 0)
exception error: #(unbound_symb one)

Here's my church.lfe file:

(defmodule church                                                                                                                                                                   &nbsp ;                                                     

Duncan McGreggor

unread,
Apr 7, 2013, 7:24:40 PM4/7/13
to lisp-flavo...@googlegroups.com
Links has changed; new page is here:
  http://lfe.github.io/user-guide/recursion/5.html

d
(defmodule church                                                                                                                                                                  & amp;nb sp;&nbsp ;                                                     
Reply all
Reply to author
Forward
0 new messages