From: Tamas Papp
Subject: how to bind a function generated by another function locally
Date: 
Message-ID: <873azg9xt9.fsf@pu100877.student.princeton.edu>
I hope this makes sense.  I have a function that defines functions:

(defun make-conversion (start end device-start device-end)
  "Create a linear map from [start,end] to [device-start,device-end]."
  (let* ((multiplier (/ (- device-end device-start) (- end start)))
	 (constant (- device-start (* multiplier start))))
    (lambda (x)
      (+ (* x multiplier) constant))))

I know I can use it with funcall:

(let ((conv (make-conversion 100 0 1 0)))
  (funcall conv 100))                          ; => 1

But how could I achieve a situation where I could use it directly
(locally?)  Something like

(some-form-of-let ((conv (make-conversion 100 0 1 0)))
  (conv 100))

flet and labels obviously don't work here, they have different syntax,
but I need a "let for functions".

Tamas

From: Zach Beane
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <m3lkd85pcr.fsf@unnamed.xach.com>
Tamas Papp <······@gmail.com> writes:

> But how could I achieve a situation where I could use it directly
> (locally?)  Something like
>
> (some-form-of-let ((conv (make-conversion 100 0 1 0)))
>   (conv 100))
>
> flet and labels obviously don't work here, they have different syntax,
> but I need a "let for functions".

You could do this:

(let ((conv (make-conversion 100 0 1 0)))
  (flet ((conv (i) (funcall conv i)))
    (conv 100)))

Zach
From: Harald Hanche-Olsen
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <pcod4ykdys5.fsf@shuttle.math.ntnu.no>
+ Zach Beane <····@xach.com>:

| You could do this:
|
| (let ((conv (make-conversion 100 0 1 0)))
|   (flet ((conv (i) (funcall conv i)))
|     (conv 100)))

And of course one could make a macro for that construction
(also taking the liberty of substituting a macrolet for the flet):

