Re: [racket-users] splicing conditional results in the surrounding block?

2016-02-13 Thread Eli Barzilay
On Fri, Feb 12, 2016 at 10:45 PM, Nota Poin  wrote:
>
> at-exp really is a fascinating language,

It's not a language in itself, it's a meta-language, which modifies the
actual language with the @-form syntax.

> but if a (flatten) isn't any more computationally expensive, you can
> just splice all the lists at the end and use the regular racket
> language. Either way would work fine, I suspect.

This sounds confused.  The purpose of the at-exp language is just to
make it easier to write code with a lot of text, which is what you do.

The scribble/text language that was mentioned is based on the same
@-form syntax, and it adds the functionality of outputting strings (and
other primitive values), with lists being scanned recursively (so it's
essentially flattening everything), and it outputs nothing for #f and
void, which makes it easy to embed `and`s and `when`s without the usual
gymnastics involved in splicing the results back into a single-level
list.

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


Re: [racket-users] splicing conditional results in the surrounding block?

2016-02-12 Thread Nota Poin
On Thursday, February 11, 2016 at 12:29:04 PM UTC, Neil Van Dyke wrote:
> http://www.neilvandyke.org/racket-html-template/

This does almost exactly what I was thinking about! Looking at the code makes 
me go cross-eyed, but if you (expand-once #'(html-template ...)) enough, it 
turns the SXML tree structure into a linear sequence of (write-bytes) 
statements. It would definitely be possible to instead generate a linear 
sequence of strings, that could be cached and then possibly written with one 
single (write-bytes).

Certainly not worth the trouble, but possible. And very fascinating!

-- 
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] splicing conditional results in the surrounding block?

2016-02-12 Thread Neil Van Dyke

Nota Poin wrote on 02/12/2016 10:41 PM:


This does almost exactly what I was thinking about! Looking at the code makes 
me go cross-eyed,


Yes, I recommend not looking at the code.  IIRC, the code is a little 
icky for a few reasons:
1. It was initially not as clear as I like, just because of the nature 
of how it worked, and because I was figuring it out.
2. We didn't yet have submodules, which are a godsend for working with 
Racket's phases, especially how I prefer to work, with one file per 
package, with inline docs
3. I did a big reworking to facilitate some optimizations for using this 
with the Racket Web Server specifically, which complicated things and 
left a lot of placeholders for further changes.  But then all my 
packages stalled around the time of the new package system work, so it's 
in a half-finished state, and without a cleanup pass (though it should 
work).


Neil V.

--
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] splicing conditional results in the surrounding block?

2016-02-12 Thread Nota Poin
On Friday, February 12, 2016 at 1:26:05 AM UTC, Matthew Butterick wrote:
> Of course, you can also use the `at-exp` metalanguage from Scribble to 
> simplify text-heavy constructions like these, with variables interpolated 
> into strings:

