[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Delayed quote expansion

Kevin Olbrich

1/18/2006 5:30:00 AM

I'm sure the answer to this will seem simple once I see it. Right now
it eludes me.

How can one have a string object like this...

a = '#{some_value}'

and have it get evaluated as a double quoted string (with the value for
some_value being automatically replaced) at a later time?

I would prefer that it is evaluated in context from which it is called.

I would like to do something like this...

def func(param)
test = 42
puts param.quote_substitution
end

func('my number is #{test}') #=> "my number is 42"

_Kevin

--
Posted via http://www.ruby-....


12 Answers

Gary Wright

1/18/2006 6:35:00 AM

0


On Jan 18, 2006, at 12:29 AM, Kevin Olbrich wrote:
> I would prefer that it is evaluated in context from which it is
> called.
>
> I would like to do something like this...
>
> def func(param)
> test = 42
> puts param.quote_substitution
> end
>
> func('my number is #{test}') #=> "my number is 42"


How about:

template = lambda { |x| "my number is: #{x}" }

# some time passes

template.call(42) # "my number is: 42"




Gary Wright





ES

1/18/2006 7:52:00 AM

0

On 2006.01.18 14:29, Kevin Olbrich wrote:
> I'm sure the answer to this will seem simple once I see it. Right now
> it eludes me.
>
> How can one have a string object like this...
>
> a = '#{some_value}'
>
> and have it get evaluated as a double quoted string (with the value for
> some_value being automatically replaced) at a later time?
>
> I would prefer that it is evaluated in context from which it is called.
>
> I would like to do something like this...
>
> def func(param)
> test = 42
> puts param.quote_substitution
> end
>
> func('my number is #{test}') #=> "my number is 42"

You can delay evaluation like this:

string = '"#{foo}"'

# ...

value = eval string # Add a binding if you want

> _Kevin


E


Paolo Capriotti

1/18/2006 10:10:00 AM

0

On 1/18/06, Kevin Olbrich <kevin.olbrich@duke.edu> wrote:
[snip]
> I would like to do something like this...
>
> def func(param)
> test = 42
> puts param.quote_substitution
> end
>
> func('my number is #{test}') #=> "my number is 42"

Try this:

class String
def evaluate(*args)
eval inspect.gsub(/\\#/, '#'), *args
end
end

def func(str)
x = 42
str.evaluate(binding)
end

puts func('the answer is #{x}')



--

Paolo


Kevin Olbrich

1/18/2006 12:48:00 PM

0

Lots of good responses here, but the one that turns out to be the
easiest is...

def func(param)
some_value = 42
value = eval %Q{%Q{#{param}}}
end

func('my number is #{some_value}') #=> 'my number is 42'


_Kevin

--
Posted via http://www.ruby-....


James Gray

1/18/2006 1:43:00 PM

0

On Jan 18, 2006, at 6:48 AM, Kevin Olbrich wrote:

> Lots of good responses here, but the one that turns out to be the
> easiest is...
>
> def func(param)
> some_value = 42
> value = eval %Q{%Q{#{param}}}
> end
>
> func('my number is #{some_value}') #=> 'my number is 42'

What you really want here is ERB:

>> require "erb"
=> true
>> def expand( template )
>> some_value = 42
>> ERB.new(template).result(binding)
>> end
=> nil
>> expand "My number is <%= some_value %>."
=> "My number is 42."

James Edward Gray II


Kevin Olbrich

1/18/2006 1:52:00 PM

0

James Gray wrote:
> What you really want here is ERB:
>

A good suggestion, but I would rather avoid unnecessary dependencies if
there is an adequate pure ruby way to do it.

_Kevin

--
Posted via http://www.ruby-....


Bob Showalter

1/18/2006 2:06:00 PM

0

Kevin Olbrich wrote:
> James Gray wrote:
>
>>What you really want here is ERB:
>>
>
>
> A good suggestion, but I would rather avoid unnecessary dependencies if
> there is an adequate pure ruby way to do it.

erb *is* pure Ruby. It is part of the standard library, so every Ruby
installation has it.


Kevin Olbrich

1/18/2006 4:13:00 PM

0

Bob Showalter wrote:

> erb *is* pure Ruby. It is part of the standard library, so every Ruby
> installation has it.

So it is, my bad.

--
Posted via http://www.ruby-....


Geoff Jacobsen

1/19/2006 9:45:00 PM

0

Kevin Olbrich wrote:
> Lots of good responses here, but the one that turns out to be the
> easiest is...
>
> def func(param)
> some_value = 42
> value = eval %Q{%Q{#{param}}}
> end
>
> func('my number is #{some_value}') #=> 'my number is 42'

This solution has the problem that it doesn't work for:

func('{ #{1+2}')

A solution I have used in the past is:

param.gsub(/\#\{([^\}]*)\}/) { eval($1) }

but that wont work for:

param='#{"12#{1+2}4"}'

I would be very interested if anyone has a robust solution...

Andrew Johnson

1/20/2006 9:36:00 AM

0

On 19 Jan 2006 13:45:14 -0800, geoffjacobsen@gmail.com
<geoffjacobsen@gmail.com> wrote:
[snip]
> but that wont work for:
>
> param='#{"12#{1+2}4"}'
>
> I would be very interested if anyone has a robust solution...


The problem is that the #{code} construct can contain arbitrary
code, including being multi-line code, with comments, other blocks,
nested strings ...

If using Oniguruma is allowed (with subexpression calling and cuts) then we
can make a bit of progress hacking up a rudimentary parser that can try to
grab #{}-like things for evaluation:

class Parse
QLIKE = %r/(?:'(?:\\'|[^'])*' |
"(?:\\"|[^"])*" |
%[qQrxw]\!(?:\\!|[^\!])*\! |
%[qQrxw]\#(?:\\\#|[^#])*\# |
%[qQrxw]\|(?:\\\||[^|])*\| |
%[qQrxw]\/(?:\\\/|[^\/])*\/ |
%[qQrxw](?<qb>\[(?:(?>\\[\]\[]|[^\[\]])|\g<qb>)*\]) |
%[qQrxw](?<qa>\<(?:(?>\\[<>]|[^<>])|\g<qa>)*\>) |
%[qQrxw](?<qc>\{(?:(?>\\[{}]|[^{}])|\g<qc>)*\}) |
%[qQrxw](?<qp>\((?:(?>\\[()]|[^()])|\g<qp>)*\)) )/x

COMMENT = %r/(?:#[^\n]*\n)/
SBLOCK = %r/(?<block>\{(?:(?>#{COMMENT} |
#{QLIKE} |
[^{}]
) |
\g<block>)*
\})/x

def Parse.expand str
test = "ple"
str.gsub!(/(?<!\\)##{SBLOCK}/){eval $1.gsub(/\A\{|\}\z/,'')}
end
end

param='#{"12#{1+2}4"}'
Parse.expand(param)
puts param

test = 42
param = 'this is \#{not} a #{"sil".succ + # blah } blah comments
(%Q!}! << lambda{?b - ?5}.call) + # }}more comments{{}
"{#{test}" # yet more (*&@QI#{J$)*DF}{Junk
} exercise' # <- string ends down here
Parse.expand(param)
puts param

__END__

results in:

1234
this is \#{not} a sim}-{ple exercise


Is this robust? It is only a small bit of required parsing (for instance,
there are more potential delimiters for quote-like expressions) -- However,
it does make failure-prediction less obvious, which some might substitute
for robustness :-)

cheers,
andrew

--
Andrew L. Johnson http://www.s...
I don't want to achieve immortality through my work; I want to
achieve immortality through not dying.
- Woody Allen