Having a block executed in the context of an instance

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'

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

   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

···

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

--
judge your success by what you had to give up in order to get it.
- h.h. the 14th dali lama

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

···

ara.t.howard@noaa.gov wrote:

On Wed, 8 Mar 2006, Mike Austin wrote:

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.erikveen.dds.nl/

Well I found out either way I go with passing a block to Button.new(), it doesn't work very well because subclasses' initialize() is called afterwards and clobbers the changes :slight_smile: So I just have another method called init().

....
   def init()
     yield self
     return self
   end
....

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

Mike

···

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'

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

  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

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

Mike Austin wrote:

Thanks, that works well. But as you note, prepending 'self' kind of
defeats the purpose :wink: 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

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

···

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

Thanks, that works well. But as you note, prepending 'self' kind of
defeats the purpose :wink: 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.

Hi --

···

On Wed, 8 Mar 2006, itsme213 wrote:

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

Thanks, that works well. But as you note, prepending 'self' kind of
defeats the purpose :wink: 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 :slight_smile:

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.

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black

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

···

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.

How about allowing

.attr = val

as a shortcut for

self.attr = val

It's no "new" punctuation and I can't see any ambiguities with current ruby syntax (correct me if I'm wrong).

Just an idea.

Dominik

···

On Wed, 08 Mar 2006 15:56:53 +0100, <dblack@wobblini.net> wrote:

Hi --

On Wed, 8 Mar 2006, itsme213 wrote:

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

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.

rmagick@gmail.com 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 :wink:

Mike

···

dblack@wobblini.net wrote:

Hmmmmmm, It's shorter than self.attr, but on the other hand it's uglier IMO. One question I would have to wonder is:

self.method( ) # definitely not private
method( ) # definitely private
self.x = y # could be public or private
.x # probably(?) not private ???
.x = y # ???

Oh wait I take the whole thing back, naked method( ) could be public too. I guess throwing .x in there doesn't make the visibility any more confusing

···

On Mar 8, 2006, at 2:09 PM, Dominik Bathon wrote:

On Wed, 08 Mar 2006 15:56:53 +0100, <dblack@wobblini.net> wrote:

Hi --

On Wed, 8 Mar 2006, itsme213 wrote:

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

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.

How about allowing

.attr = val

as a shortcut for

self.attr = val

It's no "new" punctuation and I can't see any ambiguities with current ruby syntax (correct me if I'm wrong).

Just an idea.

Dominik

Hi --

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.

You can look at it the other way around, though: you *always* specify
a receiver explicitly in Ruby, except in the one case where the
receiver is self and the syntax is such as to be unambiguously a
method call.

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?

I'm not seeing the connection between the two halves of that sentence
:slight_smile: I don't think the existence of the attr_* methods implies that
Ruby should adopt a system of variable declaration. (At least, I
don't see how one follows from the other.) But I'm not sure I'm
understanding you correctly.

David

···

On Thu, 9 Mar 2006, Mike Austin wrote:

rmagick@gmail.com wrote:

dblack@wobblini.net wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

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

If you don't mind dropping the equals sign it's a pretty easy fix. At that
point you could even do some method_missing magic and have it check for
existing attributes and use those.

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

And as david said, really the lack of a receiver is the exception not the
rule.

Mike

···

On 3/8/06, Mike Austin <noone@nowhere.com> wrote:

rmagick@gmail.com wrote:
> dblack@wobblini.net wrote:

--
===Tanner Burson===
tanner.burson@gmail.com
http://tannerburson.com <---Might even work one day...

Hi --

Hi --

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

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.

How about allowing

.attr = val

as a shortcut for

self.attr = val

It's no "new" punctuation and I can't see any ambiguities with current ruby syntax (correct me if I'm wrong).

Just an idea.

Dominik

Hmmmmmm, It's shorter than self.attr, but on the other hand it's uglier IMO. One question I would have to wonder is:

self.method( ) # definitely not private
method( ) # definitely private
self.x = y # could be public or private
.x # probably(?) not private ???
.x = y # ???

Oh wait I take the whole thing back, naked method( ) could be public too. I guess throwing .x in there doesn't make the visibility any more confusing

I wonder how the parser would handle:

   obj .x

i.e., whether it would be:

   obj.x

or

   obj(.x)

David

···

On Thu, 9 Mar 2006, Logan Capaldo wrote:

On Mar 8, 2006, at 2:09 PM, Dominik Bathon wrote:

On Wed, 08 Mar 2006 15:56:53 +0100, <dblack@wobblini.net> wrote:

On Wed, 8 Mar 2006, itsme213 wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

Not quite. I believe
    self.foo
does completely different privacy checks than just
    foo

Specifically,
    self.foo
on a private foo will fail, while
    self.foo=
on private foo= will succeed.

···

<dblack@wobblini.net> wrote

You can look at it the other way around, though: you *always* specify
a receiver explicitly in Ruby, except in the one case where the
receiver is self and the syntax is such as to be unambiguously a
method call.

I would imagine obj.x since that is the current behavior

···

On Mar 8, 2006, at 9:58 PM, dblack@wobblini.net wrote:

I wonder how the parser would handle:

  obj .x

i.e., whether it would be:

  obj.x

or

  obj(.x)

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

I would say it should be obj.x, as I didn't propose to allow .meth as a general shortcut for self.meth, but only when it is a left hand side of an asignment.

But this leads to:

meth .attr=42

I would say that would also be meth.attr=42 and not meth(.attr=42). If you want the latter, then use brackets.

Dominik

···

On Thu, 09 Mar 2006 03:58:07 +0100, <dblack@wobblini.net> wrote:

On Thu, 9 Mar 2006, Logan Capaldo wrote:

Hmmmmmm, It's shorter than self.attr, but on the other hand it's uglier IMO. One question I would have to wonder is:

self.method( ) # definitely not private
method( ) # definitely private
self.x = y # could be public or private
.x # probably(?) not private ???
.x = y # ???

Oh wait I take the whole thing back, naked method( ) could be public too. I guess throwing .x in there doesn't make the visibility any more confusing

I wonder how the parser would handle:

   obj .x

i.e., whether it would be:

   obj.x

or

   obj(.x)