Re: [racket-users] Requiring module beneath top level?

2017-08-18 Thread Jon Zeppieri
On Fri, Aug 18, 2017 at 7:08 PM,   wrote:
>
> Here is an idea of what a plugin registration function could look like:
>
>   (define (load-plugins paths)
> ;; Process one plugin at a time
> (define (load-plugin path)
>   ;; Add the path (or its stem) to the search paths
>   ;; Require the plugin (the plugin should register itself)
>   )
> (vector-map load-plugin paths)
> "Loaded plugins")
>
> The sequence of paths was received from Nvim as a vector, and I map over
> every path, requiring the module/collection. The problem is that I
> cannot use (require (file path)) because the require is not a top- or
> module level. The question is: what can I do instead?

I think you want `dynamic-require`:
[http://docs.racket-lang.org/reference/Module_Names_and_Loading.html?q=dynamic-require#%28def._%28%28quote._~23~25kernel%29._dynamic-require%29%29]

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Matthias Felleisen

> On Aug 18, 2017, at 6:41 PM, Matthew Butterick  wrote:
> 
> 
>> On Aug 18, 2017, at 2:28 AM, Sam Waxman > > wrote:
>> 
>> If I have code like this,
>> 
>> (define-syntax-rule (identity x)
>>   x)
>> 
>> ((identity identity) 1)
>> 
>> Is there a simple way to change this so that ((identity identity) 1) 
>> actually does expand into (identity 1) which expands into 1? I'm guessing 
>> not, but it would certainly be a nice trick if there were.
> 
> 
> You need an "identifier macro", which is a macro that will match the case 
> where the macro name is used in an identifier position. [1] For instance: 
> 
> #lang racket
> (require rackunit)
> 
> (define-syntax (identity stx)
>   (syntax-case stx ()
> [(identity arg) #'(#%app identity arg)]
> [identity (identifier? #'identity) ; guard prevents matching `(identity)`
>  #'(λ (x) x)]))



That is guaranteed to evaluate the expression. What if you really want to 
insert a macro that takes apart/suspends/deletes the outer expression? (A 
2-clause ‘identity’ might appear to be able to do so.) 

The point of “macro expansion won’t re-focus outside of the given expression” 
stands. 

— Matthias





> 
> (check-true (procedure? identity))
> (check-equal? ((identity identity) 1) 1)
> (check-equal? (map identity (range 5)) (range 5))
> 
> 
> 
> 
> [1] 
> http://docs.racket-lang.org/guide/pattern-macros.html?q=identifier%20macro#%28tech._identifier._macro%29
>  
> 
> 
> -- 
> 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 racket-users+unsubscr...@googlegroups.com 
> .
> 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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Requiring module beneath top level?

2017-08-18 Thread hiphish
Hello Racketeers,

A while ago I announced my MessagePack library here and I mentioned that
I was needing it for a client library for the Neovim text editor. Since
then I have been writing this client library and now I'm at a point
where I need help.

Let me first give you some context: Neovim is a fork of Vim which allows
people to write remote plugins in any language. Remote plugins are run
by a separate process which is a client to the Neovim server. Basically
this means I can write Neovim plugin in Racket (given a Racket host) and
call functions written in Racket from Neovim and use them in Neovim
plugins.

For this to work the functions defined in Racket need to tell Neovim
about themselves, they need to register their specifications. Here is
how the process works: Neovim first searches for paths to remote
plugins, in this case the pattern is "rplugin/racket/*" where "rplugin"
is a directory of a Neovim plugin. This means there are many such paths
that all end in "/rplugin/racket/*". Neovim then passes the list of all
these paths on to the Racket client.

The client then has to load or require all these plugins so that they
can register their specifications. I'll try to capture the sequence of
events in a list:

1) Neovim launches
2) It collects a list of all Racket remote plugins, where a remote
   plugin is either a file ending in ".rkt" or a directory
3) Neovim launches a Racket instance as the client
4) Neovim sends a request to Racket with a list of all the plugin paths
5) Racket has to set up the specifications
6) After Racket responds back Neovim asks for the specifications
7) Racket sends back a hash table containing the specifications

