[racket] at-exp: is there any way to make it turn @list{A @"string" escape} into (list "A " "string" " escape") ?

From: Alexander D. Knauth (alexander at knauth.org)
Date: Mon Dec 29 18:01:33 EST 2014

On Dec 29, 2014, at 4:53 PM, Eli Barzilay <eli at barzilay.org> wrote:

> On Mon, Dec 29, 2014 at 3:03 AM, Alexander D. Knauth
> <alexander at knauth.org> wrote:
>>> ... this is generally a bad idea.  What do you do when you want the
>>> @"..." escapes?  How do you find out which parts of the input are
>>> arguments and which are part of the format string?
>> 
>> For that, I have a helper function that looks at the first argument,
>> sees how many arguments it would take as a format string, and then
>> takes the next n arguments as the place-fillers for that format
>> string, then recursively looks at the next format string.
> 
> Well, what I meant is that it's a bad idea conceptually, in a way that
> can lead to actual bugs.  For example, if you do exacly that, then
> you'll probably have an unexpected result with something like:
> 
>    @my-error['x]{blah blah
>                    blah blah ~v
>                    @|"something”|}

Yes this would be bad, but part of the whole point of this is that I wanted to
be able to specify the place-fillers on the same line as the place-holders while
still having multi-line format strings, so I would never do this, and if I put this
into a package or something, I would be sure to specify that the place-fillers
should always be on the same line as the place-fillers.  

But to help this I just added a parameter that would tell it whether or not to
warn you if one of the place-fillers was the “\n” string.  
(the default is to warn you)

> And you can probably also run into surprises when some argument
> evaluates to a string that has ~s in it.

No, because it never tries to parse an argument as a format string, because
it knows the number of arguments there should be from the previous format
string.

>> I wanted to be able to format things that can't be converted to text and
>> back properly, so for example in DrRacket this works:
>> @my-printf{the plt logo: ~v@(plt-logo #:height 50)}
>> But this doesn't:
>> (display @string-append{the plt logo: @~v[(plt-logo #:height 50)]})
>> There is a similar-ish thing with syntax-objects and mixed numbers (and
>> there are probably more) in DrRacket.
> 
> You can still do that nicely:
> 
>    (define (my-print . stuff) (for-each display stuff))
>    @my-print{blah @some-value blah}

The reason I don’t want to do this (or your next suggestion) is that I want to
be able to show a string argument as a string value, with the quotes
(unless I specify ~a as the place-holder).

> that, or some variant that uses `display' for strings and `print' for
> other values:
> 
>    (define (my-print . stuff)
>      (for ([thing (in-list stuff)])
>        ((if (string? thing) display print) thing)))
> 
> or even ignore voids
> 
>    (define (my-print . stuff)
>      (for ([thing (in-list stuff)] #:unless (void? thing))
>        ((if (string? thing) display print) thing)))
> 
> so you can do something like:
> 
>    @my-print{blah @some-value blah @write[another-value] blah}

This is interesting, and solves most of the same “problems," but it doesn’t
extend to things like error.

> The bottom line is that I'm avoiding the strange mixture of a format
> string and mixed string/values ("interpolation"), which makes it easier
> to use.

I understand that, but the processing of the format strings first to find out
how many arguments they should take should make sure that they are
never confused with one another, right?  
(assuming the place-fillers are on the same line as the place-holders)

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



Posted on the users mailing list.