[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Re: Request for Block local methods, and Proc syntax

Joshua Ballanco

9/2/2008 11:45:00 AM

Patrick Li wrote:
> 2) Procs without proc keyword.
>
> Is there any reason why we need a proc keyword in front of a block?

Well, it's not exactly what you're looking for, but Ruby 1.9 has
introduced the "->" notation for closures. It takes a bit of getting
used to, but personally I rather like it. See
http://eigenclass.org/hiki.rb?Changes+in+R... for more info
(except it's no longer experimental).

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

7 Answers

Patrick Li

9/2/2008 6:52:00 PM

0

Thanks for your input guys.

I want to say that I do really like Ruby. I'm just probing to see if
there's improvements that can still be made, or whether it's as good as
it can be already.

Oh, and I do realize the ambiguity of my last example.

Here's my thoughts on that:

I think you should ALWAYS be able to retrieve the "context" of an object
given an object reference.

In compiled, statically-typed languages such as C++ or Java.
objects can access their "class context" by using:
obj.class

They cannot access their "block context", by well they don't have to,
because Java blocks aren't first-class objects like they are in Ruby.

I think, given an object, you should be able to access their
"block"/"scope", because Ruby actually treats them as first-class
objects.

So my example would look something like this:

block.scope.instance_eval do
def myMethod
end
end

Anyway, thanks for the discussion. It's nice to read a thoughtful
response.
-Patrick

PS: I am actually currently investigating Smalltalk. I like the syntax,
and the system, but Ruby does have one big advantage over it. It's
standardized.
I can't even find a book that discusses the Smalltalk in depth, because
there's so many different versions.
--
Posted via http://www.ruby-....

Robert Klemme

9/3/2008 7:26:00 AM

0

2008/9/2 Patrick Li <patrickli_2001@hotmail.com>:
> Thanks for your input guys.

You're welcome!

> I want to say that I do really like Ruby. I'm just probing to see if
> there's improvements that can still be made, or whether it's as good as
> it can be already.

I have a different approach: I like the challenge to get things
working - without trying to change the language. Actually I believe,
most of the time language changes are not worthwhile because of the
huge potential to wreck havoc on code - and if the language changes a
lot code is affected. You can see that from discussions and change
notices for even the comparatively small changes that have been done
for 1.9.

> Oh, and I do realize the ambiguity of my last example.
>
> Here's my thoughts on that:
>
> I think you should ALWAYS be able to retrieve the "context" of an object
> given an object reference.

How does this help the parser in detecting whether it's a proc /
lambda or a Hash? Runtime access to the binding does not help here at
all.

> In compiled, statically-typed languages such as C++ or Java.
> objects can access their "class context" by using:
> obj.class

Well, yes, but with significant differences to Ruby. C++ has
extremely limited capabilities in that area. Did you mean C#?

> They cannot access their "block context", by well they don't have to,
> because Java blocks aren't first-class objects like they are in Ruby.

Actually, you can have a kind of closures in Java as well - although
not as elegant as in Ruby.

interface Foo {
void bar();
}

public static void doit(Foo f) {
f.bar();
}

public static void test() {
final int i = 10;
doit( new Foo() {
void bar() {
System.out.println("i is " + i);
}
} );

> I think, given an object, you should be able to access their
> "block"/"scope", because Ruby actually treats them as first-class
> objects.

There is no general "scope" of an object since you can have multiple
references to any object. The notion of "scope of an object" does not
make sense in Ruby.

Btw, your functionality can be achieved without language changes by
applying a small change to my first version:

09:29:38 Temp$ ruby dm2.rb
intro
An image "test"
An image 999
extro
09:30:18 Temp$ cat dm2.rb
def html(&block)
context = Object.new
orig = eval("self", block.binding)
orig.instance_variables.each do |var|
context.instance_variable_set(var, orig.instance_variable_get(var))
end

def context.image(x)
puts "An image #{x.inspect}"
end

context.instance_eval &block
end

@foo = "test"
def bar() 999 end

html do
puts "intro"
image @foo
image bar
puts "extro"
end

Cheers

robert

--
use.inject do |as, often| as.you_can - without end

Patrick Li

9/4/2008 2:34:00 PM

0

So I thought about your code snippet a bit more Robert, and it's almost
what I need. Which is, the ability to access the local scope, but also
have access to the methods that are granted by the html-do-end method.

so in your example, you can now do this:

html do
image(@source)
end

but you still can't do something this:

html do
@code = retrieveCode
end
puts @code <-- doesn't work, because this is a different @code than the
one you assigned to.

I got around this by writing all the instance variables in "context" out
again at the end of the block. But it's not a very clean solution.

Is there anyway to retrieve the current block from within the block?
ie...

block = lambda do
//bla bla bla
//how does a block refer to itself?
end

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

Robert Klemme

9/4/2008 3:10:00 PM

0

2008/9/4 Patrick Li <patrickli_2001@hotmail.com>:

> I got around this by writing all the instance variables in "context" out
> again at the end of the block. But it's not a very clean solution.

Well, but it works remarkably well, doesn't it?

> Is there anyway to retrieve the current block from within the block?
> ie...
>
> block = lambda do
> //bla bla bla
> //how does a block refer to itself?
> end

As blocks have no conscience there is no way they know about
themselves - at least none that I would be aware of. :-)

Kind regards

robert

--
use.inject do |as, often| as.you_can - without end

Patrick Li

9/4/2008 4:07:00 PM

0

Mmm, that throws a wrench in things... well if I figure out how to do
proper dsl's with access to scope, I'll post it up here.

Thanks for your help and patience Robert
--
Posted via http://www.ruby-....

David A. Black

9/4/2008 4:18:00 PM

0

Hi --

On Thu, 4 Sep 2008, Patrick Li wrote:

> So I thought about your code snippet a bit more Robert, and it's almost
> what I need. Which is, the ability to access the local scope, but also
> have access to the methods that are granted by the html-do-end method.
>
> so in your example, you can now do this:
>
> html do
> image(@source)
> end
>
> but you still can't do something this:
>
> html do
> @code = retrieveCode
> end
> puts @code <-- doesn't work, because this is a different @code than the
> one you assigned to.
>
> I got around this by writing all the instance variables in "context" out
> again at the end of the block. But it's not a very clean solution.

I personally dislike the "stealth" instance_eval, since it does indeed
look like instance variables belong to one object when they actually
belong to another. One thing you can do:

class C
def some_method
yield self
end
end

@a = 1
C.new.some_method do |c|
c.another_method(@a) # etc.
end

so that you have the object you need but without changing 'self'
during the block.


David

--
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL *
* Co-taught with Patrick Ewing!
See http://www.r... for details and updates!

ara.t.howard

9/4/2008 4:21:00 PM

0


On Sep 4, 2008, at 8:34 AM, Patrick Li wrote:

>
> but you still can't do something this:
>
> html do
> @code = retrieveCode
> end
> puts @code <-- doesn't work, because this is a different @code than
> the
> one you assigned to.
>
>

sure you can:

require 'rubygems'
require 'tagz'
include Tagz.globally


content =
html_{
body_{
@code = 42
}
}

puts @code

puts content



cfp:~ > ruby a.rb
42
<html><body>42</body></html>


you just have to be clever about when methods are in effect - check
out the tagz source for an example of this.


alternatively you can skin it this way pushing and popping methods on
the object in question:


cfp:~ > cat a.rb

content =
html do
body do
img do
@code = 42
end
end
end

y 'content' => content, '@code' => @code




BEGIN {
module Html
Methods = lambda do
def body &block
"<body>#{ block.call }</body>"
end

def img &block
"<img>#{ block.call }</img>"
end
end

def Methods.new
Module.new do
module_eval &Methods
def self.delete!() instance_methods.each{|m| remove_method m}
end
end
end

def Methods.push object
singleton_class_for(object) do
include(( @html_methods = Methods.new )) unless @html_methods
end
end

def Methods.pop object
singleton_class_for(object) do
@html_methods.delete! if @html_methods
end
end

def Methods.singleton_class_for object, &block
singleton_class =
class << object
self
end
block ? singleton_class.module_eval(&block) : singleton_class
end
end

def html &block
Html::Methods.push self
content = instance_eval(&block)
"<html>#{ content }</html>"
ensure
Html::Methods.pop self
end

require 'yaml'
}




cfp:~ > ruby a.rb
---
"@code": 42
content: <html><body><img>42</img></body></html>



you'll have to try harder than that before proposing changes to the
language ;-)

cheers


a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama