Here's something in the ballpark.

#lang racket

(define-namespace-anchor nsa)
(define ns (namespace-anchor->namespace nsa))

(let ((xyz 1))
  (for ((name '(x y z)))
    (namespace-set-variable-value! name (lambda () (displayln (format "~a:
~a" name xyz)) (set! xyz (add1 xyz))) #f ns)))

(eval '(x) ns)

On Tue, Aug 9, 2016 at 5:20 PM, 'John Clements' via Racket Users <
[email protected]> wrote:

>
> > 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.
>

-- 
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.

Reply via email to