(defmacro funlet (bindings &body body)
  `(let ,bindings
     (macrolet ,(loop for (name fun) in bindings collect
		     `(,name (&rest args) `(funcall ,',name ,@args)))
       ,@body)))

and use it as

(funlet
    ((conv (make-conversion 100 0 1 0)))
  (conv 100))

though in real life, the macro should perhaps be equipped with a bit
of usage error detection.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Daniel Trstenjak
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <20070722171305.GB7600@linux.ver>
On Sun, Jul 22, 2007 at 07:02:10PM +0200, Tamas Papp wrote:
> flet and labels obviously don't work here, they have different syntax,
> but I need a "let for functions".

It's all about Lisp1 and Lisp2. 
Have look at http://www.dreamsongs.com/Separation.html.


Regards,
Daniel
From: Tamas Papp
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <87tzrw8iiw.fsf@pu100877.student.princeton.edu>
Daniel Trstenjak <················@online.de> writes:

> On Sun, Jul 22, 2007 at 07:02:10PM +0200, Tamas Papp wrote:
>> flet and labels obviously don't work here, they have different syntax,
>> but I need a "let for functions".
>
> It's all about Lisp1 and Lisp2. 
> Have look at http://www.dreamsongs.com/Separation.html.

I think I understand _why_ this is, but I still don't know how to
achieve whay I wanted.

Tamas
From: Daniel Trstenjak
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <20070722173123.GC7600@linux.ver>
> > On Sun, Jul 22, 2007 at 07:02:10PM +0200, Tamas Papp wrote:
> I think I understand _why_ this is, but I still don't know how to
> achieve whay I wanted.

Then, imho, it's not a got idea wanting to achieve it. It gives
you almost nothing, but obfuscates your code.


Regards,
Daniel
From: ········@gmail.com
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <1185125675.787268.43820@q75g2000hsh.googlegroups.com>
On Jul 22, 12:02 pm, Tamas Papp <······@gmail.com> wrote:
> I hope this makes sense.  I have a function that defines functions:
>
> (defun make-conversion (start end device-start device-end)
>   "Create a linear map from [start,end] to [device-start,device-end]."
>   (let* ((multiplier (/ (- device-end device-start) (- end start)))
>          (constant (- device-start (* multiplier start))))
>     (lambda (x)
>       (+ (* x multiplier) constant))))
>
> I know I can use it with funcall:

>
> (let ((conv (make-conversion 100 0 1 0)))
>   (funcall conv 100))                          ; => 1
>
> But how could I achieve a situation where I could use it directly
> (locally?)  Something like
>
> (some-form-of-let ((conv (make-conversion 100 0 1 0)))
>   (conv 100))

Could you do this with a macro-defining-macro?
Something like:

(defmacro my-defun (name func)
  `(defmacro ,name (&rest args)
    (apply ,func args)))

And then use it with :

(my-defun conv (make-conversion 100 0 1 0))
(conv 100)

It does pollute the namespace though.



Thanks
Raja
From: Thomas F. Burdick
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <1185143916.840327.52200@k79g2000hse.googlegroups.com>
On Jul 22, 7:02 pm, Tamas Papp <······@gmail.com> wrote:

> (some-form-of-let ((conv (make-conversion 100 0 1 0)))
>   (conv 100))
>
> flet and labels obviously don't work here, they have different syntax,
> but I need a "let for functions".

How can you possibly post here as much as you do and not understand
funcall nor apply?  I'll give you, and not c.l.l the benefit of the
doubt (not that I have any particular reason to) ... here's a hint:
(conv (&rest args) (apply %conv args))
From: Tamas Papp
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <87ps2j8rhk.fsf@pu100877.student.princeton.edu>
"Thomas F. Burdick" <········@gmail.com> writes:

> On Jul 22, 7:02 pm, Tamas Papp <······@gmail.com> wrote:
>
>> (some-form-of-let ((conv (make-conversion 100 0 1 0)))
>>   (conv 100))
>>
>> flet and labels obviously don't work here, they have different syntax,
>> but I need a "let for functions".
>
> How can you possibly post here as much as you do and not understand
> funcall nor apply?  I'll give you, and not c.l.l the benefit of the
> doubt (not that I have any particular reason to) ... here's a hint:
> (conv (&rest args) (apply %conv args))

Your assumption is wrong: I know about funcall and apply, but I
thought that there was another way.

It still seems weird that you can assign values to slots in the
namespace of values, but for functions, you can't do that directly:
you have to _define_ the functions there.  I still don't know enought
about Lisp to decide if I am trying to do something silly or if this
is a wart.

I checked the details of my implementation (SBCL), and found the
internal function make-lexenv, but that is not a portable solution.

Tamas
From: Harald Hanche-Olsen
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <pcoy7h7whte.fsf@shuttle.math.ntnu.no>
+ Tamas Papp <······@gmail.com>:

| It still seems weird that you can assign values to slots in the
| namespace of values, but for functions, you can't do that directly:
| you have to _define_ the functions there.

Check out SYMBOL-FUNCTION in the CLHS.  Note that it is an /accessor/,
which means you can do (setf (symbol-function some-symbol) ...).

But you weren't really talking about assigning values in your post.
You were asking about making new bindings.

| I still don't know enought about Lisp [...]

It is good that you admit this.

| to decide if I am trying to do something silly or if this is a wart.

I'd say it's moderately silly in the sense that what you were trying
to do is something experienced Lisp programmers rarely (if ever) see a
need for doing.  And if you should, for some reason, see a definite
need for it, it is easily added to the language, as shown by previous
posts in the thread.  Personally, I don't see the need, although I
provided a solution earlier:  That "extra" FUNCALL in the code conveys
an important clue to the reader of the code about what is happening.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Tamas Papp
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <87hcnv8lrp.fsf@pu100877.student.princeton.edu>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + Tamas Papp <······@gmail.com>:
>
> | It still seems weird that you can assign values to slots in the
> | namespace of values, but for functions, you can't do that directly:
> | you have to _define_ the functions there.
>
> Check out SYMBOL-FUNCTION in the CLHS.  Note that it is an /accessor/,
> which means you can do (setf (symbol-function some-symbol) ...).
>
> But you weren't really talking about assigning values in your post.
> You were asking about making new bindings.

I started by reading the HyperSpec on symbol-function, but learned
that it works on globally defined symbols only.

> | to decide if I am trying to do something silly or if this is a wart.
>
> I'd say it's moderately silly in the sense that what you were trying
> to do is something experienced Lisp programmers rarely (if ever) see a
> need for doing.  And if you should, for some reason, see a definite
> need for it, it is easily added to the language, as shown by previous
> posts in the thread.  Personally, I don't see the need, although I
> provided a solution earlier:  That "extra" FUNCALL in the code conveys
> an important clue to the reader of the code about what is happening.

I see your point.  Nevertheless, in this instance I did think that
Lisp-1 (eg Scheme) is more elegant.  But when I tried Scheme, I felt
constrained by cramming everything into a single namespace --- I guess
I can't have it both ways.

Thanks,

Tamas
From: Harald Hanche-Olsen
Subject: Re: how to bind a function generated by another function locally
Date: 
Message-ID: <pcotzrvwgie.fsf@shuttle.math.ntnu.no>
+ Tamas Papp <······@gmail.com>:

| I started by reading the HyperSpec on symbol-function, but learned
| that it works on globally defined symbols only.

Right, though your terminology is off: "Globally defined symbols"
makes no sense, except in the empty sense that all symbols are in a
way global.  But SYMBOL-FUNCTION works only on the global function
value of the symbol.  Your inability to change the local function
value of the symbol on the fly allows the compiler some important
optimizations, which is very likely one reason you can't do it.  I
mean, in the body of FLET og LABELS the compiler knows exactly what
those symbols stand for, and it can insert calls to the functions
directly or even inline them if it so wishes, with no need to do any
lookup at runtime.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell