Delaying string evaluation

Hi,

I would like to partially expand a string and then further expand it
later on when more information is available. I am currently using
string interpolation with a reeval method suggested by Bill Kelly.

class String
  def reeval(b = TOPLEVEL_BINDING)
    eval("<<END_REEVAL\n" + self + "\nEND_REEVAL\n", b).chomp!
  end
end

This lets me do stuff like this:

expanded = "one"
delayed = "two"

s = "#{expanded} \#{delayed}" # => "one #{delayed}"
s = s.reeval(binding) # => "one two"

As a more complex example, this is a string I wish to partially expand:

options = [ 10, 20, 30, 40, 50 ]

combobox =<<"END"
...
#{options.map {|n|
%{<option value="#{n}"\#{thread_threshold == n ? ' SELECTED' : ''}>#{n} comments</option>}
}.join("\n")
}
...
END

The idea is to create the combobox and then later insert the SELECTED
part, when I know the value of thread_threshold. Unfortunately, the
above partial expansion is:

<option value="10"#{thread_threshold == n ? ' SELECTED' : ''}>10 comments</option>
<option value="20"#{thread_threshold == n ? ' SELECTED' : ''}>20 comments</option>
<option value="30"#{thread_threshold == n ? ' SELECTED' : ''}>30 comments</option>
<option value="40"#{thread_threshold == n ? ' SELECTED' : ''}>40 comments</option>
<option value="50"#{thread_threshold == n ? ' SELECTED' : ''}>50 comments</option>

This would have been great, except that I have all these values for
'n' that have been left out of the expressions that I want to evaluate
afterwards. That is, I want the partial expansion to be this:

<option value="10"#{thread_threshold == 10 ? ' SELECTED' : ''}>10 comments</option>
<option value="20"#{thread_threshold == 20 ? ' SELECTED' : ''}>20 comments</option>
<option value="30"#{thread_threshold == 30 ? ' SELECTED' : ''}>30 comments</option>
<option value="40"#{thread_threshold == 40 ? ' SELECTED' : ''}>40 comments</option>
<option value="50"#{thread_threshold == 50 ? ' SELECTED' : ''}>50 comments</option>

and later when I reeval the string:

thread_threshold = 50
combobox.reeval(binding)

the result should be:

<option value="10">10 comments</option>
<option value="20">20 comments</option>
<option value="30">30 comments</option>
<option value="40">40 comments</option>
<option value="50" SELECTED>50 comments</option>

Anyone have any ideas for how I can get a correct partial expansion?

I have a lambda/closure feeling about how this should work, but I
can't quite see the solution in the context of strings.

Thanks,
Navin.

Hi,

I would like to partially expand a string and then further expand it
later on when more information is available. I am currently using
string interpolation with a reeval method suggested by Bill Kelly.

is sprintf (aka %) unable to fulfill your requirements?

class String
  def reeval(b = TOPLEVEL_BINDING)
    eval("<<END_REEVAL\n" + self + "\nEND_REEVAL\n", b).chomp!
  end
end

This lets me do stuff like this:

expanded = "one"
delayed = "two"

s = "#{expanded} \#{delayed}" # => "one #{delayed}"
s = s.reeval(binding) # => "one two"

s = "#{expanded} %s"
s = s % delayed

As a more complex example, this is a string I wish to partially expand:

options = [ 10, 20, 30, 40, 50 ]

combobox =<<"END"
...
#{options.map {|n|
%{<option value="#{n}"\#{thread_threshold == n ? ' SELECTED' : ''}>#{n} comments</option>}
}.join("\n")
}
...
END

combobox = <<END
...
%s
...
END

opts = options.map { |n| "<option value=\"#{n}\"%s>#{n} comments</

" }.join "\n"

combobox = combobox % opts

and later when I reeval the string:

thread_threshold = 50
combobox.reeval(binding)

the result should be:

<option value="10">10 comments</option>
<option value="20">20 comments</option>
<option value="30">30 comments</option>
<option value="40">40 comments</option>
<option value="50" SELECTED>50 comments</option>

Hrm, maybe not...

How about:

opts = options.map { |n| "<option value=\"#{n}\"SEL_#{n}>#{n} comments</option>" }.join "\n"

combobox = combobox % opts

combobox.gsub!(/SEL_(\d+)/) do
   thread_threshold == $1.to_i ? ' SELECTED' : ''
end

Anyone have any ideas for how I can get a correct partial expansion?

I have a lambda/closure feeling about how this should work, but I
can't quite see the solution in the context of strings.

I think the reeval thing is the wrong way to go about it. I find it much more useful to use a library that generates HTML programatically or from a template than to try fancy substitution tricks (unless its really small). Eventually you end up with either a template language or programatic HTML generation in the end.

···

On 16 Jul 2005, at 01:23, Navindra Umanee wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Navindra Umanee schrieb:

I would like to partially expand a string and then further expand it
later on when more information is available. (...)

combobox =<<"END"
...
#{options.map {|n|
%{<option value="#{n}"\#{thread_threshold == n ? ' SELECTED' : ''}>#{n} comments</option>}

                                                >
                                               #{n}

}.join("\n")
}
...
END

(...)

Change the second "n" to "#{n}", just like the others.

Regards,
Pit

why not make up a mini interpolator?

   ~ > cat a.rb
   class String
     def expand! h = {}
       gsub!(%r/:\w+/o){|k| h[k.delete(':').intern] || k}
     end
     def expand(*a, &b)
       dup.expand!(*a, &b); self
     end
   end

   s = '<:expanded> - <:delayed>'

   s.expand! :expanded => 'one'
   puts s

   s.expand! :delayed => 'two'
   puts s

   ~ > ruby a.rb
   <one> - <:delayed>
   <one> - <two>

cheers.

-a

···

On Sat, 16 Jul 2005, Navindra Umanee wrote:

Hi,

I would like to partially expand a string and then further expand it
later on when more information is available. I am currently using
string interpolation with a reeval method suggested by Bill Kelly.

class String
def reeval(b = TOPLEVEL_BINDING)
   eval("<<END_REEVAL\n" + self + "\nEND_REEVAL\n", b).chomp!
end
end

This lets me do stuff like this:

expanded = "one"
delayed = "two"

s = "#{expanded} \#{delayed}" # => "one #{delayed}"
s = s.reeval(binding) # => "one two"

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Eric Hodel <drbrain@segment7.net> writes:

combobox = combobox % opts

Just wanted to point out that you can shorten that:

   combobox %= opts

···

--
Daniel Brockman <daniel@brockman.se>

Hah! I had no idea that would work.

Thanks,
Navin.

···

Pit Capitain <pit@capitain.de> wrote:

Change the second "n" to "#{n}", just like the others.

> I would like to partially expand a string and then further expand it
> later on when more information is available. I am currently using
> string interpolation with a reeval method suggested by Bill Kelly.

is sprintf (aka %) unable to fulfill your requirements?

I am aware that there are solutions such as these, but I keep finding
the string interpolation solution to be the most attractive/elegant
one as a general solution.

s = "#{expanded} %s"
s = s % delayed

If there are multiple occurrences of delayed, you have to repeatedly
apply it in the second line in proper order, and if you have any
independent occurrence of % in the string, I'm not entirely sure how
to escape it. This solution isn't very symmetric either.

I think the reeval thing is the wrong way to go about it.

What do you have against reeval? I have been trying to convince
myself there are better solutions, but after looking I keep coming
back to it. It just seems more natural or at least it works as a
general solution.

I find it much more useful to use a library that generates HTML
programatically

You mean like the CGI.* stuff or Amrita? CGI.* stuff looks very
painful and verbose to use, and Amrita, while it looks interesting in
simple cases, gives me the feeling that I will have to use too many
contortions to get it to work the way I want.

I mean constructs like <p id="var"></p> in Amrita look brilliant.
But then you get to stuff like <a id='a2' amrita:type='link'>Amrita2</a>
which starts to look more ugly and as you get to complex conditional
code generation it gets worse and worse.

It just seems easier to "just do it the way I want" in Ruby instead of
artificially constraining myself in Amrita, since I have the feeling I
would have to resort to Ruby programming in addition to Amrita just to
get the sort of effects I want anyway.

It could well be I'm not giving Amrita its due. I have been
considering re-implementing my stuff in it, but at the depressing
prospect, I thought I'd try making the string interpolation template
stuff more elegant (which it obviously isn't yet).

or from a template than to try fancy substitution tricks (unless its
really small). Eventually you end up with either a template language
or programatic HTML generation in the end.

I agree that this is what I will end up with -- I'm just trying to get
it to work in the most elegant way I can.

What do you use?

Cheers,
Navin.

···

Eric Hodel <drbrain@segment7.net> wrote:

Interesting.

As a general solution I'm not sure it's what I want.
I am also expanding complex objects (e.g #{posting.attribute}) and
with your custom interpolator I would end up either having to copy
information around (e.g. :posting_attribute => posting.attribute) or
using it with the regular delayed string interpolation strategy anyway.

Thanks,
Navin.

···

Ara.T.Howard <Ara.T.Howard@noaa.gov> wrote:

why not make up a mini interpolator?

   ~ > cat a.rb
   class String
     def expand! h = {}
       gsub!(%r/:\w+/o){|k| h[k.delete(':').intern] || k}
     end
     def expand(*a, &b)
       dup.expand!(*a, &b); self
     end
   end

Are you aware that Ruby ships with a templating language in its standard library?

irb(main):001:0> require "erb"
=> true
irb(main):002:0> expand, delay = "Expanded!", "Delayed!"
=> ["Expanded!", "Delayed!"]
irb(main):003:0> template = "#{expand} <%= delay %>"
=> "Expanded! <%= delay %>"
irb(main):004:0> ERB.new(template).result(binding)
=> "Expanded! Delayed!"

James Edward Gray II

···

On Jul 16, 2005, at 10:34 AM, Navindra Umanee wrote:

Eventually you end up with either a template language
or programatic HTML generation in the end.

I agree that this is what I will end up with -- I'm just trying to get
it to work in the most elegant way I can.

s = "#{expanded} %s"
s = s % delayed

If there are multiple occurrences of delayed, you have to repeatedly
apply it in the second line in proper order, and if you have any
independent occurrence of % in the string, I'm not entirely sure how
to escape it. This solution isn't very symmetric either.

Yes :frowning:

I think the reeval thing is the wrong way to go about it.

What do you have against reeval? I have been trying to convince
myself there are better solutions, but after looking I keep coming
back to it. It just seems more natural or at least it works as a
general solution.

I find \#{} hard to read because I have to think about it. (It also feels very funny.)

or from a template than to try fancy substitution tricks (unless its
really small). Eventually you end up with either a template language
or programatic HTML generation in the end.

I agree that this is what I will end up with -- I'm just trying to get
it to work in the most elegant way I can.

What do you use?

I've never used Amrita, and I've found CGI lacking. Rails' use of erb is very nice, I've used (and extended) RDoc's template system and ported one from Seaside which was CGI-like, but felt better.

The biggest problem with CGI is that it does everything you want out-of-the-box in an ugly way, and nobody seems to wrap up fragments into methods that act as templates. CGI used this way would be much more palatable.

See also http://raa.ruby-lang.org/search.rhtml?search=template

Its so easy to write a proper one that everybody does it! It seems to be the second Ruby project everyone uses.

···

On 16 Jul 2005, at 08:34, Navindra Umanee wrote:

Eric Hodel <drbrain@segment7.net> wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Yes I know of ERB. I am not sure what the advantage of using a
different syntax is, when I can simply use the same Ruby syntax but
escape it when necessary.

<%= delay %> is at least as verbose as \#{delay}.

What advantage do you see to using a new syntax instead of just Ruby?

Cheers,
Navin.

···

James Edward Gray II <james@grayproductions.net> wrote:

Are you aware that Ruby ships with a templating language in its
standard library?

> apply it in the second line in proper order, and if you have any
> independent occurrence of % in the string, I'm not entirely sure how
> to escape it.

(Side note: Using %% is enough to escape it)

I find \#{} hard to read because I have to think about it. (It also
feels very funny.)

Yeah, that's true. It's doing something special since it's
essentially delaying evaluation. It's almost sort of a simplistic
lambda, but for strings. If I were to do the same thing in erb,

"#{expanded} \#{delayed}"

would become:

"<%= expanded %> <%%= delayed %>"

The double % should give you same pause that \ does.

I am somehow loath to mix both syntaxes, although I realise that's an
option. I don't really know why I would want to use one syntax to
partially build a template and another syntax to build the rest.

See also http://raa.ruby-lang.org/search.rhtml?search=template

Its so easy to write a proper one that everybody does it! It seems
to be the second Ruby project everyone uses.

Hehe! Thanks a lot for the info. I'll have to think about this and
play around with a few of them.

Cheers,
Navin.

···

Eric Hodel <drbrain@segment7.net> wrote:

Off the top of my head:

* ERb's <% ... %> flow control construct.
* The ability to control spacing as you can with the special string ERb's constructor takes.
* ERb's handy "% ... entire line of code ..." shortcut.
* ERb's utility methods for HTML and URL escaping.

But if you've found what works for you, far be it from me to complain. I was just making sure you were aware of another option.

James Edward Gray II

···

On Jul 16, 2005, at 3:23 PM, Navindra Umanee wrote:

James Edward Gray II <james@grayproductions.net> wrote:

Are you aware that Ruby ships with a templating language in its
standard library?

Yes I know of ERB. I am not sure what the advantage of using a
different syntax is, when I can simply use the same Ruby syntax but
escape it when necessary.

<%= delay %> is at least as verbose as \#{delay}.

What advantage do you see to using a new syntax instead of just Ruby?

Hi James,

But if you've found what works for you, far be it from me to
complain. I was just making sure you were aware of another option.

Thanks a lot for the info, I really appreciate it actually.

Off the top of my head:

* ERb's <% ... %> flow control construct.
* ERb's handy "% ... entire line of code ..." shortcut.

#{} allows arbitrary flow control of course. I think I can see where
ERB might have an edge in that it is easier to mix fixed strings with
Ruby code output.

* The ability to control spacing as you can with the special string
ERb's constructor takes.

I suppose I do sometimes end up with an extra \n here and there. I
haven't been bothered too much by it yet, because it generally doesn't
affect HTML rendering at all.

Another spacing problem right now is that I build my templates from a
lot of sub-templates and I can't see an easy way to get the HTML
indentation right because I never know what level I'm importing a
sub-template at. I doubt ERb would be of help here though and this is
basically only a concern regarding the readability of the HTML output.

* ERb's utility methods for HTML and URL escaping.

Unless I'm misunderstanding something, those utility methods are
replicated everywhere in Ruby. For example, CGI has its own copy of
them and I think WEBrick does too. Typically the methods are only 1
or 2 lines... I'm already using my own version of them.

Thanks a lot for the info! Let me know if I'm missing something.
I'll start thinking about whether it's worth switching to ERB given
the above.

Cheers,
Navin.

···

James Edward Gray II <james@grayproductions.net> wrote:

Navindra Umanee wrote:

#{} allows arbitrary flow control of course. I think I can see where
ERB might have an edge in that it is easier to mix fixed strings with
Ruby code output.

To be specific:

<html>
<head><title>Woo!</title>
<body>
  <table>
   <% @table.each do |row| %>
    <tr>
     <% row.each do |cell| %>
      <td><%= cell %></td>
     <% end %>
    </tr>
   <% end %>
  </table>
</body>
</html>

Devin

Indeed. This is what the same code looks like in Ruby syntax:

<html>
<head><title>Woo!</title>
<body>
  <table>
    #{@table.map do |row|
      %{<tr>
        #{row.map do |cell|
          %{<td>#{cell}</td>}
          end.join}
        </tr>}
      end.join}
  </table>
