From: Vassil Nikolov
Subject: Re: conditionals in flet: symbol-function =/= #' ?!
Date: 
Message-ID: <85351.vnikolov@math.acad.bg>
On 08 Sep 1997 12:27:37 -0400, 
SDS  <···········@cctrading.com> wrote:

> ... text omitted...
>The question remains: is there
>a way to flet a local function conditionally?

No, there isn't.  FLET (and LABELS, for that matter) are
quite `static.'  What you get from

  (flet ((foo (x ...) #<foo's body>))
    ... calls to foo...
  )

is no more than what you get by substituting
``(LAMBDA (X ...) #<foo's body>)'' for ``FOO'' at every
call to FOO in the body of the FLET form.  (Of course,
there are obvious advantages to FLET, but it doesn't give
more power with respect to such conditionals.)

>
>What I will be doing for now is:
>
>(let ((zz (if whatever #'(lambda (xx) (1- xx)) #'(lambda (xx) (1+ xx)))))
>  (funcall zz xx))
>
>I am pretty sure it will work, although it does look kind of ugly.
>

Ugly or not, this is the way to do it, at least in the
general case.

You could hide FUNCALL, of course, by having

  (let ((zz-aux (if whatever ...)))
    (flet ((zz (x) (funcall zz-aux x)))
      ...
    )
  )

which might be better from a stylistic point of view, or
you could have the IF outside the FLET:

  (if whatever
    (flet ((zz (x) (1- x)))
      ...
    )
    (flet ((zz (x) (1+ x)))
      ...
    ))

at the expense of greater program size.  (This latter approach
would work only in some cases, naturally, i.e. when there is
no need to change ZZ during each extent of the FLET form.)

In case you need to refer to the ZZ function outside the
lexical scope of the above form, you have to use LET *and*
a special variable, of course, together with FUNCALL.

> ... text omitted...

In most cases FUNCALL is unavoidable when the function
to be called will be determined at run time.  This doesn't
really add overhead per se; and whether the explicit use of
FUNCALL is a good or bad thing is up to personal preferences,
I'd say.  Think about this analogy to C: if you have a pointer
to a function declared as

  return_type (*f)(some_type x);

then would you call the function that f points to by

  result = (*f)(expression);

or by

  result = f(expression);

as C allows you to have it both ways?

(I think that your post is really about the need for
FUNCALL, not about SYMBOL-FUNCTION vs. FUNCTION.)

Good luck,
Vassil.

Vassil Nikolov         <········@bgearn.acad.bg>     (+359-2) 713-3813
Department of Information Research
Institute of Mathematics and Informatics        fax: (+359-2) 9713649
Acad. G. Bonchev, block 8, Sofia 1113, Bulgaria

From: Ken Tilton
Subject: Re: conditionals in flet: symbol-function =/= #' ?!
Date: 
Message-ID: <347877D7.6D85@bway.net>
> On 08 Sep 1997 12:27:37 -0400,
> SDS  <···········@cctrading.com> wrote:
> 
> > The question remains: is there
> > a way to flet a local function conditionally?
> >
> >What I will be doing for now is:
> >
> >(let ((zz (if whatever #'(lambda (xx) (1- xx)) #'(lambda (xx) (1+ xx)))))
> >  (funcall zz xx))
> >

I did not see the original post, but /this/ code at least can be
achieved more simply like this:

 (funcall (if whatever #'1- #'1+) xx)

Since flet is mentioned, I'll guess the real problem being solved was
more elaborate, so although the following does no more than the
preceding, I'll include it to demonstrate an important idea, viz,
lexical scope:

(defun bump-or-dump (target whatever)
  (flet ((up-down (tgt)
            (funcall (if whatever #'1- #'1+) tgt)))
    (up-down target)))

The big thing to pick up from this is that 'up-down' need not be passed
'whatever', because it is within the lexical scope of its definition.
From: Kent M Pitman
Subject: Re: conditionals in flet: symbol-function =/= #' ?!
Date: 
Message-ID: <sfwoh3a2ucy.fsf@world.std.com>
Ken Tilton <····@bway.net> writes:

> > On 08 Sep 1997 12:27:37 -0400,
> > SDS  <···········@cctrading.com> wrote:
> > 
> > > The question remains: is there a way to flet a local function conditionally?
> > >What I will be doing for now is:
> > >(let ((zz (if whatever #'(lambda (xx) (1- xx)) #'(lambda (xx) (1+ xx)))))
> > >  (funcall zz xx))

SDS, I think what you're asking for (if you'll pardon the subtle
difference in how I use the words) is not to conditionally flet
something (that is, not to create a local lexical contour in which a
name might or might not have become bound, but rather to
unconditionally flet something to a dynamically chosen value.  Sorry,
but the answer is no, there is not a way.  I'm not sure the reason is
principled--I think it's just that there's been little call for it
over the years.  It's not a horrible idea in principle, but really so
few people have asked for it in practice that it's just been
traditionally left out.

> I did not see the original post, but /this/ code at least can be
> achieved more simply like this:
>  (funcall (if whatever #'1- #'1+) xx)
> [...or...]
>   (flet ((up-down (tgt)
>             (funcall (if whatever #'1- #'1+) tgt)))
>     (up-down target)))

Ken, I think the thing he wants to do (and not an unreasonable thing)
is to make the decision once-and-for all.  Imagine the up-down being in a
(dotimes (i 10000) ...) and you'll see 10,000 extra conditionals of
(if whatever ...) being needlessly done when one on the outside would have
sufficed.  [Yes, a sufficiently clever compiler might help.  Don't hold your
breath, though.]  The issue is not just one of dynamic optimization, btw,
and therefore not just one to be left for a compiler.  The fact is that it's
useful to know that in a (dotimes (i 10000) ...) the function is always 
uniformly ascending or descending--something with an IF like you look
at least gives the reader of the code the sense that it might climb and
fall.  Indeed, in certain situations, if WHATEVER were dynamically changing,
you'd actually have do 
 (let ((whatever0 whatever))
   (flet ((up-down (tgt) (funcall (if whatever0 ...) ...))) ...)  ...)
in order to avoid this function being sensitive to it changing, while
SDS's (let ((zz (if whatever #'(...) #'(...)))) ...) would avoid that
need since it would be done with the conditional before the body of the
LET was done.

Seems to me that the more general missing item here is not a new binding
form, but the inability to (setf (function ...) ...) and affect a local
binding contour.  Just as Scheme implementations often define 
 (labels ((a (x) ...) (b (y) ...)) ...)
as
 (let (a b) (set! a (lambda (x) ...)) (set! b (lambda (y) ...)))
so, too, one could define 
 (defmacro fbind ((fvar val) &body forms)
   (let ((temp (gensym "TEMP")))
     `(let ((,temp ,val))
        (flet ((,fvar ()))
          (setf #',fvar ,temp)
          ,@forms))))
I'd feel much more comfortable extending the language initially just to add
(setf #'foo ...) rather than extending the language to add something as obscure
as fbind (or whatever you'd want to call it).  The fact that we only provide
(setf (symbol-function ...) ...) right now, so you can only assign global function
cells, really bugs me and is a much more commonly complained-about problem.