Re: [racket-users] beautiful racket: trying a first dsl of my own

2017-12-29 Thread Matthias Felleisen

> On Dec 29, 2017, at 10:41 PM, Matthew Butterick  wrote:
> 
> 
> The `define-macro` used in the `br/quicklang` language is not the same as the 
> one in Racket's "legacy macro" library. [1] Rather, it's a simplified version 
> of `syntax-parse`. [2] 
> 

Mea culpa. Then may I recommend to teach syntax annotations from the get-go? I 
think it helps people who work thru individual stages of macros. It’s part of 
the design recipe to get the call to macros right (examples, tests). Then 
someone like Robert can discover that the language reader needs to warp certain 
identifiers in quotes. 

-- 
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] beautiful racket: trying a first dsl of my own

2017-12-29 Thread Matthew Butterick

> On Dec 29, 2017, at 3:31 PM, Robert Girault  > wrote:
> 
> (define-macro (prelude/connect-to HOST PORT)
>   #'(begin
>   (require racket/tcp)
>   (require racket/port)
>   (define-values (input-port output-port)
> (tcp-connect HOST PORT
> 
> This doesn't work because I get the error message
> 
>   www.google.com : unbound identifier in module in: 
> www.google.com 
> 
> This must be because www.google.com  is not a string. 
>  I don't know how to turn into a string and this must mean I'm very confused. 
>  What should my macro do so I'd get the desired expansion?

The issue is that when `read-syntax` encounters

www.google.com

in your source, it treats it as an identifier, not a literal string. (This 
identifier hasn't been defined, hence the "unbound identifier" error.) 

But you want it to behave as a string, so you can pass it to `tcp-connect`. So 
you have two choices. 

1) You can fix the problem in your source, by instead writing 

"www.google.com"

which will cause `read-syntax` to treat it as a literal string, rather than an 
identifier.

2) You can fix the problem in your macro, by converting the would-be identifier 
to a string in the output of the macro:

(define-macro (prelude/connect-to HOST PORT)
  #'(begin
  (require racket/tcp)
  (require racket/port)
  (define-values (input-port output-port)
(tcp-connect (symbol->string 'HOST) PORT


The notation 'HOST rather than HOST makes the identifier into a symbol, and 
then `symbol->string` finishes the job. 

If you like to be lenient with input, you could also do this, which will work 
with either www.google.com or "www.google.com":

(define-macro (prelude/connect-to HOST PORT)
  #'(begin
  (require racket/tcp)
  (require racket/port)
  (define-values (input-port output-port)
(tcp-connect (format "~a" 'HOST) PORT



> On Dec 29, 2017, at 7:31 AM, Matthias Felleisen  wrote:
> 
> I prefer to teach syntax transformers using define-syntax and syntax-parse so 
> that you can say 
> 
>  (define-syntax (prelude/connect-to stx)
> (syntax-parse stx 
>   [(_ HOST:str PORT:nat) #’(  . . HOST . . PORT ..)])) 
> 
> That way misuses of a ‘macro’ are caught immediately and you get sensible 
> error messages. 
> 
> [I just went thru this with freshmen in the spare weeks after Thanksgiving 
> and it worked like a charm.
> I don’t understand the appeal of define-macro.]


The `define-macro` used in the `br/quicklang` language is not the same as the 
one in Racket's "legacy macro" library. [1] Rather, it's a simplified version 
of `syntax-parse`. [2] 


[1] 
https://docs.racket-lang.org/compatibility/defmacro.html?q=define-macro#%28form._%28%28lib._compatibility%2Fdefmacro..rkt%29._define-macro%29%29
 


[2] 
https://beautifulracket.com/appendix/from-br-to-racket-base.html#macro-definitions
 



-- 
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] beautiful racket: trying a first dsl of my own

2017-12-29 Thread Matthias Felleisen

When you use the macro with 

   (prelude/connect-to www.google.com  80)

you are asking it to place the identifier www.google.com 
 wherever HOST shows up in the right-hand-side of the 
macro definition. 

I prefer to teach syntax transformers using define-syntax and syntax-parse so 
that you can say 

 (define-syntax (prelude/connect-to stx)
(syntax-parse stx 
  [(_ HOST:str PORT:nat) #’(  . . HOST . . PORT ..)])) 

That way misuses of a ‘macro’ are caught immediately and you get sensible error 
messages. 

[I just went thru this with freshmen in the spare weeks after Thanksgiving and 
it worked like a charm.
I don’t understand the appeal of define-macro.]





> On Dec 29, 2017, at 3:31 PM, Robert Girault  
> wrote:
> 
> I thought I had understood mostly everything I learned in Beautiful Racket.  
> But I must be very confused as a whole.  I gave myself the task of 
> translating something like this 
> 
> #lang tcp
> connect www.google.com  80
> text GET / HTTP/1.1
> text Host: www.google.com 
> text
> read-until-eof
> exit
> 
> into something like this
> 
> #lang racket/base
> (require racket/tcp)
> (require racket/port)
> 
> (define host "www.google.com ")
> (define port 80)
> 
> (define-values (input-port output-port)
>   (tcp-connect host port))
> 
> (define (sendline ln)
>   (display ln (current-output-port))
>   (display ln output-port)
>   (flush-output output-port))
> 
> (displayln (format "Connected @ ~a on port ~a." host port))
> 
> (sendline "GET / HTTP/1.1\r\n")
> (sendline (format "Host: ~a\r\n\r\n" host))
> 
> (write (port->lines input-port))
> (exit)
> 
> I've achived a bit.  I translated that dsl-source into this.
> 
> '(prelude/connect-to www.google.com  80)
> '(send-line GET / HTTP/1.1)
> '(send-line Host: www.google.com )
> '(send-line)
> '(loop read until eof)
> '(exit)
> 
> Now I don't know how to proceed.  I think I must define a macro 
> prelude/connect-to.  For example
> 
>   (prelude/connect-to www.google.com  80)
> 
> should expand to 
> 
>   (begin
>   (require racket/tcp)
>   (require racket/port)
>   (define-values (input-port output-port)
> (tcp-connect "www.google.com " 80
> 
> Here's what I tried.  (See my full code at http://pasterack.org/pastes/16943 
> )
> 
> (define-macro (prelude/connect-to HOST PORT)
>   #'(begin
>   (require racket/tcp)
>   (require racket/port)
>   (define-values (input-port output-port)
> (tcp-connect HOST PORT
> 
> This doesn't work because I get the error message
> 
>   www.google.com : unbound identifier in module in: 
> www.google.com 
> 
> This must be because www.google.com  is not a string. 
>  I don't know how to turn into a string and this must mean I'm very confused. 
>  What should my macro do so I'd get the desired expansion?
> 
> -- 
> 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.