[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

block as string

Louis-Philippe

6/2/2009 8:56:00 PM

[Note: parts of this message were removed to make it a legal post.]

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

11 Answers

Jason Roelofs

6/2/2009 9:30:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

You'll want to check out ruby2ruby:
http://seattlerb.rubyforge.org/...

There's nothing built into Ruby that will get you this.

Jason

On Tue, Jun 2, 2009 at 4:55 PM, Louis-Philippe <default@spiralix.org> wrote:

> 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
>

Louis-Philippe

6/2/2009 9:48:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

mmm, I'm looking for a jRuby compatible solution... Ruby2Ruby look like its
C dependant.
any other idea?

2009/6/2 Jason Roelofs <jameskilton@gmail.com>

> You'll want to check out ruby2ruby:
> http://seattlerb.rubyforge.org/...
>
> There's nothing built into Ruby that will get you this.
>
> Jason
>
> On Tue, Jun 2, 2009 at 4:55 PM, Louis-Philippe <default@spiralix.org>
> wrote:
>
> > 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
> >
>

Brian Candler

6/3/2009 9:09:00 AM

0

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
--
Posted via http://www.ruby-....

Louis-Philippe

6/3/2009 2:17:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

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 Candler <b.candler@pobox.com>

> 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
> --
> Posted via http://www.ruby-....
>
>

Brian Candler

6/3/2009 2:43:00 PM

0

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.
--
Posted via http://www.ruby-....

Brian Candler

6/3/2009 2:58:00 PM

0

# Slightly enhanced version
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

# %{...} performs substitutions as per double-quoted string
prefix = "hello"
c = lambda %{ |x| puts "#{prefix} " + x }
puts c.source
c["world"]

# %q{...} is like single-quoted string
d = lambda %q{ |x| puts "#{prefix} " + x }, binding
puts d.source
d["world"]
prefix = "goodbye"
d["world"]
--
Posted via http://www.ruby-....

Ryan Davis

6/3/2009 6:50:00 PM

0


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.


Caleb Clausen

6/3/2009 10:09:00 PM

0

On 6/3/09, Louis-Philippe <default@spiralix.org> 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:

http://github.com/coatl/...

Louis-Philippe

6/4/2009 5:14:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

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 }
# process cmd_array here
cmd_array.each_with_index do |o,i|
puts "cmd #{i}:"
$var = "Finished!!" if i == cmd_array.size-1
eval o
end
end

parsed_execution <<-BLOCK
puts "Line 1"
puts $var
puts "replacing global var..."
$var = "new global var" # will never get printed!!!
puts $var
BLOCK
---------------------------------

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 Clausen <vikkous@gmail.com>

> On 6/3/09, Louis-Philippe <default@spiralix.org> 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:
>
> http://github.com/coatl/...
>
>

Brian Candler

6/4/2009 7:39:00 PM

0

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.
--
Posted via http://www.ruby-....