> #lang at-exp racket
> 
> (define (query condA condB (limit #f) (offset #f))
>   @~a{SELECT something FROM table WHERE @condA AND @condB @(if limit
>@~a{LIMIT 
> @limit @(if offset
>   
>@~a{OFFSET @offset}
>   
>"")}
>"")})

I could also do this:

(define (query condA condB (limit #f) (offset #f))
  (flatten
(list "SELECT something FROM table WHERE "
condA
" AND "
condB
(if limit
(list "LIMIT " limit
  (if offset
  (list "OFFSET " offset)
  '()))
'(

at-exp really is a fascinating language, but if a (flatten) isn't any more 
computationally expensive, you can just splice all the lists at the end and use 
the regular racket language. Either way would work fine, I suspect.

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


[racket-users] splicing conditional results in the surrounding block?

2016-02-11 Thread Nota Poin
I run into this problem a lot whenever I'm generating some text. I'll be making 
what amounts to a sequence of strings being appended, and do something like 
this:

(apply string-append 
  (list "" something ""))

Compared to un-parsing a representation of a document tree every single time, 
simplifying document production down to a bunch of string concatenations is 
pretty efficient. The problem happens when I introduce conditionals, like this:

(list
  ""
  (if prev
(list "Prev")
'())
  (if next
(list "Next")
'())
  "")

Now I no longer have a sequence of strings, but instead a nested list of 
strings. Then I usually call (apply string-append (flatten list-of-strings)) 
and don't worry about it, but it'd be even cooler if I could proactively 
flatten it.

(if prev
  (if next
(list 
  ""
  "Prev"
  "next"
  "")
(list 
  ""
  "Prev"
  ""))
  (if next
  (list 
  ""
  "next"
  "")
  (list 
  ""
  "")))

Obviously that's horrible code, since I don't want to type the surrounding 
stuff for every possible logic pathway in my code. But it'd be relatively 
simple to concatenate whatever the result is! I guess what I'm asking is how 
would I take code like this:

(list 
  ""
  (splicing-if prev
(splicing-list "Prev")
nada)
  (splicing-if next
(splicing-list "Next")
nada)
  "")

...and have the result inherently be a flat list of strings? Not a complex tree 
that I then have to walk with (flatten), but genuinely just a list of strings?

Something with (reset) and (shift) maybe? Something with (and-let)? To make 
this happen, would I have to instrument the conditionals like (if)? Would I 
have to instrument the (list) forms that they result in?

Obviously if my conditionals produce simple strings it's easy:

(list 
  "things: "
  (if thing1
thing1
"")
  (if (and thing1 thing2)
 " and "
 "")
  (if thing2
thing2
""))

Even that is kind of cludgy though, because the "" fallthrough results in lists 
like (list "things: " thing1 "" "") instead of the ideal: (list "things: " 
thing1)

One possible solution is to use mutable variables and shared state. (ugh)

(write "")
(when prev
(write "Prev"))
(when next
(write "Next"))
(write "")

Another thing I've tried is concatenations of concatenations:

(apply string-append 
  ""
  (if prev
(string-append "Prev")
"")
  (if next
(string-append "Next")
"")
  "")

That of course scatters fallthrough "" strings in the calculation, and since it 
calls string-append multiple times, the implementation can't exactly allocate 
the result all at once, and must spend more time fooling around with memory. 
Creating strings, only to destroy them as soon as they've been appended to the 
larger string.

But there's no way I've ever been able to figure to produce generated text that 
is just a flat list of strings, if I ever want to have conditional decisions 
about what to go in that list.

-- 
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] splicing conditional results in the surrounding block?

2016-02-11 Thread Nota Poin
On Thursday, February 11, 2016 at 9:08:33 AM UTC-8, Matthew Butterick wrote:

> I'm supposing you know that Racket has at least two native representations 
> (X-expression and SXML) for HTML-like structures, so hacking HTML tags by 
> hand is unnecessary.

Yes, thank you for mentioning them. I was actually thinking of starting with 
SXML, but then turning it into a list of string fragments (with spaces left for 
the dynamically generated parts) as a simplification step once I've figured out 
where everything goes. But there are other languages besides HTML this is 
relevant for.

(define (query condA condB (limit #f) (offset #f))
  (list "SELECT something FROM table WHERE "
condA
" AND "
condB
(if limit
(list "LIMIT " limit
  (if offset
  (list "OFFSET " offset)
  '()))
'(

for instance.

> But if you must, there's a #lang for that:

I'll look at scribble/text, but I don't think a whole new language is necessary 
just to factor if-statements inside out. I suspect it does a (flatten) 
operation though, after having constructed a complex tree, since this problem 
seems like a difficult one, and (flatten) really isn't all that much trouble. I 
was just curious if it was possible to do this, but if I had to get 
scribble/text ready to release to the masses I'd just throw a (flatten) in 
there to splice the lists.

> Enjoy.

No problem!

-- 
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] splicing conditional results in the surrounding block?

2016-02-11 Thread Neil Van Dyke

Nota Poin wrote on 02/11/2016 04:48 AM:

But there's no way I've ever been able to figure to produce generated text that 
is just a flat list of strings, if I ever want to have conditional decisions 
about what to go in that list.


You might like `quasiquote` and `unquote-splicing`:

`("a"
  "b"
  ,@(if (= 2 (+ 1 1))
`("p"
  "q")
`("x"
  "y"))
  "c"
  "d")

;;=> ("a" "b" "p" "q" "c" "d")

BTW, for HTML-writing, maintaining HTML markup in string literals gets 
to be a headache, and also tends to have bugs.  I would use my 
`html-writing` or `html-template` package.

http://www.neilvandyke.org/racket-html-writing/#%28part._.Writing_.H.T.M.L%29
http://www.neilvandyke.org/racket-html-template/

Neil V.

--
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] splicing conditional results in the surrounding block?

2016-02-11 Thread Matthew Butterick
> Yes, thank you for mentioning them. I was actually thinking of starting with 
> SXML, but then turning it into a list of string fragments (with spaces left 
> for the dynamically generated parts) as a simplification step once I've 
> figured out where everything goes. But there are other languages besides HTML 
> this is relevant for.
> 
> (define (query condA condB (limit #f) (offset #f))
>   (list "SELECT something FROM table WHERE "
>   condA
>   " AND "
>   condB
>   (if limit
>   (list "LIMIT " limit
> (if offset
> (list "OFFSET " offset)
> '()))
>   '(
> 
> for instance.

Of course, you can also use the `at-exp` metalanguage from Scribble to simplify 
text-heavy constructions like these, with variables interpolated into strings:

#lang at-exp racket

(define (query condA condB (limit #f) (offset #f))
  @~a{SELECT something FROM table WHERE @condA AND @condB @(if limit
   @~a{LIMIT @limit 
@(if offset

 @~a{OFFSET @offset}

 "")}
   "")})

-- 
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] splicing conditional results in the surrounding block?

2016-02-11 Thread Matthew Butterick
> Nota Poin wrote on 02/11/2016 04:48 AM:
>> But there's no way I've ever been able to figure to produce generated text 
>> that is just a flat list of strings, if I ever want to have conditional 
>> decisions about what to go in that list.

I'm supposing you know that Racket has at least two native representations 
(X-expression and SXML) for HTML-like structures, so hacking HTML tags by hand 
is unnecessary.

But if you must, there's a #lang for that:

Here's the literal translation of your code in `scribble/text`, which 
automatically splices all `list`s it finds: 

#lang scribble/text

@(define prev "foo")
@(define next "bar")

@(if prev
 @(if next
  @list{
Prev
next
}
  @list{
Prev
})
 @(if next
  @list{
next
}
  @list{
}))


A more compact refactoring of same:

#lang scribble/text

@(define prev "foo")
@(define next "bar")


@(if prev @list{Prev} "")
@(if next @list{next} "")



And here's the refactored version in `pollen/pre`, which is based on 
`scribble/text`. It does not splice `list`s by default, but it has a splicing 
operator `@`, and also a `when/splice` that lets you do single-branch 
conditionals.

#lang pollen/pre

◊(define prev "foo")
◊(define next "bar")


◊when/splice[prev]{Prev}
◊when/splice[next]{next}



Here's an HTML-free variant in `pollen/markup` that produces an equivalent 
X-expression (which can be easily converted to HTML):

#lang pollen/markup

◊(define prev "foo")
◊(define next "bar")

◊p[#:id "navigation"]{
◊when/splice[prev]{◊a[#:href ◊prev]{Prev}}
◊when/splice[next]{◊a[#:href ◊next]{next}}}


Finally, we can throw in a macro for fun:

#lang pollen/markup

◊(define prev "foo")
◊(define next "bar")

◊(define-syntax-rule (cond-nav id text ...)
   ◊when/splice[id]{◊a[#:href ◊id text ...]})

◊p[#:id "navigation"]{
◊cond-nav[prev]{Prev}
◊cond-nav[next]{next}}

Enjoy.

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