[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Coopting String interpolation

aurelianito

5/17/2007 4:19:00 AM

We all know the #{} operator for String interpolation.
It's used like this:

name="Aure"
greeting="hi, #{name}"

and greeting evaluates to "hi, Aure". But I would like to change it.
Is there a pure Ruby way to force "hi, #{name}" to evaluate to "hi,
AURE" (get the uppercase of the original interpolated String).
Something like:

class String
# do some magic here
end

name="Aure"
greeting="hi, #{name}"

and now greeting evaluates to "hi, AURE". Is there a method in String
to override in order to take control of the String interpolation?

Thanks in advance,
Aureliano.

17 Answers

Peña, Botp

5/17/2007 4:29:00 AM

0

From: aurelianito [mailto:aurelianocalvo@gmail.com] :
# Is there a pure Ruby way to force "hi, #{name}" to evaluate to "hi,
# AURE" (get the uppercase of the original interpolated String).
# Something like:

pols. think simple, then just do it.

interpolation can be any expression..

irb(main):001:0> name="Aure"
=> "Aure"
irb(main):002:0> greeting="hi, #{name}"
=> "hi, Aure"
irb(main):003:0> greeting="hi, #{name.upcase}"
=> "hi, AURE"
irb(main):005:0> greeting="hi, #{"Ms "+name.capitalize}"
=> "hi, Ms Aure"
irb(main):006:0>

Peña, Botp

5/17/2007 4:33:00 AM

0

# irb(main):005:0> greeting="hi, #{"Ms "+name.capitalize}"
# => "hi, Ms Aure"

sorry, was too fast on the last example; should be..

irb(main):006:0> greeting="hi, #{name="Anne";"Ms "+name.capitalize}"
=> "hi, Ms Anne"

aurelianito

5/17/2007 5:10:00 AM

0



On 17 mayo, 01:33, Peña, Botp <b...@delmonte-phil.com> wrote:
> # irb(main):005:0> greeting="hi, #{"Ms "+name.capitalize}"
> # => "hi, Ms Aure"
>
> sorry, was too fast on the last example; should be..
>
> irb(main):006:0> greeting="hi, #{name="Anne";"Ms "+name.capitalize}"
> => "hi, Ms Anne"

I'm trying to do some metaprogramming and I need to apply some
operation to all the strings that are interpolated. But I can't change
the interpolation. In the example, I would like that "hi, #{name}" to
evaluate to "hi, AURE" instead of "hi, Aure". I know that inside the
#{} "operator" I can put any ruby code, so "hi, #{name.capitalize}"
would evaluate to what I want.

But I want it to execute code that I DON'T write there. Ideally, there
should be a method hook or something to change the way the
interpolation works. But I couldn't find it :(. May be a different
example may be more clear. How can I do to write to a file all the
strings generated via interpolations (id est, all the strings that are
generated evaluating the different #{} "operators" in a program)?

Thanks,
Aureliano.


Nobuyoshi Nakada

5/17/2007 7:15:00 AM

0

Hi,

At Thu, 17 May 2007 13:20:14 +0900,
aurelianito wrote in [ruby-talk:251879]:
> class String
> # do some magic here
> end
>
> name="Aure"
> greeting="hi, #{name}"
>
> and now greeting evaluates to "hi, AURE". Is there a method in String
> to override in order to take control of the String interpolation?

If the value isn't a String, to_s is called for it to get a
String. Otherwise, the content is interpolated directly.
There is not a hook you want.

--
Nobu Nakada

Robert Klemme

5/17/2007 10:48:00 AM

0

On 17.05.2007 07:09, aurelianito wrote:
>
> On 17 mayo, 01:33, Peña, Botp <b...@delmonte-phil.com> wrote:
>> # irb(main):005:0> greeting="hi, #{"Ms "+name.capitalize}"
>> # => "hi, Ms Aure"
>>
>> sorry, was too fast on the last example; should be..
>>
>> irb(main):006:0> greeting="hi, #{name="Anne";"Ms "+name.capitalize}"
>> => "hi, Ms Anne"
>
> I'm trying to do some metaprogramming and I need to apply some
> operation to all the strings that are interpolated. But I can't change
> the interpolation. In the example, I would like that "hi, #{name}" to
> evaluate to "hi, AURE" instead of "hi, Aure". I know that inside the
> #{} "operator" I can put any ruby code, so "hi, #{name.capitalize}"
> would evaluate to what I want.
>
> But I want it to execute code that I DON'T write there. Ideally, there
> should be a method hook or something to change the way the
> interpolation works. But I couldn't find it :(. May be a different
> example may be more clear. How can I do to write to a file all the
> strings generated via interpolations (id est, all the strings that are
> generated evaluating the different #{} "operators" in a program)?

Frankly, it has not become clear to me what you are up to. Can you
maybe just state which problem you are trying to solve?

As for a solution to your original example, you can do something like
this - but it's a hack and not very reliable:

class Env
def initialize(vals)
@vals = vals
end

def process(&b)
instance_eval(&b)
end

def method_missing(s,*a,&b)
super unless a.empty?
@vals[s.to_sym].upcase
end
end

irb(main):015:0> e=Env.new(:name=>'foo')
=> #<Env:0x7ff6d388 @vals={:name=>"foo"}>
irb(main):016:0> e.process { "bar #{name}" }
=> "bar FOO"
irb(main):017:0>

Kind regards

robert

aurelianito

5/17/2007 12:28:00 PM

0

> > I'm trying to do some metaprogramming and I need to apply some
> > operation to all the strings that are interpolated. But I can't change
> > the interpolation. In the example, I would like that "hi, #{name}" to
> > evaluate to "hi, AURE" instead of "hi, Aure". I know that inside the
> > #{} "operator" I can put any ruby code, so "hi, #{name.capitalize}"
> > would evaluate to what I want.
> >
> > But I want it to execute code that I DON'T write there. Ideally, there
> > should be a method hook or something to change the way the
> > interpolation works. But I couldn't find it :(. May be a different
> > example may be more clear. How can I do to write to a file all the
> > strings generated via interpolations (id est, all the strings that are
> > generated evaluating the different #{} "operators" in a program)?
>
> Frankly, it has not become clear to me what you are up to. Can you
> maybe just state which problem you are trying to solve?

NDAs are a bitch. I can't state the exact problem (bah! I can, but I
could be fired, in a trial, and I also might inhibit my coworkers to
publish a paper with their findings). I'm working in a research
project and I need to do some "clever stuff" (that's the thing I can't
disclose) to all the Strings. This thing is "different" depending on
how strings are composed. All the ways I know for string composition
but string interpolation (<<, +, concat, gsub, etc.) can be overridden
redefining methods in the string class. I'm looking for a way to
intercept the string expansion to do my thing. Does ruby internally
call some overridable method to compose the strings used in a
interpolation?

Now I see that if I can transform all the <"a#{expression}c"> in <"a"
+ (expression) + "c"> in a ruby source code string, I could change
expression with "a#{expression}c" in "a" + clever_stuff(expression) +
"c" and use my changed + method in Strings. Is there an easy way to
manipulate ruby code in ruby to do this?

Thanks for your time,
Aureliano.

Mariusz Pekala

5/17/2007 2:40:00 PM

0

On 2007-05-17 21:27:56 +0900 (Thu, May), Aureliano Calvo wrote:
> Now I see that if I can transform all the <"a#{expression}c"> in <"a"
> + (expression) + "c"> in a ruby source code string, I could change
> expression with "a#{expression}c" in "a" + clever_stuff(expression) +
> "c" and use my changed + method in Strings. Is there an easy way to
> manipulate ruby code in ruby to do this?

Maybe this will be of some use:

irb(main):005:0> "asd_#{raise caller.to_s}_"
RuntimeError: /usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'/usr/lib/ruby/1.8/irb/workspace.rb:52
from (irb):5

--
No virus found in this outgoing message.
Checked by 'grep -i virus $MESSAGE'
Trust me.

Mariusz Pekala

5/17/2007 2:51:00 PM

0

> On 2007-05-17 21:27:56 +0900 (Thu, May), Aureliano Calvo wrote:
> > Now I see that if I can transform all the <"a#{expression}c"> in <"a"
> > + (expression) + "c"> in a ruby source code string, I could change
> > expression with "a#{expression}c" in "a" + clever_stuff(expression) +
> > "c" and use my changed + method in Strings. Is there an easy way to
> > manipulate ruby code in ruby to do this?
>
> Maybe this will be of some use:
>
> irb(main):005:0> "asd_#{raise caller.to_s}_"
> RuntimeError: /usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'/usr/lib/ruby/1.8/irb/workspace.rb:52
> from (irb):5

Oh, no - it's stupid. Sorry ;-)


--
No virus found in this outgoing message.
Checked by 'grep -i virus $MESSAGE'
Trust me.

Gavin Kistner

5/17/2007 5:05:00 PM

0

On May 17, 6:27 am, "Aureliano Calvo" <aurelianoca...@gmail.com>
wrote:
> Now I see that if I can transform all the <"a#{expression}c"> in <"a"
> + (expression) + "c"> in a ruby source code string, I could change
> expression with "a#{expression}c" in "a" + clever_stuff(expression) +
> "c" and use my changed + method in Strings. Is there an easy way to
> manipulate ruby code in ruby to do this?

Can you make life easier by changing to use ERB?
You cannot change Ruby string interpolation in Ruby. You can hack the
source code if you really need to. You can manually change your
strings, or you can (as below) use gsub to change the string before
evaluating.

def clever_stuff( str )
str.upcase
end

require 'erb'
def clever_template( str )
ERB.new( str.gsub( /<%=(.+?)%>/, '<
%=clever_stuff(\1)%>' ) ).result
end

name1, name2 = %w|Gavin Kistner|

str1 = "Hello there, <%=name1%> <%=name2%>! Nice to meet you!"
puts clever_template( str1 )
#=> Hello there, GAVIN KISTNER! Nice to meet you!

str2 = "Hello there, <%=name1 + ' ' + name2%>! Nice to meet you!"
puts clever_template( str2 )
#=> Hello there, GAVIN KISTNER! Nice to meet you!

Pit Capitain

5/17/2007 6:49:00 PM

0

Aureliano Calvo schrieb:
> Now I see that if I can transform all the <"a#{expression}c"> in <"a"
> + (expression) + "c"> in a ruby source code string, I could change
> expression with "a#{expression}c" in "a" + clever_stuff(expression) +
> "c" and use my changed + method in Strings. Is there an easy way to
> manipulate ruby code in ruby to do this?

Aureliano, is it right that you don't need to manipulate the code at
runtime, and you can work with the source code instead? This can be more
or less hard to do, depending on the complexity of the expressions which
are allowed inside the strings. For simple expressions a regex solution
might be enough. Otherwise you'd need to use one of the Ruby parser
libraries.

If this is for a research project, then maybe you could patch the Ruby
interpreter to add the hook you need. This shouldn't be too difficult.

Regards,
Pit