File.readlines(“test.txt”).each {|line| print eval(’"’ + line + ‘"’)}
will work. Even if there were a function such as String.interpolate(str) it
would still be dangerous because any code within the #{} blocks would be
evaluated!
Steve
···
-----Original Message-----
From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]
Sent: Friday, September 20, 2002 2:54 PM
To: ruby-talk ML
Subject: String interpolation at will?
Maybe I’m overlooking something obvious,
or maybe it’s not possible.
We all know how convenient string interpolation
can be: msg = “myval = #{myval}”
Is there a way to perform interpolation on
an arbitrary string? For example, if the
above string were read in from a file?
gsub doesn’t count. Unless you have a
particularly elegant way to use it.
File.readlines(“test.txt”).each {|line| print eval(‘"’ + line + ‘"’)}
Well, I guess you’d have to use gsub to escape any existing quotes
first…
will work. Even if there were a function such as String.interpolate(str)
it
would still be dangerous because any code within the #{} blocks would be
evaluated!
Hmm, there have been times I wished for a String.interpolate
method… couldn’t be too hard to expose it. Wonder if it’s
worth it?
Danger is always an issue… guess it’s not so bad as long as
you have control over the data.
Even regular interpolation is potentially dangerous:
string = “Hi, my name is #{format_hard_drive_and_return_name()}.”
Hal
···
----- Original Message -----
From: “Steve Tuckner” STUCKNER@MULTITECH.COM
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 3:08 PM
Subject: RE: String interpolation at will?
File.readlines(“test.txt”).each {|line| print eval(‘"’ + line + ‘"’)}
will work. Even if there were a function such as String.interpolate(str) it
would still be dangerous because any code within the #{} blocks would be
evaluated!
indeed.
im stuck with this version:
—
def interpolate(str)
reg = Regexp.new(‘#{(($|@|@@)\w+)}’)
ret = ‘’
while (match = reg.match(str))
ret += match.pre_match
for i in 1..(match.length-1)
ret += yield(match[1])
end
str = match.post_match
end
ret += str
end
testing calls:
a = ‘3012’
b = ‘1322’
str = ‘foo “#{a} #{b}”’
p interpolate(str) {|match| eval(match)}
p interpolate(‘#{a}’) {|match| eval(match)}
—
and i have 2 questions to the community:
i was not able to find an equivalent to perl’s regexp-substitutes, so i had to do the
ugly/complex/inefficient loop-contruct in “interpolate”. is there a better way to achieve
this in ruby?
i have to call interpolate with the eval block appended, so that the variables a
looked up in the scope of the calling environment. is there a more better way to do
this, or to make ‘{|match| eval(match)}’ the default, if no block is supplied?
regards
messju
···
Steve
-----Original Message-----
From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]
Sent: Friday, September 20, 2002 2:54 PM
To: ruby-talk ML
Subject: String interpolation at will?
Maybe I’m overlooking something obvious,
or maybe it’s not possible.
We all know how convenient string interpolation
can be: msg = “myval = #{myval}”
Is there a way to perform interpolation on
an arbitrary string? For example, if the
above string were read in from a file?
gsub doesn’t count. Unless you have a
particularly elegant way to use it.
To reply to myself: I’ve just remembered why
this is nontrivial in pure Ruby. If you write
a String#interpolate, it can’t get to your
local variables, i.e. if you do:
bar = “secret”
foo = ‘code is #{bar}’
str = foo.interpolate
it won’t work because #interpolate can’t see
the bar variable. Hmm.
You can still do it outside of a method, of
course.
I’m playing with a Proc now out of curiosity.
Hal
···
----- Original Message -----
From: “Hal E. Fulton” hal9000@hypermetrics.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 3:30 PM
Subject: Re: String interpolation at will?
Hmm, there have been times I wished for a String.interpolate
method… couldn’t be too hard to expose it. Wonder if it’s
worth it?
class String
def String.interpolate(str)
@@interp.call(str)
end
def interpolate
@@interp.call(self)
end
end
Now try it out
str = <<‘END’
He said, “I am the #{alpha} and
the #{omega}.”
Have a nice day.
END
puts str
alpha = “walrus”
omega = “weather is fine”
str2 = str.interpolate
puts str2
str3 = String.interpolate(str)
puts str3
And the output is:
He said, “I am the #{alpha} and
the #{omega}.”
Have a nice day.
He said, “I am the walrus and
the weather is fine.”
Have a nice day.
He said, “I am the walrus and
the weather is fine.”
Have a nice day.
···
----- Original Message -----
From: “Hal E. Fulton” hal9000@hypermetrics.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 4:06 PM
Subject: Re: String interpolation at will?
----- Original Message -----
From: “Hal E. Fulton” hal9000@hypermetrics.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 3:30 PM
Subject: Re: String interpolation at will?
Hmm, there have been times I wished for a String.interpolate
method… couldn’t be too hard to expose it. Wonder if it’s
worth it?
To reply to myself: I’ve just remembered why
this is nontrivial in pure Ruby. If you write
a String#interpolate, it can’t get to your
local variables, i.e. if you do:
bar = “secret”
foo = ‘code is #{bar}’
str = foo.interpolate
it won’t work because #interpolate can’t see
the bar variable. Hmm.
You can still do it outside of a method, of
course.
Hal E. Fulton (in "String[#.]interpolate (was Re: String interpolation
[…]
And to answer my own post again, I find that
this works OK.
[…]
You can also require a Binding as an argument to #interpolate, and then
do the eval with it, which allows you to interpolate from arbitrary
scopes:
class String
def interpolate( scope )
unless scope.is_a?( Binding )
raise TypeError, "Argument to interpolate must be a Binding,
not "
“a #{scope.class.name}”
end
----- Original Message -----
From: “Hal E. Fulton” hal9000@hypermetrics.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 4:06 PM
Subject: Re: String interpolation at will?
----- Original Message -----
From: “Hal E. Fulton” hal9000@hypermetrics.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, September 20, 2002 3:30 PM
Subject: Re: String interpolation at will?
Hmm, there have been times I wished for a String.interpolate
method… couldn’t be too hard to expose it. Wonder if it’s
worth it?
To reply to myself: I’ve just remembered why
this is nontrivial in pure Ruby. If you write
a String#interpolate, it can’t get to your
local variables, i.e. if you do:
bar = “secret”
foo = ‘code is #{bar}’
str = foo.interpolate
it won’t work because #interpolate can’t see
the bar variable. Hmm.
You can still do it outside of a method, of
course.
I’m playing with a Proc now out of curiosity.
And to answer my own post again, I find that
this works OK.
Tempted to put ANN: on the subject line.
Code below.
Cheers,
Hal
Let’s make a setter for a class variable
class String
def String.interp=(blk)
@@interp = blk
end
end
class String
def String.interpolate(str)
@@interp.call(str)
end
def interpolate
@@interp.call(self)
end
end
Now try it out
str = <<‘END’
He said, “I am the #{alpha} and
the #{omega}.”
Have a nice day.
END
puts str
alpha = “walrus”
omega = “weather is fine”
str2 = str.interpolate
puts str2
str3 = String.interpolate(str)
puts str3
And the output is:
He said, “I am the #{alpha} and
the #{omega}.”
Have a nice day.
He said, “I am the walrus and
the weather is fine.”
Have a nice day.
He said, “I am the walrus and
the weather is fine.”
Have a nice day.
very nice. but, unless i am missing something, there is just one flaw:
String.interp is always called in global context. you cannot use
String.interpolate inside a method and use local variables there.
very nice. but, unless i am missing something, there is just one flaw:
String.interp is always called in global context. you cannot use
String.interpolate inside a method and use local variables there.
Perhaps you are right. I don’t have time
to look at it right now.
Can you show me an example of something
that fails?
Hal
···
----- Original Message -----
From: “M Mohr” messju@lammfellpuschen.de
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, September 23, 2002 7:16 AM
Subject: Re: String[#.]interpolate (was Re: String interpolation at will?)