Viral arguments

thanks for all the response on the float problem. alot of people jumped on
that one. guess everyone but me knew the answer. :slight_smile:

anyway, i’m sitting here coding my billy-bad-ass cgi accounting system, in
yours truly, ruby, and i’m running into small sticky spots in which i want to
keep a library i created pure for general use, yet i run into particular
situations where the behavior needs a minor tweak to work. upon looking at
these recoccuring catches, i started to develop a notion of "virus-like"
arguments.

the idea is that rather then pass simple argumments, one could pass a little
piece of code that would execute in the context of the method.

here’s a foo example (vproc is like proc but viral):

def foo(x)
	i = 1
	puts "#{x + i}"
end

puts foo(4) --> 5
puts foo(vproc {i + 1}) --> 3

any thoughts? can ruby achieve something like this already?

-transami

If I am understanding you correctly, Ruby has this mechanism already.
It is called a “block” (much better sounding than “viral” is it not?)

def foo (x=nil)
i = 1
x = 0 if !x # use whatever default you want, or raise error
return yield (i) if block_given?
i + n
end

bar = Proc.new { |i| i + 3 }
baz = Proc.new { |i| i * 5 }

foo #=> 1
foo 4 #=> 5
foo &bar #=> 4
foo &baz #=> 5

Thus, no argument returns a predefined default
Argument returns defined behavior operating on argument
Block returns returns operation on variable i

Note & in front of block names (bar and baz); this tells Ruby a block
has been passed (given). The block_given? method in the if statement
tests for that.

This is a very powerful feature; there are a lot of possibilities. Play
araound, experiement and enjoy.

Hope this helps?

Regards,

Kent Starr

···

On Fri, 2002-12-27 at 03:12, Tom Sawyer wrote:

the idea is that rather then pass simple argumments, one could pass a little
piece of code that would execute in the context of the method.

here’s a foo example (vproc is like proc but viral):

def foo(x)
i = 1
puts “#{x + i}”
end

puts foo(4) → 5
puts foo(vproc {i + 1}) → 3

any thoughts? can ruby achieve something like this already?

Hi,

the idea is that rather then pass simple argumments, one could pass a little
piece of code that would execute in the context of the method.

here’s a foo example (vproc is like proc but viral):

def foo(x)
i = 1
puts “#{x + i}”
end

puts foo(4) → 5
puts foo(vproc {i + 1}) → 3

any thoughts? can ruby achieve something like this already?

