> On Aug 9, 2016, at 4:46 PM, David Storrs <[email protected]> wrote:
> 
> In Perl it's possible to generate main-namespace functions like so:
> 
> perl -E 'my $z = 1; for (qw/foo bar baz/) {my $x = $_; *$_ = sub{ say "$x: ", 
> $z++ }};  foo(); bar(); baz();'
> 
> This outputs:
> foo: 1
> bar: 2
> baz: 3
> 
> 
> Note that it is generating top-level subroutines that can be called from 
> elsewhere in the program (including other modules) and that those subroutines 
> close over existing lexical variables.
> 
> 
> I tried to do this in Racket and haven't been able to figure it out:
> 
> First attempt, only partial solution:
> $ racket
> -> (for ((name '(x y z))) (define name (lambda () (displayln "foo"))))
> 
> ; /Applications/Racket_v6.3/collects/racket/private/for.rkt:1487:62: begin
> ;   (possibly implicit): no expression after a sequence of internal 
> definitions
> ;   in: (begin (define name (lambda () (displayln "foo"))))
> ; [,bt for context]
> 
> 
> I found 'eval', but that doesn't close over lexical variables 
> (https://docs.racket-lang.org/guide/eval.html: "The eval function cannot see 
> local bindings"):
> 
> $ racket
> Welcome to Racket v6.3.
> -> (let ((xyz 1)) (for ((name '(x y z))) (eval `(define ,name (lambda () 
> (displayln (format "~a: ~a" ,name ,xyz) (set! xyz (add1 xyz))))))))
> 
> -> (x)
> (x)
> ; xyz: undefined;
> ;  cannot reference undefined identifier
> ; [,bt for context]
> 
> 
> What have I not found?

Racket is essentially a lexically scoped language. That is: it should be 
possible to look at a piece of code and figure out where the binding for a 
given variable is. It does have a dynamic binding mechanism, but the names that 
are bound dynamically … can be determined lexically.

This might seem to prevent the kind of code that you’re talking about, but 
Racket compensates for this with an extraordinarily flexible macro system, and 
a very permissive notion of what exactly constitutes “compile-time.” It’s 
certainly possible to dynamically generate a piece of code using macros. Once 
generated, though, this piece of code is going to behave dependably.

How does this affect your particular example? Well, it’s extremely easy to 
write a macro that does what you describe:

#lang racket

(define-syntax makefuns
  (syntax-rules ()
    [(_ name ...)
     (begin (define name (lambda () (displayln "foo")))
            ...)]))

(makefuns x y z)

(x)

(y)

(z)



Does this solve your problem? If not, why not? It’s going to depend a lot on 
what exactly you want to do.


Hope this helps, apologies for telling you anything that you already knew.

John


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Attachment: signature.asc
Description: PGP signature

Reply via email to