</body>
</html>

What do you think? It's close isn't it? But thanks for your example,
I'm slowing starting to see the point.

Cheers,
Navin.

···

Devin Mullins <twifkak@comcast.net> wrote:

<html>
<head><title>Woo!</title>
<body>
  <table>
   <% @table.each do |row| %>
    <tr>
     <% row.each do |cell| %>
      <td><%= cell %></td>
     <% end %>
    </tr>
   <% end %>
  </table>
</body>
</html>

and amrita is even nicer:

   ~ > cat a.rb
   require 'amrita/template'

   template = Amrita::TemplateText::new <<-html
     <html>
       <head> <title> Woo! </title> </head>
       <body>
         <table>
           <tr id=rows>
             <td id=foo></td>
             <td id=bar></td>
           </tr>
         </table>
       </body>
     </html>
   html

   rows = [
     { :foo => 42, :bar => 42.0 },
     { :foo => 'forty-two', :bar => 'FORTY-TWO' },
   ]

   template.expand STDOUT, :rows => rows

   ~ > ruby a.rb
   <html>
     <head> <title> Woo! </title> </head>
     <body>
       <table>
         <tr>
           <td>42</td>
           <td>42.0</td>
         </tr><tr>
           <td>forty-two</td>
           <td>FORTY-TWO</td>
         </tr>
       </table>
     </body>
   </html>

ahhhh. :wink:

-a

···

On Sun, 17 Jul 2005, Navindra Umanee wrote:

Devin Mullins <twifkak@comcast.net> wrote:

<html>
<head><title>Woo!</title>
<body>
  <table>
   <% @table.each do |row| %>
    <tr>
     <% row.each do |cell| %>
      <td><%= cell %></td>
     <% end %>
    </tr>
   <% end %>
  </table>
</body>
</html>

Indeed. This is what the same code looks like in Ruby syntax:

<html>
<head><title>Woo!</title>
<body>
<table>
   #{@table.map do |row|
     %{<tr>
       #{row.map do |cell|
         %{<td>#{cell}</td>}
         end.join}
       </tr>}
     end.join}
</table>
</body>
</html>

What do you think? It's close isn't it? But thanks for your example, I'm
slowing starting to see the point.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Hmmm, but your code doesn't quite do the same thing in that it doesn't
render the same structure:

@table = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]

Any particular reason you did it that way? I expect it's a symptom of
using Amrita, you have to beat the data into shape first.

Cheers,
Navin.

···

Ara.T.Howard <Ara.T.Howard@noaa.gov> wrote:

and amrita is even nicer:

just showing a simple example. for the same thing you'd

   ~ > cat a.rb
   require 'amrita/template'

   template = Amrita::TemplateText::new <<-html
     <html>
       <head> <title> Woo! </title> </head>
       <body>
         <table>
           <tr id=rows>
             <td id=a></td> <td id=b></td> <td id=c></td>
           </tr>
         </table>
       </body>
     </html>
   html

   rows = [
     { :a => 1, :b => 2, :c => 3 },
     { :a => 4, :b => 5, :c => 6 },
     { :a => 7, :b => 8, :c => 9 },
   ]

   template.expand STDOUT, :rows => rows

   ~ > ruby a.rb
   <html>
     <head> <title> Woo! </title> </head>
     <body>
       <table>
         <tr>
           <td>1</td> <td>2</td> <td>3</td>
         </tr><tr>
           <td>4</td> <td>5</td> <td>6</td>
         </tr><tr>
           <td>7</td> <td>8</td> <td>9</td>
         </tr>
       </table>
     </body>
   </html>

i generally wrap the 'beating' of data with something like

   class SomeTable < ::Array
     FIELDS = :a, :b, :c
     def to_amrita
       map do |row|
         FIELDS.inject(Hash::new){|h,f| h[f] = row.shift; h}
       end
     end
   end

so you can do something like

   st = SomeTable[
     [1, 2, 3],
     [4, 5, 6],
     [7, 8, 9],
   ]

   template.expand STDOUT, :rows => st.to_amrita

and have made component type object that have an 'to_html' method using an
internal template... the possiblities are endless but amrita, though it has a
small learning curve, can enable some really elegant ones. personally i
detest mixing html with ruby code in any form so amrita takes the cake in my
book.

cheers.

-a

···

On Sun, 17 Jul 2005, Navindra Umanee wrote:

Ara.T.Howard <Ara.T.Howard@noaa.gov> wrote:

and amrita is even nicer:

Hmmm, but your code doesn't quite do the same thing in that it doesn't
render the same structure:

@table = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]

Any particular reason you did it that way? I expect it's a symptom of
using Amrita, you have to beat the data into shape first.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Aha, but this is just the beginning. I was impressed by Amrita when I
first looked at the table example, but the more complex stuff you have
to do, the more contortions you have to suffer. To do an arbitrary
text substitution, you have to begin using these ugly <span>
statements, for example, and to substitute attributes you have to use
some other indirect stuff to describe them... but all this is easy
compared to what you have to do for complex control flow and
computation.

Development has in fact stopped on Amrita, as far as I can tell. Now
it's Amrita2 which allows you to use ERB... and you're back to square
one with an uncomfortable mix of different syntaxes. Essentially I
think this is a tacit admission that the Amrita approach is not powerful
enough on its own, or really it is just too clunky. Then there is the
horror that is Template Spec.

I could have it all wrong of course, having never used Amrita.
However when I start thinking about how I'm going to convert all my
"just do it in Ruby" code to Amrita, I get a nice little headache.

My Ruby HTML code generation does recursive tree traversals, has
special conditions, it has counters keeping track of nesting levels
that it uses for later substitions in the code it is building. It's
complex stuff doing complex things, but I "just do it" because it
really is straightforward Ruby coding. There's nothing magic about
recursion or counters.

On the other hand, I haven't the faintest idea how I would approach
that in Amrita. I imagine I would have to do all the work on some
external data structures and then somehow apply it to a template.
It's just an extra indirection and extra work... for what really? A
performance hit at runtime? Amrita just feels like a mental
straitjacket to me.

I too, like you, am attracted to the idea of separating HTML template
code from Ruby code. I can't quite think of a way of doing this that
is actually worthwhile when getting down to the more complex stuff.

:slight_smile:

Cheers,
Navin.

···

Ara.T.Howard <Ara.T.Howard@noaa.gov> wrote:

i generally wrap the 'beating' of data with something like