I did something that sounds a little like that the other day
when making a web site for my girlfriend ( http://zip.to/beadyourselfup :slight_smile:

···

From: “Tom Sawyer” transami@transami.net

Adding a new instance method to String class which “re evaluates”

the string in the context of the Kernel::binding object we pass in.

(Note that the here-document approach this uses tacks on an extra

\n to the resulting string… but that was fine for my purposes.)

class String
def reeval(b = TOPLEVEL_BINDING)
eval(%Q{<<“END_REEVAL”\n} + self + “\nEND_REEVAL\n”, b)
end
end

class BeadShot

def gen_fullsize_html(prev_shot, next_shot)
#
# Here, a string containing the HTML template for the
# page we’re generating is “reevaluated” in the current
# context - so it has access (via interpolation #{ }) to
# the current BeadShot instance’s methods, and even the
# local variables in scope at the moment (prev_shot,
# next_shot).
#
html = $bead_fullsize_page.reeval(binding)
end

def item_number
@file_num + $item_number_offset
end

… etc.

end

Here’s an excerpt from the string reevaluated by the code

above. Note that I wanted interpolation to occur both when

the string was defined - to pull in other components of the

page like $header_html - and later when re-evaluated; so

the interpolation that’s deferred for “reeval” is escaped

like #{ } .

$bead_fullsize_page = <<“END_HTML”
#$header_html

item # \#{ item_number }
\#{ gen_fullsize_inline_img(1) }
\#{ prev_shot ? prev_shot.gen_link("previous", 1) : "" } \#{ (prev_shot && next_shot)? $sep_bar : "" } \#{ next_shot ? next_shot.gen_link("next", 1) : "" }
 
... back to home page ...
END_HTML

An example of the resulting HTML can be seen at the bottom of:
http://www.foosenblat.com/beadyourselfup/bead_html/bead00057.html

[Flames about anything stupid I may have done in the HTML that
aren’t Ruby-related should probably be sent to me off-list. ]

Anyway I wondered if this might be similar to what you had in
mind with “viral arguments”. ?

Regards,

Bill

Hi –

thanks for all the response on the float problem. alot of people jumped on
that one. guess everyone but me knew the answer. :slight_smile:

anyway, i’m sitting here coding my billy-bad-ass cgi accounting system, in
yours truly, ruby, and i’m running into small sticky spots in which i want to
keep a library i created pure for general use, yet i run into particular
situations where the behavior needs a minor tweak to work. upon looking at
these recoccuring catches, i started to develop a notion of “virus-like”
arguments.

the idea is that rather then pass simple argumments, one could pass a little
piece of code that would execute in the context of the method.

here’s a foo example (vproc is like proc but viral):

def foo(x)
i = 1
puts “#{x + i}”
end

puts foo(4) → 5
puts foo(vproc {i + 1}) → 3

any thoughts? can ruby achieve something like this already?

It’s not clear to me why executing “i+1” at the top of the method
would do anything but raise an exception (unless the object has an #i
method)… but in any case, see Kent’s answer about blocks. Also,
consider the impossibility of maintaining and debugging code where the
names of a method’s local variables have to be known outside the
method. That’s why they’re local :slight_smile:

David

···

On Fri, 27 Dec 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

If I understand you (which I very well may not :), you are asking if you can
execute a block in the context of the method you send the block into.

Check out html/common.rb (comes standard with Ruby) which has html
generation code. In the middle of HTML.def_element you’ll see:

          buf = instance_eval(&block)

It’s that simple.

(Mind you, it took me quite a while to figure out why my #$*!ing blocks
weren’t working properly! When I found out what was going on, I stopped
using this library and wrote a quick-n-dirty one of my own. Now I just
subclass.)

Chris

If I am understanding you correctly, Ruby has this mechanism already.
It is called a “block” (much better sounding than “viral” is it not?)

Thus, no argument returns a predefined default
Argument returns defined behavior operating on argument
Block returns returns operation on variable i

Note & in front of block names (bar and baz); this tells Ruby a block
has been passed (given). The block_given? method in the if statement
tests for that.

This is a very powerful feature; there are a lot of possibilities. Play
araound, experiement and enjoy.

Kent,

this is kind of like what i’m talking about. blocks are very powerful indeed,
and i have used blocks many a time.

the differenece between this and my idea though is that, with blocks, one must
pre-program the method to deal with the incoming block. my notion dosen’t
have this requirement.

of course david’s right, my example is poor in that the viral argument
shouldn’t be able to access local variables, only public accessable methods.

-transami

···

On Friday 27 December 2002 03:11 am, W. Kent Starr wrote:

Hello Tom,

Saturday, December 28, 2002, 9:10:33 AM, you wrote:

the differenece between this and my idea though is that, with blocks, one must
pre-program the method to deal with the incoming block. my notion dosen’t
have this requirement.

i think that thing you want called “lazy (deferred) evaluation”. it’s fashion
of modern functional languages, but it’s slows down all the program and more
hard to understand by “average” programmer. see haskell language if you interested
in this. one example of power of this technique:

def natural_numbers
return [1] + natural_numbers.map{|x| x+1}
end
def fib
return [1,1] + natural_numbers.each{|i| fib[i-1]+fib[i]}
end
print fib[0…100]

actuall, this technique - passing ALL arguments as blocks and evaluating
them only when algorithm needs concrete value and only to that
deepness level that needed for algorithm. it’s very power technique
for lists manipulation - you can represent naturally INFINITE lists
with recursive definition which will be evaluated only to the element(s)
you need

···


Best regards,
Bulat mailto:bulatz@integ.ru

Sat, 28 Dec 2002 15:37:14 +0900, Bulat Ziganshin bulatz@integ.ru pisze:

i think that thing you want called “lazy (deferred) evaluation”.

I think he wants dynamic scoping. But I haven’t encountered it in
any language except ancient Lisp.

I don’t know any case where I would want dynamic scoping.

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ Blog człowieka poczciwego.