On Sun, Sep 25, 2016 at 3:34 AM, William G Hatch <will...@hatch.uno> wrote:
> First of all, I really didn't mean any offense.  I think the at-reader
> and my nestable string delimiters are trying to solve slightly
> different problems, and I didn't really convey that well.  I didn't
> mean for it to be "Eli bait".  Let me explain my use case a little,
> and maybe my earlier mail will seem less baiting in the context I had
> intended, albeit poorly communicated.

To be clear, no offense taken -- I'm only considering the technical
reasons to want yet another string delimiter and the technical aspects
of what you get.  "Eli bait" is not because I take it personally, it's
just because I spent a ton of time thinking about such problems, and I'd
hate to see people fall into the expected traps when following
"traditional" solutions, not seeing how the @-syntax already provides a
nice solution.  (I suspected that you'd fall into them, and later in
this email you indeed do...)


> So I really do just mean that the string delimiters themselves nest --
> IE it balances them so that the string doesn't necessarily end once it
> hits an ending delimiter.  So yes, any two characters will do for the
> job.  That in itself is something that I've wanted independent of
> anything else, so for me that was a good enough reason to make this,
> and is something that I'll use it for, to avoid things like \", which
> have always irked me (whether or not it's reasonable that that should
> bother me).

Note that the scribble syntax starts with that as a basic feature.  That
is, if you replace {}s with something else like «», then inside a quoted
context @«...» any matching «»s are ignored.


> Basically, I want to have a macro that will be fully in charge of
> determining the meaning of the string, and I want to be able to use
> the same reader functions in the macro that I use in the #lang.

Same here: this is one of the uses cases I described many times for the
scribble syntax: start with a macro that uses a parser to parse the
whole thing, then refine by making it parse just one form and start
besting @-forms, and eventually get to a point when you have a new #lang
implementation.


> But to use the same read-syntax function that my language uses, I need
> a port to run it on.  To make this port, I really just need a string
> with no pre-read syntax objects inside it.  So in this case I don't
> want the top-level reader of whatever #lang I'm in to look in the
> string, I just want the macro to be able to use read-syntax on the
> full string.

Yes, and you can do all of that with just a string, which you can still
get from an @-form -- just throw a syntax error if it's not all strings.
And with just that you get the *benefit* of ignoring indentation which
makes it possible to use your syntax in a sane way.


> If the middle of the string has already been read into syntax objects,
> my reader functions would be much more complicated to write (IE I'd
> have to figure out how to deal with the port ending in the middle of a
> parenthesised expression or something, then use a pre-read syntax
> object, then jump back into reading the next section that remained a
> string while conveying whatever context I was in in the last string
> segment...).

Right -- that's what I mentioned as "throw a syntax error" above.  But
it would be a good idea to think about why it's a syntax error, which
would in most cases get you closer to something that is a composable
language.


> And the string splitting, which is as you've shown quite helpful in
> many cases, would in this case simply be something that I would have
> to undo, which as you point out would be a bit of a waste.

What I view as a waste is not just undoing the indentation elimination
-- it's the idea of a form where you want indentation to matter at the
semantic runtime level.  To clarify, my opinion is that

    (foo bar
         baz)

and

                     (foo bar
                          baz)

should be the same.  @-expressions follow that; (traditional)
here-strings do not.  Because here-strings do not follow that, you end
up writing ugly code like

                     (foo #<<FOO
    blah
    FOO
                          baz)

which is a mess that might make your readers' eyes bleed.  The usual
shell-way-out is to just use it in a context that is insensitive for
spaces so you end up writing

                     (foo #<<FOO
                            blah
    FOO
                          baz)

and hope that `foo` will overlook the spaces that are all still there.


> So I see the difference as being that in uses like scribble, the bold
> procedure isn't trying to use a reader on its arguments, and the
> at-reader needs to have split them up and turned the nested
> expressions into s-expressions already for them to have their intended
> meaning.

*Don't* confuse scribble-the-documentation-system with the syntax -- the
syntax is useful for many other cases, and designed to make sense in
other cases.  See my description (specifically section 4, which is very
relevant here), and the scribble/text and scribble/html languages.


> [...]
> ;; So basically the rash macro does exactly the same thing as #lang
> ;; rash, but is embeddable in #lang whatever!

Yes, and you can get the same with any string, and

    (rash "stuff
           in a different
           language")

The next problem is quoting and backslash hell, so you want a better
quotation, and (I'm guessing) you end up with something like

    (rash «stuff
           in a different
           language»)

using @-forms would be a tiny delta for the implementation -- basically
just a string-append (actually, not even a delta since your macro
already allows multiple strings), and the use is more convenient:

    @rash{stuff
          in a different
          language}


> each one can do the reading however it sees fit, as long as at each
> level I can pass an appropriate string to the next level down.

The only tricky bit here is that if you want to deal with only strings
and at the same time maintain a syntax-time parsing of strings, then you
need to do this whole multi-level collapsing as a macro thing, which
means no runtime expressions.


> Maybe the languages have very different views on which characters do
> something special (or specifically should not do something special),
> including flag characters like @ (or any one you choose at the top
> level or a higher level up in the nesting).

Note that the scribble syntax uses "@" by default, but it's easy to
change, as Matthew B. did with pollen.


> For example, something like this could happen:
>
> (define some-output
>  (rash/out
>   «some-query $(first
>                 (python-ish-list-comprehend
>                  «machine for i in machine-list where should-i-query(i)»))
>               $(make-query
>                 «this is a bogus example that I'm really stretching
>                  for, but maybe this is some nice syntax for some
>                  sort of query producing dsl? And maybe it has some
>                  macro in it in whatever its syntax is to
>                  (go-a-level-deeper «in this nonsense ...»)
>                  But importantly, no top-level reader has to know or
>                  care what the syntax here is, nor the rash reader,
>                  nor any reader in between, aside from simply
>                  preserving it as a string, which I can hopefully do
>                  in most any language.»)»))

And here you're falling into the trap I mentioned above.  You're trying
to use "$" as an escape, but, for example, what happens if you want to
escape a single identifier and not an expression?  Anyway, here's the
same thing using the scribble syntax:

    (define some-output
     @rash/out{
       some-query @(first
                    @python-ish-list-comprehend{
                      machine for i in machine-list where should-i-query(i)})
                  @make-query{
                    this is a bogus example that I'm really stretching
                    for, but maybe this is some nice syntax for some
                    sort of query producing dsl? And maybe it has some
                    macro in it in whatever its syntax is to
                    (go-a-level-deeper {in this nonsense ...})
                    But importantly, no top-level reader has to know or
                    care what the syntax here is, nor the rash reader,
                    nor any reader in between, aside from simply
                    preserving it as a string, which I can hopefully do
                    in most any language.}})

Note that at the superficial concrete level what this does is (a)
eliminates the need for some "$" escape character, and (b) reduces the
double-delimiter (foo «...») that you often use into a single delimiter
form of @foo{...}.  This latter point is subtly important: users that
write your version need to be aware of both sexpr syntax and string
syntax and how they combine, whereas users that write my version have a
single delimiter.  This is combined with the fact that "@" means the
same at all level in the scribble syntax -- that simplifies things
further by removing the need for some $-like escape construct for
interpolation.  These two features make it easier to comprehend the new
thing as a new syntax rather than be aware of some places that are
texts, some that are not, and the ways to combine this all in code.

It might help to compare this with JS's "template literals", where the
equivalent of the scribble form:

    @foo{... @bar{... @baz ...} ...}

is possible to write -- it's even not that hard: just replace @X{_} with
"${X(`_`)}" except at the toplevel:

    foo(`... ${bar(`... @{baz} ...`)} ...`)

but given how obfuscated the result is (specifically: you now have three
paired delimiters: {}s for interpolation, ()s for arguments, and ``s for
text), almost nobody will actually write such code.

Note also that in *both* of these cases you need to deal with the
problem of `first` being a Racket runtime binding that gets used at the
syntax level if you want to stick with `rash/out` doing its parsing as a
macro implementation -- that's a problem that is inherently there
regardless of concrete syntax.  But the scribble syntax provides an easy
way to handle this: you just need to define `rash/out` as a function (so
do the parsing at runtime), and the result plays much nicer with any
language it's used in.


> I'm a little hard pressed to come up with examples I haven't thought
> of remotely concretely yet, but it seems to me that it's much easier
> to have these sort of #lang-embedding macros that do their own reading
> if you just have a simple string.

At this point I'm guessing that you'd still not be convinced.  So maybe
phrase this as a challenge: see if you can come up with an actual
example where the scribble syntax won't do what you want, or examples
that you're not sure how the scribble syntax would look like.  Maybe
doing this will lead to further enlightment.  (Feel free to email me
such examples off-list.)


> I'm really sorry if my initial mail came off as offensive or
> aggressive against the at-reader, because I really think it's great.
> It's just that it doesn't seem to be the tool best suited to my
> particular need, [...]

I'm not trying to defend the scrible syntax's honor -- I'm only trying
to show you why it solves your particular needs too...  As a long
postfix comment, the personal angle here is that I've been obsessed with
such problems for a *very* long time.  At some point I've had a system
that I'm guessing would interest you: I've basically made a language
where <<>> would delimit meta-level text to be run and its output used
instead, then I made it so each of these could specify its own language
so something like <<TCL: ...>> would run in a tcl interpreter (it was
before python became popular), and you could nest any number of levels
(using a different language in each).  I've used some shreds of that
years later in mzpp which is a much more simplistic language, and closer
to a traditional template system.  And since you've mentioned changing
the "@" character at every level, I've also implemented something on
that side of the spectrum -- mztext -- where the resulting language is
more tex-like where you can do arbitrary parsing at each nested level
down to changing how "functions" are written and arguments are parsed,
and (just like tex) the result is pretty powerful in what it can do, but
nobody ever needs that complication which makes the whole thing useless
for practical purposes.  The scribble syntax is the last thing I had in
that long list of experiments which finally made sense at all levels,
and was both something that was easy to understand yet flexible to
express any of the complicated needs.

-- 
                   ((x=>x(x))(x=>x(x)))                  Eli Barzilay:
                   http://barzilay.org/                  Maze is Life!

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

Reply via email to