Step 5 is the one that is giving me trouble. Here is how the Racket
client is launched:

  racket -eee '(require (file "autoload/host/bootstrap.rkt"))' \
  '(require neovim)' \
  '(start-host)'

The first instructions requires a bootstrapping module which will get
the host ready to receive the requests in step 4 - 7. It works, I have
tested it. In the bootstrapping module I also want to process the
plugins. A remote plugin has to be required so that its side effects are
performed. A declaration in a remote plugin could look something like
this:

  (require neovim/rpc)

  (define (two) 2)
  (register-function! two #:name "Two" #:sync #t)

Ideally both would be wrapped up in a macro, this is just an idea. The
point is that the Racket function foo is not supposed to leave the
module, but the side effect of registering it in a global table must
happen.

Here is an idea of what a plugin registration function could look like:

  (define (load-plugins paths)
;; Process one plugin at a time
(define (load-plugin path)
  ;; Add the path (or its stem) to the search paths
  ;; Require the plugin (the plugin should register itself)
  )
(vector-map load-plugin paths)
"Loaded plugins")

The sequence of paths was received from Nvim as a vector, and I map over
every path, requiring the module/collection. The problem is that I
cannot use (require (file path)) because the require is not a top- or
module level. The question is: what can I do instead? I would like all
the side effects that usually go with "require", but since the
registration happens via RPC request it cannot be at module level. I can
also pass arbitrary arguments to the racket binary, so I don't need to
do all the work in Racket.

I hope this explanation makes it clear what I'm trying to achieve. Of
course if there is a better way of adding a bunch of collections and
modules I am open to that as well.

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Readers and Namespaces

2017-08-18 Thread Matthew Butterick

> On Aug 17, 2017, at 10:11 PM, Alexis King  wrote:
> 
> This is, for
> better or for worse, currently a no-no in Racket — syntax objects
> produced by a #lang’s reader are supposed to only have source locations
> and syntax properties on them, not lexical context.

Supposed to, yes. But AFAIK this is not enforced. If your `read-syntax` 
produces a syntax object with bindings clinging to it, so they remain.


> There are various reasons this can be explained, some historical, others
> technical. One explanation I’ve heard is that valid programs read by
> `read-syntax` are supposed to also be valid programs if read by `read`
> — this means lexical context shouldn’t matter. 

"It's usually not a good idea to have a reader produce syntax objects with 
lexical context. (One reason: binding dependencies are hidden from the 
compilation manager. Another reason: it's easy to trip into a world of 
ambiguous bindings.)" — Matthew Flatt

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Matthew Butterick

> On Aug 18, 2017, at 2:28 AM, Sam Waxman  wrote:
> 
> If I have code like this,
> 
> (define-syntax-rule (identity x)
>   x)
> 
> ((identity identity) 1)
> 
> Is there a simple way to change this so that ((identity identity) 1) actually 
> does expand into (identity 1) which expands into 1? I'm guessing not, but it 
> would certainly be a nice trick if there were.


You need an "identifier macro", which is a macro that will match the case where 
the macro name is used in an identifier position. [1] For instance: 

#lang racket
(require rackunit)

(define-syntax (identity stx)
  (syntax-case stx ()
[(identity arg) #'(#%app identity arg)]
[identity (identifier? #'identity) ; guard prevents matching `(identity)`
 #'(λ (x) x)]))

(check-true (procedure? identity))
(check-equal? ((identity identity) 1) 1)
(check-equal? (map identity (range 5)) (range 5))




[1] 
http://docs.racket-lang.org/guide/pattern-macros.html?q=identifier%20macro#%28tech._identifier._macro%29
 


-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Re: Readers and Namespaces

2017-08-18 Thread Shu-Hung You
If you are implementing a new language, this can be done by delegating
the "=-to-let" work to the macro-expander and let the reader simply
parenthesizing the input into s-expression form. In this approach, we
don't need to worry about being hygienic in the reader since the
actual work is done by the macro expander.

For example, we can make the reader turn the following input

; a-test.rkt
#lang my-let-lang
x = 5;
a = 8;
my-let = 10;
= = a + a;
u = x + my-let + = + = + = + = + =;
printf("u = ~a\n", u);

into some parenthesized form

(module a-test my-let-lang
(= x 5) (= a 8) (= my-let 10) (= = (+ a a))
(= u (+ x my-let = = = = =))
(printf "u = ~a\n" u))

and implement a module-begin macro that turns the parenthesized body
into my-let.

(provide
 (rename-out [new-module-begin #%module-begin]))
(require
 (rename-in racket [#%module-begin racket-module-begin]))

(define-syntax (new-module-begin stx)
  (syntax-parse stx
; parse the s-exp-ized "=" syntax here
[(_ (= x:id e:expr) ... body)
 #'(racket-module-begin
(make-nested-my-let ((x e) ...) body))]))

--Shu-Hung

On Fri, Aug 18, 2017 at 9:21 AM, gfb  wrote:
> Assuming the setup where you make a module syntax object and call 
> strip-context on it, you can add a scope to all the user's identifiers after 
> that so they're not considered “above” any of the language's identifiers. 
> Make a function to do the marking:
>
> (define marker (make-syntax-introducer #true))
>
> Then walk the syntax object tree and replace each user identifier ‘id’ with 
> (marker id 'add). Depending on your parsing setup, you could have a specific 
> non-terminal for places a user identifier occurs and have a very generic 
> syntax tree walker that looks for the non-terminal and adds the mark to the 
> identifier.
>
> If you make a second marker for all other identifiers you encounter, then 
> none of the user's identifiers will be “under” the language's bindings, and 
> error messages will be better if the user accidentally uses (without binding) 
> one of the language's names.
>
> --
> 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 racket-users+unsubscr...@googlegroups.com.
> 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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Re: Readers and Namespaces

2017-08-18 Thread gfb
Assuming the setup where you make a module syntax object and call strip-context 
on it, you can add a scope to all the user's identifiers after that so they're 
not considered “above” any of the language's identifiers. Make a function to do 
the marking:

(define marker (make-syntax-introducer #true))

Then walk the syntax object tree and replace each user identifier ‘id’ with 
(marker id 'add). Depending on your parsing setup, you could have a specific 
non-terminal for places a user identifier occurs and have a very generic syntax 
tree walker that looks for the non-terminal and adds the mark to the identifier.

If you make a second marker for all other identifiers you encounter, then none 
of the user's identifiers will be “under” the language's bindings, and error 
messages will be better if the user accidentally uses (without binding) one of 
the language's names.

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Sam Waxman
On Friday, August 18, 2017 at 10:14:10 AM UTC-4, Matthias Felleisen wrote:
> On Aug 18, 2017, at 9:44 AM, Sam Waxman  wrote:
> 
> On Friday, August 18, 2017 at 9:31:33 AM UTC-4, Matthias Felleisen wrote:
> On Aug 18, 2017, at 5:28 AM, Sam Waxman  wrote:
> 
> If I have code like this,
> 
> (define-syntax-rule (identity x)
>  x)
> 
> ((identity identity) 1)
> 
> At phase 1, the (identity identity) will get transformed into identity. As 
> macros expand outside in, however, this won't turn into (identity 1) like a 
> function would, it will try expanding the identity macro all by itself 
> without any "arguments" and give a bad syntax error.
> 
> Is there a simple way to change this so that ((identity identity) 1) actually 
> does expand into (identity 1) which expands into 1? I'm guessing not, but it 
> would certainly be a nice trick if there were.
> 
> 
> The explanation of the error is wrong. Run it in DrRacket and see which 
> identity it highlights for the error message. [I’d rather have you come up 
> with a proper explanation yourself. That way you will remember.]
> 
> It highlights the second. I don't think I misspoke above, but please correct 
> me if I'm wrong.
> 
> ((identity identity) 1) first starts by receiving the entire s-expression. 
> Then it tries expanding the first thing in that s-expression which is 
> (identity identity)
> 
> To do this, it goes to the identity rule, which states that identity is 
> allowed to expand if it has exactly one argument. In this case it does, so 
> #'(identity identity) becomes #'identity. Then instead of moving back to the 
> first s-expression and moving onto 1, because macro-expansion goes outside-in 
> (and more importantly, I suppose, depth first), the macro expander then tries 
> to expand #'identity. This is where the bad syntax error comes from because 
> the rule for identity says it must have an argument, but this identity is 
> getting expanded with no arguments.
> 
> 
> Sorry I misread your words. Yes, the expander re-expands the output of a 
> transformer (see below) and thus id is mentioned w/o arguments so the 
> compile-time call fails (or in old expanders produces a free var). 
> 
> 
> 
> 
> ;; Expression  = S-expression over Symbols only 
> ;; Table       = [Listof [List Symbol Transformer]]
> ;; Transformer = [Expression -> Expression]
> 
> ;; Expression Table -> Expression 
> (define (expander exp syntax-table)
>   (displayln exp)
>   (match exp
>     [(? number? n) n]
>     [(? symbol? s) s]
>     [`(,(? symbol? token) ,t)
>      (cond
>        [(in-domain? token syntax-table)
>         (expander ((retrieve token syntax-table) exp) syntax-table)]
>        [else (error 'expander "not a macro: ~e" token)])]
>     [`(lambda (,x) exp-body) `(lamnbda (,x) (expander exp-body))]
>     [`(,f ,a) `(,(expander f syntax-table) ,(expander a syntax-table))]
>     [else (error 'expander "bad syntax: ~e" exp)]))

Thanks, it's nice to see it written out like that!

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Matthias Felleisen

> On Aug 18, 2017, at 9:44 AM, Sam Waxman  wrote:
> 
> On Friday, August 18, 2017 at 9:31:33 AM UTC-4, Matthias Felleisen wrote:
>>> On Aug 18, 2017, at 5:28 AM, Sam Waxman  wrote:
>>> 
>>> If I have code like this,
>>> 
>>> (define-syntax-rule (identity x)
>>>  x)
>>> 
>>> ((identity identity) 1)
>>> 
>>> At phase 1, the (identity identity) will get transformed into identity. As 
>>> macros expand outside in, however, this won't turn into (identity 1) like a 
>>> function would, it will try expanding the identity macro all by itself 
>>> without any "arguments" and give a bad syntax error.
>>> 
>>> Is there a simple way to change this so that ((identity identity) 1) 
>>> actually does expand into (identity 1) which expands into 1? I'm guessing 
>>> not, but it would certainly be a nice trick if there were.
>> 
>> 
>> The explanation of the error is wrong. Run it in DrRacket and see which 
>> identity it highlights for the error message. [I’d rather have you come up 
>> with a proper explanation yourself. That way you will remember.]
> 
> It highlights the second. I don't think I misspoke above, but please correct 
> me if I'm wrong.
> 
> ((identity identity) 1) first starts by receiving the entire s-expression. 
> Then it tries expanding the first thing in that s-expression which is 
> (identity identity)
> 
> To do this, it goes to the identity rule, which states that identity is 
> allowed to expand if it has exactly one argument. In this case it does, so 
> #'(identity identity) becomes #'identity. Then instead of moving back to the 
> first s-expression and moving onto 1, because macro-expansion goes outside-in 
> (and more importantly, I suppose, depth first), the macro expander then tries 
> to expand #'identity. This is where the bad syntax error comes from because 
> the rule for identity says it must have an argument, but this identity is 
> getting expanded with no arguments.

Sorry I misread your words. Yes, the expander re-expands the output of a 
transformer (see below) and thus id is mentioned w/o arguments so the 
compile-time call fails (or in old expanders produces a free var). 


;; Expression  = S-expression over Symbols only 
;; Table   = [Listof [List Symbol Transformer]]
;; Transformer = [Expression -> Expression]

;; Expression Table -> Expression 
(define (expander exp syntax-table)
  (displayln exp)
  (match exp
[(? number? n) n]
[(? symbol? s) s]
[`(,(? symbol? token) ,t)
 (cond
   [(in-domain? token syntax-table)
(expander ((retrieve token syntax-table) exp) syntax-table)]
   [else (error 'expander "not a macro: ~e" token)])]
[`(lambda (,x) exp-body) `(lamnbda (,x) (expander exp-body))]
[`(,f ,a) `(,(expander f syntax-table) ,(expander a syntax-table))]
[else (error 'expander "bad syntax: ~e" exp)]))

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Sam Waxman
On Friday, August 18, 2017 at 9:31:33 AM UTC-4, Matthias Felleisen wrote:
> > On Aug 18, 2017, at 5:28 AM, Sam Waxman  wrote:
> > 
> > If I have code like this,
> > 
> > (define-syntax-rule (identity x)
> >   x)
> > 
> > ((identity identity) 1)
> > 
> > At phase 1, the (identity identity) will get transformed into identity. As 
> > macros expand outside in, however, this won't turn into (identity 1) like a 
> > function would, it will try expanding the identity macro all by itself 
> > without any "arguments" and give a bad syntax error.
> > 
> > Is there a simple way to change this so that ((identity identity) 1) 
> > actually does expand into (identity 1) which expands into 1? I'm guessing 
> > not, but it would certainly be a nice trick if there were.
> 
> 
> The explanation of the error is wrong. Run it in DrRacket and see which 
> identity it highlights for the error message. [I’d rather have you come up 
> with a proper explanation yourself. That way you will remember.]

It highlights the second. I don't think I misspoke above, but please correct me 
if I'm wrong.

((identity identity) 1) first starts by receiving the entire s-expression. Then 
it tries expanding the first thing in that s-expression which is (identity 
identity)

To do this, it goes to the identity rule, which states that identity is allowed 
to expand if it has exactly one argument. In this case it does, so #'(identity 
identity) becomes #'identity. Then instead of moving back to the first 
s-expression and moving onto 1, because macro-expansion goes outside-in (and 
more importantly, I suppose, depth first), the macro expander then tries to 
expand #'identity. This is where the bad syntax error comes from because the 
rule for identity says it must have an argument, but this identity is getting 
expanded with no arguments.

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Matthias Felleisen

> On Aug 18, 2017, at 5:28 AM, Sam Waxman  wrote:
> 
> If I have code like this,
> 
> (define-syntax-rule (identity x)
>   x)
> 
> ((identity identity) 1)
> 
> At phase 1, the (identity identity) will get transformed into identity. As 
> macros expand outside in, however, this won't turn into (identity 1) like a 
> function would, it will try expanding the identity macro all by itself 
> without any "arguments" and give a bad syntax error.
> 
> Is there a simple way to change this so that ((identity identity) 1) actually 
> does expand into (identity 1) which expands into 1? I'm guessing not, but it 
> would certainly be a nice trick if there were.


The explanation of the error is wrong. Run it in DrRacket and see which 
identity it highlights for the error message. [I’d rather have you come up with 
a proper explanation yourself. That way you will remember.] 

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Seeking a graphviz like, diagramming language for Racket

2017-08-18 Thread Andrew Gwozdziewycz
Hi folks,

I've been using graphviz for years for basic network architecture
diagrams and things, mostly to avoid answering the question of "which
annoying tool should I use?" Graphviz has limitations for the type of
stuff I use it for, but I settle for it anyway, since it's a lot less
frustrating to use a language for laying out relationships than
clicking and dragging lines connecting things, in an agreed upon
diagramming tool.

Has anyone started work (or finished work, or even somewhere in
between?) on a diagramming language that might be, or even eventually
will be a suitable replacement for performing these types of tasks?

And if not, does anyone have suggestions for getting started with
layout drawing algorithms suitable for such a thing? I'm fairly sure
that the pict language will do the heavy lifting work for actually
drawing on a canvas, and simple layout techniques probably would go
along way, but getting to know the field a bit might be useful...

Cheers,

Andrew
-- 
http://www.apgwoz.com

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Sam Waxman
If I have code like this,

(define-syntax-rule (identity x)
   x)

((identity identity) 1)

At phase 1, the (identity identity) will get transformed into identity. As 
macros expand outside in, however, this won't turn into (identity 1) like a 
function would, it will try expanding the identity macro all by itself without 
any "arguments" and give a bad syntax error.

Is there a simple way to change this so that ((identity identity) 1) actually 
does expand into (identity 1) which expands into 1? I'm guessing not, but it 
would certainly be a nice trick if there were.

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Can a macro "return" a macro without expanding it?

2017-08-18 Thread Sam Waxman
If I have code like this,


(define-syntax-rule (identity x)

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.