Hi All,
Is there an easy way to get a block / proc / lambda as a string…
without
any fancy serialization, no binding… just the code block as string?
Thanks!
L-P
Hi All,
Is there an easy way to get a block / proc / lambda as a string…
without
any fancy serialization, no binding… just the code block as string?
Thanks!
L-P
You’ll want to check out ruby2ruby:
http://seattlerb.rubyforge.org/ruby2ruby/
There’s nothing built into Ruby that will get you this.
Jason
mmm, I’m looking for a jRuby compatible solution… Ruby2Ruby look like
its
C dependant.
any other idea?
2009/6/2 Jason R. [email protected]
Louis-Philippe wrote:
any other idea?
Well, you can remember the string form at the time you define the
lambda.
def fn(str)
res = eval “lambda { #{str} }”
class <<res; self; end.class_eval { define_method(:source) { str } }
res
end
a = fn “|x| puts x+x”
a[“Hello”]
puts a.source
Thanks Brian,
It’s a neat trick! I’ll remember it!
I’m not sure I’ll use it though, as it require you define the function
inside a string…
a bit cumbersome.
what I need is some sort of macro system (the LISP macro, not the C
one),
to parse the block before calling it. I was thinking to make it a
string,
then parsing with regex, would have done it… but seems not. I’ll work
out
an other logic around the problem then ;).
L-P
2009/6/3 Brian C. [email protected]
module Kernel
alias :orig_lambda :lambda
def lambda(src=nil,*rest,&blk)
if src.nil?
orig_lambda(&blk)
else
res = eval “lambda { #{src} }”, *rest
class << res; self; end.class_eval { define_method(:source) { src
} }
res
end
end
end
a = lambda { |x| puts x+x }
b = lambda %{ |x| puts x+x+x }
a[“a”]
b[“b”]
puts b.source
prefix = “hello”
c = lambda %{ |x| puts "#{prefix} " + x }
puts c.source
c[“world”]
d = lambda %q{ |x| puts "#{prefix} " + x }, binding
puts d.source
d[“world”]
prefix = “goodbye”
d[“world”]
Louis-Philippe wrote:
I’m not sure I’ll use it though, as it require you define the function
inside a string…
a bit cumbersome.
How about using %{ … } for the string? Then it looks more like a
normal lambda.
a = fn %{ |x| puts x+x }
a[“Hello”]
puts a.source
Or you can read the source from its own file, or for longer snippets you
can use a here-doc.
a = fn <<‘EOF’
{ |x| puts x }
EOF
what I need is some sort of macro system (the LISP macro, not the C one),
to parse the block before calling it. I was thinking to make it a string,
then parsing with regex, would have done it…
Ruby doesn’t have macros. If you write a block in the usual way, the
Ruby interpreter will turn it into a Block object, and you cannot get
its source form back (in MRI anyway)
If you are only interested in simple regexp source transformations, then
you should start from a string form as above, transform, then eval.
For more complex transformations, still starting with a string, you
might be able to use one of the ruby-in-ruby implementations (e.g.
rubinius) or ParseTree to parse and transform it, I’m not sure.
On 6/3/09, Louis-Philippe [email protected] wrote:
what I need is some sort of macro system (the LISP macro, not the C one),
to parse the block before calling it. I was thinking to make it a string,
then parsing with regex, would have done it… but seems not. I’ll work out
an other logic around the problem then ;).
RubyMacros is an implementation of lisp-like macros for ruby…
however, unlike ParseTree, it doesn’t allow you to get at the contents
of a block. It does however, provide lisp-like forms as well. Maybe
you can put whatever code you need into a form? Take a look here:
On Jun 2, 2009, at 14:47 , Louis-Philippe wrote:
mmm, I’m looking for a jRuby compatible solution… Ruby2Ruby look
like its
C dependant.
any other idea?
jruby has their own parsetree equivalent, but I don’t know of / doubt
they have their own r2r equivalent. I know they haven’t bothered to
conform to the unified_ruby “spec” that I set up for all PT related
projects to ensure compatibility… so my guess is you’re out of luck.
Thanks guys,
while I think RubyMacro is a great idea (!!!),
I will wait until it get a bit more maturity and speed before using it.
I’ll probably stick one of your trick onto a block Brian, something
like:
$var = “global var”
def parsed_execution(list)
cmd_array = list.split(“\n”).map { |i| i.chomp.lstrip.rstrip }
cmd_array.each_with_index do |o,i|
puts “cmd #{i}:”
$var = “Finished!!” if i == cmd_array.size-1
eval o
end
end
I choosed the <<-EOF string because it is less likely to introduce
conflict
with the inner syntax… though %Q with a rightly choosed symbol might
also
be interesting.
what would be even neater would be to alias the <<- or %Q as something
smaller or more intuitive for my DSL, but I believe this is
impossible…
Thanks!
L-P
2009/6/3 Caleb C. [email protected]
Louis-Philippe wrote:
I’ll probably stick one of your trick onto a block Brian, something
like:
OK - not sure why you’re eval’ing it a line at a time though, instead of
all at once, as that would prevent you doing lots of interesting things,
like loops written across multiple lines.
I see you’re using a global var. You may want to check out instance_eval
(to set the default method receiver to an arbitrary object), and the
‘binding’ parameter to eval (to be able to access local variables from a
different scope)
Regards,
Brian.
Thanks Brian,
The single line evaluation will be usefull in my purpose built DSL,
I’m essentially trying to build an iterative execution structure on top
of a
recusive context-free one.
Too complex to explain in a couple lines, and still not all clear to
me…
so the code I pasted is only an example, my project is all built using
classes and more cleanly scoped variables.
L-P
2009/6/4 Brian C. [email protected]
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs