[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Having a block executed in the context of an instance

Clint

3/8/2006 1:16:00 AM

I'm writing a property driven ui and would like to do things like:

button = Button.new do
caption = 'Click Me'
end

I've read that 2.0 will have this feature, i.e. Class.new will execute it's
block argument in it's own context. But how do I do it in 1.8?

Thanks much,
Mike
22 Answers

Ara.T.Howard

3/8/2006 1:33:00 AM

0

Clint

3/8/2006 2:29:00 AM

0

ara.t.howard@noaa.gov wrote:
> On Wed, 8 Mar 2006, Mike Austin wrote:
>
>> I'm writing a property driven ui and would like to do things like:
>>
>> button = Button.new do
>> caption = 'Click Me'
>> end
>>
>> I've read that 2.0 will have this feature, i.e. Class.new will execute
>> it's block argument in it's own context. But how do I do it in 1.8?
>>
>> Thanks much,
>> Mike
>
> class Button
> def initialize(*args, &block)
> instance_eval &block
> end
> end
>
> note that you'll need to do
>
> self.caption = 'Click Me'

Thanks, that works well. But as you note, prepending 'self' kind of defeats
the purpose ;) Is there a way to make Ruby not create local variables, but use
'local var' or similar? Io (www.iolanguage.com) has this problem early on
and was solved by using := for creating slots, and = for updating slots. It
would be nice if it could be lenient when running in irb, and more strict when
executing .rb files.

> or else caption will be a local variable. for an elegant work around
> see the
> metakoan quiz or my traits library. with it a really nice syntax like
> this is
> possible

Metakoan quiz didn't turn up anything. I looked at your traits library and it
looks nice. I could use an operator instead of '=' I suppose.

> button = Button.new {
> caption 'Click Me'
> colour 'Orange'
> size '42'
> }
>
> here's a real example from something i'm coding now:
>
>
> class Flo5 < NRT::OLSSubscription::Geotiffed
> mode "production"
>
> roi 47,16,39,27
>
> satellites %w( F15 F16 )
>
> extensions %w( OIS )
>
> solarelevations -180, -12, 10.0
>
> hold 0
>
> username "flo"
>
> password "xxx"
>
> orbital_start_direction "descending"
>
> start_time "2004-12-08"
> end_time "2006-12-08"
>
> to_keep [ %r/.tif$/, %r/.hdr$/ ]
>
> tmpwatch "8 days"
> end
>
>
> hth.
>
>
> -a

Mike

Erik Veenstra

3/8/2006 6:39:00 AM

0

> button = Button.new do
> caption = 'Click Me'
> end

Executing a block in another context isn't very readable. Ara's
example is not the same as your situation. His situation is an
example of a DSL, whereas your situation is just plain Ruby.
So, IMHO, it should be coded in just plain Ruby:

class Button
def initialize
yield(self)
end
end

button = Button.new do |b|
b.caption = 'Click Me'
end

Now it's obvious (by reading, not by knowing) what the block
does.

gegroet,
Erik V. - http://www.erikve...

Robert Klemme

3/8/2006 11:06:00 AM

0

Mike Austin wrote:
> Thanks, that works well. But as you note, prepending 'self' kind of
> defeats the purpose ;) Is there a way to make Ruby not create local
> variables, but use 'local var' or similar?

No, there isn't. However, often using a hash as argument solves this
problem:

class Foo
def initialize(h={})
h.each {|var,val| send("#{var}=", val)}
end
end

Foo.new(
:caption => 'Click me',
:color => :orange,
:size => 42
)

With a bit more code you can even have default values.

Kind regards

robert

Timothy Goddard

3/8/2006 11:07:00 AM

0

In my opinion, this is unneccesary and still a bit confusing unless the
object has a limited lifetime (as in the case of IO resources) or will
change state when the block is ended. You could use:

button = Button.new
button.caption = 'Click Me'

Blocks are good for DSLs or management of _limited_ resources. It is a
bad idea to use the new method to provide a limited resource as this
will impair forward-compatability. A different method should be used
(and new possibly made private) to enable future change.

For button management I would use something along the lines of the DSL
outlined above but would use additional blocks in the same scope to
handle events.

button = Button.new do
caption "Click Me" # Public method, button.caption and
button.caption= useable from outside

on_click do
caption "You Clicked Me!" # Can update attributes in response to
events with very little extra work.
end
end

Its Me

3/8/2006 2:35:00 PM

0


"Mike Austin" <noone@nowhere.com> wrote

> Thanks, that works well. But as you note, prepending 'self' kind of
> defeats the purpose ;) Is there a way to make Ruby not create local
> variables, but use 'local var' or similar? Io (www.iolanguage.com) has
> this problem early on and was solved by using := for creating slots, and =
> for updating slots.

I personally would like some such distinction. I don't having to use
"self.att=" since
(a) one does not use self.method(..) in general
(b) self.method(..) has different privacy rules
(c) self.attr= is an exception to both (a) and (b)

Ara's
attr(new_val)
works, but
(a) does not read like a setter, and
(b) is against the standard Ruby family of attr.. methods

I wouldn't hold my breath for := or equivalent :-)


dblack

3/8/2006 2:57:00 PM

0

Tim Hunter

3/8/2006 3:04:00 PM

0

dblack@wobblini.net wrote:

> I have to say, I've been wondering for many years... is self.x = 1
> really *that* bad? It just seems like such a minor thing to me. I
> certainly wouldn't want to see new punctuation introduced just to
> avoid it.

+1

Gary Wright

3/8/2006 4:03:00 PM

0


On Mar 8, 2006, at 9:56 AM, dblack@wobblini.net wrote:
> I have to say, I've been wondering for many years... is self.x = 1
> really *that* bad? It just seems like such a minor thing to me. I
> certainly wouldn't want to see new punctuation introduced just to
> avoid it.

It isn't *that* bad but it stands out since the rest of Ruby is
*that* good!

I think it is the old battle between 'perfect' and 'good enough'.

Gary Wright





Clint

3/8/2006 4:27:00 PM

0

rmagick@gmail.com wrote:
> dblack@wobblini.net wrote:
>
>> I have to say, I've been wondering for many years... is self.x = 1
>> really *that* bad? It just seems like such a minor thing to me. I
>> certainly wouldn't want to see new punctuation introduced just to
>> avoid it.
>
> +1

It may be a minor syntax thing, but I think it creates unnecessary ambiguity.
If there is a method called caption=(), I expect it to use that. I don't write
'self' anywhere else in Ruby, so it just seems odd. Plus is helps reduce hard
to debug locals creation by misspellings.

class Button
attr :caption, true

def initialize(*args, &block)
instance_eval &block
end
end

button = Button.new do
var :x
caption = 'Click Me'
end

There is already 'attr' for classes, why not 'local' or 'var' for methods? One
issue is that you can't assign and declare on the same line. It could be done
with a hash but that might look funny?

Take this all with a grain of salt. I'm always looking for different ways of
doing things. I.e. to find good ideas you have to find bad ideas ;)


Mike