Re: [racket-users] code reflection

2017-10-18 Thread Matthew Butterick

> On Oct 18, 2017, at 12:53 AM, Konrad Hinsen  
> wrote:
> 
> I needed to remove the first
> element and add it in front of the others. On a plain list, I could do
> this half asleep. But with the list wrapped in a syntax object, even
> after considerable thought I am not sure what the best approach would
> be.
> 
> Unwrap (syntax->datum), apply list functions, rewrap? The resulting code
> is not very readable, the wrapping stuff being much more visible than
> the code that does the real work. Pattern match against (a b c ...)? OK
> for this particular case, but not for the next case I knew I would
> have to deal with.

The fandango associated with switching between syntaxed lists and lists of 
syntax can indeed be wearying. But this seems less like an issue intrinsic to 
`syntax-parse` and more like the irreducible complexity of living in a world 
where syntax objects are distinct things. (See also strings vs. paths and 
strings vs. symbols). 

If your goal is readable code, why not add some sugar?

#lang racket/base
(require (prefix-in rb: racket/base)
 rackunit)

(define (length x)
  (cond
[(and (syntax? x) (syntax->list x)) => length]
[else (rb:length x)]))  

(check-equal? (length '(1 2 3)) 3)
(check-equal? (length #'(1 2 3)) 3)
(check-exn exn:fail:contract? (λ () (length 42)))
(check-exn exn:fail:contract? (λ () (length #'42)))


More broadly, it feels like there's plenty of room for new macro-definition and 
syntax-processing forms that suit different ergonomic needs: readability, 
automatic error messages, debugging, and so on. Interesting question why more 
of them don't exist. For `#lang br` I made a set that were designed for 
simplicity and readability. [1] 

[1] 
http://docs.racket-lang.org/br/index.html?q=br%2Fdefine#%28form._%28%28lib._br%2Fdefine..rkt%29._define-macro%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] Multiple namespaces in Racket

2017-10-18 Thread Matthias Felleisen

> On Oct 18, 2017, at 4:04 PM, Alexis King  wrote:
> 
> 
>@(examples
>   (: (Tuple 42 "hello") (#,t:Tuple Integer String)))
> 
> That’s because the `examples` form doesn’t allow escaping, which makes
> sense, since there would be no way to know what `#,t:Tuple` should mean
> when performing sandboxed evaluation. It’s theoretically possible to use
> eval:alts to manually provide a version of the program for typesetting
> and a version for evaluation:
> 
>@(examples
>   (eval:alts (: (Tuple 42 "hello") (#,t:Tuple Integer String))
>  (: (Tuple 42 "hello") (Tuple Integer String
> 
> ...but this sort of defeats the purpose of having examples that are
> automatically typeset.


What I imagined was that you’d define @h-examples, which would 
translate the former into the latter. — Matthias

-- 
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] Multiple namespaces in Racket

2017-10-18 Thread Alexis King
> On Oct 18, 2017, at 8:09 AM, Matthias Felleisen 
> wrote:
> 
> Wouldn’t something like this work for Hackett?

I don’t think so. Perhaps it would be better illustrated with an
example.

First, consider the Hackett definition of, say, the `Maybe` type:

(data (Maybe a) (Just a) Nothing)

This defines two runtime bindings with the following types:

Just : (forall [a] {a -> (Maybe a)})
Nothing : (forall [a] (Maybe a))

It also defines a type-level binding, `Maybe`, which is in the type
namespace.

Now consider the Hackett definition of the 2-tuple type:

(data (Tuple a b) (Tuple a b))

This defines two bindings, one in the value namespace and one in the
type namespace. Troublingly, they are both named `Tuple`.

To work around this duplication, these two bindings are exported as
`Tuple` and `#%hackett-type:Tuple`. When imported, the latter is
unprefixed and injected into the type namespace. But what about
Scribble? I might like to write the following:

@(examples
   (: (Tuple 42 "hello") (Tuple Integer String)))

This will evaluate properly, and it will typeset like this:

> (: (Tuple 42 "hello") (Tuple Integer String)))
: (Tuple Integer String)
(Tuple 42 "hello")

But what about the links? The first `Tuple` should link to the value
constructor (which is actually called `Tuple`), and the second `Tuple`
should link to the type constructor (actually called
`#%hackett-type:Tuple`). It won’t, however, because Scribble will link
them both to the value constructor.

I could do what you describe and create separate bindings for the two:

@(module values-for-label racket
   (require (for-label (only-in hackett Tuple))
scribble/manual)
   (provide Tuple)
   (define Tuple @racket[Tuple]))

@(module types-for-label racket
   (require (for-label (only-in hackett
[#%hackett-type:Tuple Tuple]))
scribble/manual)
   (provide t:Tuple)
   (define t:Tuple @racket[Tuple]))

Now I can use these two different bindings in a paragraph by writing
`@Tuple` or `@t:Tuple`, and they will both typeset as “Tuple”. But this
still doesn’t solve the problem of scribble/example, since the following
doesn’t work:

@(examples
   (: (Tuple 42 "hello") (#,t:Tuple Integer String)))

That’s because the `examples` form doesn’t allow escaping, which makes
sense, since there would be no way to know what `#,t:Tuple` should mean
when performing sandboxed evaluation. It’s theoretically possible to use
eval:alts to manually provide a version of the program for typesetting
and a version for evaluation:

@(examples
   (eval:alts (: (Tuple 42 "hello") (#,t:Tuple Integer String))
  (: (Tuple 42 "hello") (Tuple Integer String

...but this sort of defeats the purpose of having examples that are
automatically typeset.

A solution I alluded to in my previous email would be to provide a
notion of “eval transformers” that work like the existing “element
transformers” that scribble/racket provides. That way, `t:Tuple` could
be both an element transformer and an eval transformer that do the right
thing in each context. Otherwise, I’m not sure if there’s a different
solution (at least without dramatically changing how the documentation
is put together).

-- 
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] Multiple namespaces in Racket

2017-10-18 Thread Matthias Felleisen

> On Oct 17, 2017, at 11:02 PM, Alexis King  wrote:
> 
>It’s obvious that  should be in the value namespace and
>  should be in the type namespace. When expanding code, this
> makes things easy, but Scribble doesn’t expand its code examples,
> it merely looks at the lexical information of the source syntax.
> If a `Tuple` type has a data constructor that is also named
> `Tuple`, there is no way for Scribble to know which binding to use.


In HtDP/2e, I need different references to the same identifier in one 
paragraph. 
Here is the fully spelled out mechanism: 

> @(module racket-ormap racket/base 
>(provide racket-ormap)
>(require (for-label racket) (only-in scribble/manual racket))
>(define (racket-ormap) @racket[ormap]))
> 
> @(module isl-ormap racket/base
>(provide isl-ormap)
>(require (for-label lang/htdp-intermediate) (only-in scribble/manual 
> racket))
>(define (isl-ormap) @racket[ormap]))
> 
> @(require (submod "." racket-ormap) (submod "." isl-ormap))

Wouldn’t something like this work for Hackett? 

I understand that Type might just be defined in the preceding 
evaluator example. But that’s a different issue, namely, that 
we often need to accumulate the definitions across several different 
example and interaction items. If you combined those two issues with 
something like the above trick, would you be able to get the bindings
done properly? 

-- 
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] code reflection

2017-10-18 Thread Matthias Felleisen


Please search my post for ‘hygiene’. I didn’t mention the word. Off — Matthias



> On Oct 18, 2017, at 3:53 AM, Konrad Hinsen  wrote:
> 
> Matthias,
> 
>> It’s quite doable but I think this misses the point
> 
> I see that I haven't made my point clearly enough (if at all). I
> certainly don't want to go back to unhygienic macros without error
> checking.
> 
> What I do want to go back to is doing simple manipulations of syntax
> objects using familiar list functions. A simple example I encountered
> recently is probably the best illustration.
> 
> Somewhere in a syntax class, I had a syntax object which was checked to
> be a list with at least three elements. I needed to remove the first
> element and add it in front of the others. On a plain list, I could do
> this half asleep. But with the list wrapped in a syntax object, even
> after considerable thought I am not sure what the best approach would
> be.
> 
> Unwrap (syntax->datum), apply list functions, rewrap? The resulting code
> is not very readable, the wrapping stuff being much more visible than
> the code that does the real work. Pattern match against (a b c ...)? OK
> for this particular case, but not for the next case I knew I would
> have to deal with. Read through the extensive documentation of
> syntax-parse, hoping to find the perfect solution?  Not a very exciting
> prospect.
> 
> Note that hygiene is not an issue here. In 80% of my macro code, hygiene
> is not an issue, nor is error checking. For the other 20%, syntax-parse
> is just fine.
> 
>> I think what we’re really seeing here is that backwards compatibility
>> sometimes smothers elegant solutions.  I firmly believe that in this
>> case we should simply throw out syntax-rules and syntax-case
> 
> A very good idea. At least throw it out from the tutorials and all
> example code. Point people to syntax-parse right from the start.  Keep
> syntax-case to avoid breaking code, but don't advertise it any more.
> 
>> Other Matthew has written a book from a particular angle. It’s
>> beautiful but clearly leaves an unsatisfied need behind. 
> 
> I'd say the unsatisfied need is in between the tutorial for beginners
> and the reference documentation. Something that helps finding a good
> solution for a specific problem, for someone who knows the basics of
> syntax-parse. It could be a curated collection of case studies.
> 
> Konrad.

-- 
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] code reflection

2017-10-18 Thread Neil Van Dyke
This old post explains my rationale: 
http://lists.racket-lang.org/users/archive/2014-March/061899.html


(Update: The only reason I didn't also kill off `syntax-case` at the 
time was that the only documentation for `syntax-parse` was imposing, 
and people could find gentler tutorials for `syntax-case`.  But, with 
gentler documentation for `syntax-parse`, then `syntax-case` can go 
retire to a beach house.)


--
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] code reflection

2017-10-18 Thread Neil Van Dyke

Konrad Hinsen wrote on 10/18/2017 03:53 AM:

I think what we’re really seeing here is that backwards compatibility
sometimes smothers elegant solutions.  I firmly believe that in this
case we should simply throw out syntax-rules and syntax-case

A very good idea. At least throw it out from the tutorials and all
example code. Point people to syntax-parse right from the start.  Keep
syntax-case to avoid breaking code, but don't advertise it any more.


I agree fully with continuing to support `syntax-rules` and 
`syntax-case` in Racket (keep them working well, and keep them in the 
reference manual), but teaching only `syntax-parse` in any 
guides/tutorials/textbooks.  Teaching the multiple forms with different 
syntax just adds confusion and friction.


I'd just mention `syntax-rules` and `syntax-case` once in the document, 
saying why they're not being taught, in case anyone wonders.  And I'd 
put notes in the reference manual bits about those two, encouraging 
people to go to `syntax-parse` instead.


Suggestion: if you decide to teach only `syntax-parse`, you might want 
to include using it without the help of things like syntax 
classes, not teach always using syntax classes.  Otherwise, there would 
be a lot of occasions when people can rapidly whip out a reasonable 
`syntax-rules` example that looks a lot better than a full-features 
`syntax-parse` one.  I'm thinking that "idiomatic `syntax-parse`" should 
also include "lightweight" uses of its features -- somewhat like how 
people often prefer to use `racket/base` rather than Typed Racket.


--
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] code reflection

2017-10-18 Thread Konrad Hinsen
Matthias,

> It’s quite doable but I think this misses the point

I see that I haven't made my point clearly enough (if at all). I
certainly don't want to go back to unhygienic macros without error
checking.

What I do want to go back to is doing simple manipulations of syntax
objects using familiar list functions. A simple example I encountered
recently is probably the best illustration.

Somewhere in a syntax class, I had a syntax object which was checked to
be a list with at least three elements. I needed to remove the first
element and add it in front of the others. On a plain list, I could do
this half asleep. But with the list wrapped in a syntax object, even
after considerable thought I am not sure what the best approach would
be.

Unwrap (syntax->datum), apply list functions, rewrap? The resulting code
is not very readable, the wrapping stuff being much more visible than
the code that does the real work. Pattern match against (a b c ...)? OK
for this particular case, but not for the next case I knew I would
have to deal with. Read through the extensive documentation of
syntax-parse, hoping to find the perfect solution?  Not a very exciting
prospect.

Note that hygiene is not an issue here. In 80% of my macro code, hygiene
is not an issue, nor is error checking. For the other 20%, syntax-parse
is just fine.

> I think what we’re really seeing here is that backwards compatibility
> sometimes smothers elegant solutions.  I firmly believe that in this
> case we should simply throw out syntax-rules and syntax-case

A very good idea. At least throw it out from the tutorials and all
example code. Point people to syntax-parse right from the start.  Keep
syntax-case to avoid breaking code, but don't advertise it any more.

> Other Matthew has written a book from a particular angle. It’s
> beautiful but clearly leaves an unsatisfied need behind. 

I'd say the unsatisfied need is in between the tutorial for beginners
and the reference documentation. Something that helps finding a good
solution for a specific problem, for someone who knows the basics of
syntax-parse. It could be a curated collection of case studies.

Konrad.

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