[plt-scheme] Identifying at-exp string literals

From: Dave Gurnell (d.j.gurnell at gmail.com)
Date: Tue Sep 22 08:47:02 EDT 2009

Thanks for your replies, Eli and Matthew. I'll reply to both below:

Matthew Flatt wrote:
> To me, distinguishing those cases goes against the spirit of @- 
> notation. I think it's a great benefit that S-exprs and @-notation  
> are interchangeable.

I understand this point of view. I realise my suggestion is a bit  
dodgy, but I thought I'd ask for education's sake.

Given both of your thoughts on this matter, I will probably create two  
xml macros as Matthew suggested.

Eli Barzilay wrote:
> [...] Using the scribble properties as above is therefore somewhat  
> similar to using the 'paren-shape property to make [...] be  
> something other than function application, [...] In both cases it's  
> cute that you can do so -- and might be appropriate for a DSL where  
> it's expected to have some non-schemish syntax, but it doesn't  
> really work well for a library to do the same.

Absolutely. FWIW my intentions were for a DSL for designers. Basically  
I want to create a version of Jay's web-server/templates language that  
I can use with existing code written using Mirrors. In other words, I  
want designers to be able to write this in one module:

<html>
<body>
<div class="some-awesome-layout">
@(go-scheme)
</div>
</body>
</html>

while I write this in another module:

(define (go-scheme)
   (xml (p "Here's the application bit.")))

Of course, there's no reason that this can't be done with the two- 
macro approach described above so I'll go with that.

> I don't know what the typical use patterns for the mirrors library  
> is, but I don't think that I'd use it... I don't know what the  
> typical use patterns for the mirrors library is, but I don't think  
> that I'd use it...  It looks to me like it would suffer from the  
> same problem that xexprs suffer -- where the implicit quoting means  
> that you can make errors that will not be caught until you get to  
> the client of the generated xml.

Welllllll... I see your point, but unquote-related bugs are relatively  
difficult to introduce:

   - single identifiers aren't valid XML so you can't miss an unquote  
in this situation:

     (let ([x 1]) (xml "The number is " x)) ; compile error
     (let ([x 1]) (xml "The number is " ,x)) ; okay

     although admittedly you can still do this:

     (xml "The number is " (add 1 2 3))

   - "xml" isn't valid within an "xml" block so you can't double-quote:

     (xml (xml "Hi")) ; compile error
     (XML (xml "Hi")) ; okay: <xml>Hi</xml>

   - there're fewer uses of unquote-splicing, and the code fails much  
earlier than with xexprs:

     (xml (ul ,(xml (li "Item 1") (li "Item 2")))) ; okay
     (xml (ul ,@(list (xml (li "Item 1")) (xml (li "Item 2")))) ; okay
     (xml (ul ,@(xml (li "Item 1") (li "Item 2")))) ; immediate  
runtime error

> My "recent" solution for this (I've only been playing with it for  
> about 10 years...) is to define all of the (x)html tags as functions  
> that generate tags by the same name.

This is quite nice, and it's something I did think of. You're  
basically using Scheme to partially validate your XML for you, and as  
you point out later on it makes you think of all the other checks you  
can introduce by annotating your tag procedures with extra information.

The biggest problem with this approach for me is that it introduces a  
class of bugs where you push a tag out of scope by introducing a  
variable with the same name:

   (let ([p 0.5])
     (p "The probability of something happening is: " p))

I guess you can prefix tags, but I think that would become tiresome  
pretty quickly.

Perhaps there's some middle ground between these approaches,  
registering tags and XML namespaces in some way and then declaring  
them for use later:

   (xml #:ns xhtml-1.0 (p "Hi there"))

>  Because [tags are] functions, you can add more functions that  
> behave as an alias to some existing tag (so you can get your own  
> layer of semantic-oriented functions on top of the limited set of  
> html tags)...

Yes - this is good. I've started to play with this by introducing  
define-xml-expander and define-javascript-expander, but your approach  
is lots better than mine. It's definitely harder to play with syntax  
than runtime values. I suppose with the advent of syntax/parse I might  
get some more mileage from my approach.

> You can obviously bake more xml knowledge in -- from contracts or  
> types that will enforce dtd requirements all the way up to a macro  
> that will read a dtd, parse it, and generate the tag definitions  
> with their contracts/types.

Actually this is something I really need to add to Mirrors, and it  
goes even further than the officially quoted rules of hich tags can go  
where. For example, Mirrors contains custom little hard coded rules  
that prevent your writing HTML like:

   <div/>
   <script/>

and so on. AFAIK these are technically speaking okay, but they break  
in pretty much all browsers.

Anyway, all these rules are hard coded. Having some richer tag  
definition language where the user can specify them would definitely  
help.

Anyway, this is all good discussion. Thanks again for your comments!

Cheers,

-- Dave


Posted on the users mailing list.