[racket] Dynamically Bind Functions

From: Stephen Bloch (bloch at adelphi.edu)
Date: Sat Dec 22 07:59:42 EST 2012

On Dec 22, 2012, at 4:23 AM, Cristian Esquivias wrote:

> Is this the general practice? It looks rather cumbersome and difficult to plan for.
> 
> Is there anything that would prevent me from having to wrap functions in make-parameter calls? Something like Clojure's binding special form (if you're familiar with it).
> 
> - Cristian
> 
> On Dec 21, 2012 6:45 PM, "David Van Horn" <dvanhorn at ccs.neu.edu> wrote:
> On 12/21/12 9:41 PM, Cristian Esquivias wrote:
> I'm trying to replace a function with another using parameterize.
> 
> For example, when I try:
> 
> (define (add2 n)
>    (add1 (add1 n)))
> 
> (parameterize ([add1 (λ [n] (+ n 2))])
>    (add2 2))

Part of the reason you can't do this is that Racket, like Scheme but unlike some old versions of Lisp, uses static scoping: whatever definition of "add1" is in effect at the time you define "add2" is the definition that will be used, regardless of what you do to "add1" later.  This makes programs enormously easier to think about, since you can tell what a program does simply by reading its definition, without having to allow for any arbitrary definition somebody might make later.

If you want "add1" to be redefinable later, you have to tell Racket about that in advance, using "make-parameter".

Another option would be to "set!" the function that you're trying to redefine.  However, if the function in question was defined in a different module, you probably won't be able to do that unless it was "set!" at least once in that module; as I understand it, Racket recognizes things that are never mutated in their defining module and optimizes them to be immutable forever.

If you just want to redefine "add1" in a specific scope, you can use "let", which shadows an existing definition:
(let ((add1 (lambda (n) (+ n 2)))) (add1 3))   ; produces 5

If you want to do this for a definition, you could try
(define (add2 m)
   (let ((add1 (lambda (n) (+ n 2))))  (add1 (add1 m))))
(add2 3) ; produces 7
or, if you prefer to do the "let"ting at define-time,
(define add2
   (let ((add1 (lambda (n) (+ n 2))))
      (lambda (m) (add1 (add1 m)))))
(add2 3) ; produces 7


Stephen Bloch
sbloch at adelphi.edu

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20121222/590cc83c/attachment-0001.html>

Posted on the users mailing list.