*with* block?

If you're just after configuring the instance variables, you might go
for:

my_obj = boxWidget.new
my_obj.instance_eval do
  @x = 0
  @y = 10
  @width = 100
  @height = 100
end

Though doing so will make you code fairly fragile - setting variables in
this way will bypass the setters, so you can't customize your setting
actions. (I was suprised that instance_eval didn't actually grant the
ability to call methods on the object without prefixing them)

Something like this maybe?

class BoxWidget
  attr_accessor :x, :y, :width, :height
end

class Object
  def set_all(hash)
    hash.each { |k,v| send("#{k}=", v) }
  end
end

my_obj = BoxWidget.new
my_obj.set_all({
  :x => 10,
  :y => 10,
  :width => 100,
  :height => 100,
})

my_obj

=> #<BoxWidget:0x2caa6d0 @y=10, @x=10, @height=100, @width=100>

···

-----Original Message-----
From: Zach Dennis [mailto:zdennis@mktec.com]
Sent: Tuesday, 24 August 2004 11:09 AM
To: ruby-talk ML
Subject: *with* block?

I am looking for a structure like:

my_obj = boxWidget.new
with my_obj do
    x = 0
    y = 10
    width = 100
    height = 100
end

instead of having to say

my_obj = boxWidget.new
my_obj.x = 0
my_obj.y = 10
my_obj.width = 100
my_obj.height = 100

Can you do this already? If not....anyone support an RCR for
it besides me?

Zach

#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################

Hi --

If you're just after configuring the instance variables, you might go
for:

my_obj = boxWidget.new
my_obj.instance_eval do
  @x = 0
  @y = 10
  @width = 100
  @height = 100
end

Though doing so will make you code fairly fragile - setting variables in

sub(/fairly/,"extremely") :slight_smile: There's absolutely no guarantee of a
one-to-one correspondence between instance variables and setter/getter
methods -- and the way those methods are implemented could even change
from one release of a library to another.

this way will bypass the setters, so you can't customize your setting
actions. (I was suprised that instance_eval didn't actually grant the
ability to call methods on the object without prefixing them)

It's because it's a parse-time thing: all the bare identifiers on the
left of ='s are designated local variables. So #instance_eval is in
the same boat as other contexts (instance methods, etc.). Also, its
block acts as a closure:

  a = 1
  "".instance_eval { a = 2 } # pointless, but just to illustrate
  p a # 2

David

···

On Tue, 24 Aug 2004, Daniel Sheppard wrote:

--
David A. Black
dblack@wobblini.net

If the following syntax is acceptable

my_obj.with do
   x = 0
  y = 10
  width = 100
  height = 100

···

On Tue, Aug 24, 2004 at 11:15:26AM +0900, David A. Black wrote:

> my_obj = boxWidget.new
> my_obj.instance_eval do
> @x = 0
> @y = 10
> @width = 100
> @height = 100
> end
>
> Though doing so will make you code fairly fragile - setting variables in

sub(/fairly/,"extremely") :slight_smile: There's absolutely no guarantee of a
one-to-one correspondence between instance variables and setter/getter
methods -- and the way those methods are implemented could even change
from one release of a library to another.

  _
end

you can make it 'setter-safe' (i.e. go through the normal attribute
setters instead of bypassing them and assigning to the iv.s directly)
trivially with Kernel#local_variables.

You'll have to make sure you are introducing new variables (not reusing
the ones from the outer scope) though, since otherwise there's no way
to know which locals you used in the with block, short of using
set_trace_func or doing my_obj.with %{ ..... }.

And this won't work with Rite.

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

you can make it 'setter-safe' (i.e. go through the normal attribute
setters instead of bypassing them and assigning to the iv.s directly)
trivially with Kernel#local_variables.

clever

You'll have to make sure you are introducing new variables (not reusing
the ones from the outer scope) though, since otherwise there's no way
to know which locals you used in the with block, short of using
set_trace_func or doing my_obj.with %{ ..... }.

And this won't work with Rite.

why's that?

p.s. are we going to get &{ ... } shorthand for lambda?

···

On Tuesday 24 August 2004 05:11 am, Mauricio Fernández wrote:

--
T.

Hi --

If the following syntax is acceptable

my_obj.with do
   x = 0
  y = 10
  width = 100
  height = 100
  _
end

you can make it 'setter-safe' (i.e. go through the normal attribute
setters instead of bypassing them and assigning to the iv.s directly)
trivially with Kernel#local_variables.

If you're trying to fight back against Ruby's need for an explicit
receiver in assignment-style method calls, I think you've won a bit of
a Pyrrhic victory. That looks like a bunch of assignments to local
variables; I wouldn't want to have to train my eye to find the word
"with" and then figure out that Ruby's normal assignment behavior was
temporarily suspended. That's a heavy price to pay for avoiding a few
occurrences of the word 'self' (or 'some_obj', etc.).

David

···

On Tue, 24 Aug 2004, Mauricio Fernández wrote:

--
David A. Black
dblack@wobblini.net

In Rite,

def foo
  [0].each{ a = 1 }
  p a #=> 1
end

will work, which means that variables introduced in the block will
belong to the method, and the only way to create block local vars will
be using local{|your,locals,here| ..... } or adding them to the
parameter list, so you'd have to write the with construction
as follows:

  foo.with do |x,y|
     x = 1
   y = 2

···

On Tue, Aug 24, 2004 at 07:24:07PM +0900, T. Onoma wrote:

On Tuesday 24 August 2004 05:11 am, Mauricio Fernández wrote:
> you can make it 'setter-safe' (i.e. go through the normal attribute
> setters instead of bypassing them and assigning to the iv.s directly)
> trivially with Kernel#local_variables.

clever

> You'll have to make sure you are introducing new variables (not reusing
> the ones from the outer scope) though, since otherwise there's no way
> to know which locals you used in the with block, short of using
> set_trace_func or doing my_obj.with %{ ..... }.

> And this won't work with Rite.

why's that?

   _
  end

Otherwise it would work only once in a given scope, cause when running
the second instance of whatever.with{...}, the locals introduced in
the previous block would already be there and it would be impossible to
know what has been assigned in the block, unless you do some ugly hack
like assigning some NotSetValue to all those locals before eval'ing the
block and then verifying which ones have been set to something else.
But this wouldn't be thread safe (if you want several threads within
the same method/scope, that is)...

p.s. are we going to get &{ ... } shorthand for lambda?

I'd search the RCRs to see if this has been proposed formally in the
past, but rcrchive.net seems to be down...

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Hi --

···

On Tue, 24 Aug 2004, T. Onoma wrote:

p.s. are we going to get &{ ... } shorthand for lambda?

There was a recent discussion of this, somewhere in the thread that
started at 108059.

David

--
David A. Black
dblack@wobblini.net

For the matter, if you want you can keep

my_obj.with do
  @x = 0
  @y = 10
  @width = 100
  @height = 100
end

while making it 'accessor-safe'. One only has to create a throw-away
object to capture the values and inject them into the accessors.

Now, you might argue that this could be tricky for the untrained eye
because what looks like a normal assignment to instance variables is
transformed into a method call, and I'd rather agree.

So the problem is not as much what can be done in Ruby, as what we want
to take a "being Ruby" or simple/obvious enough, or not contradicting
the "normal rules".

Whether we can take all the features/techniques used in the stdlib as
a reference for what's Ruby and what isn't, and therefore declare the
things not there as un-Ruby, is an open issue. Of course, only matz
can really tell what is Ruby and what isn't.

I think the above might not be interesting for general usage, but in
some cases it could be useful (for instance when one disguises Ruby as
a domain specific language, in which case there is no concern about the
"Ruby nature" of the resulting language)

···

On Tue, Aug 24, 2004 at 07:49:19PM +0900, David A. Black wrote:

If you're trying to fight back against Ruby's need for an explicit
receiver in assignment-style method calls, I think you've won a bit of
a Pyrrhic victory. That looks like a bunch of assignments to local
variables; I wouldn't want to have to train my eye to find the word
"with" and then figure out that Ruby's normal assignment behavior was
temporarily suspended. That's a heavy price to pay for avoiding a few
occurrences of the word 'self' (or 'some_obj', etc.).

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Hi --

···

On Tue, 24 Aug 2004, Mauricio Fernández wrote:

I'd search the RCRs to see if this has been proposed formally in the
past, but rcrchive.net seems to be down...

(Why doesn't anyone ever tell me? :slight_smile:

It's back up.

David

--
David A. Black
dblack@wobblini.net

Hi --

> If you're trying to fight back against Ruby's need for an explicit
> receiver in assignment-style method calls, I think you've won a bit of
> a Pyrrhic victory. That looks like a bunch of assignments to local
> variables; I wouldn't want to have to train my eye to find the word
> "with" and then figure out that Ruby's normal assignment behavior was
> temporarily suspended. That's a heavy price to pay for avoiding a few
> occurrences of the word 'self' (or 'some_obj', etc.).

For the matter, if you want you can keep

my_obj.with do
  @x = 0
  @y = 10
  @width = 100
  @height = 100
end

while making it 'accessor-safe'. One only has to create a throw-away
object to capture the values and inject them into the accessors.

Now, you might argue that this could be tricky for the untrained eye
because what looks like a normal assignment to instance variables is
transformed into a method call, and I'd rather agree.

I would argue also that it's tricky for the trained eye :slight_smile:

So the problem is not as much what can be done in Ruby, as what we want
to take a "being Ruby" or simple/obvious enough, or not contradicting
the "normal rules".

Whether we can take all the features/techniques used in the stdlib as
a reference for what's Ruby and what isn't, and therefore declare the
things not there as un-Ruby, is an open issue. Of course, only matz
can really tell what is Ruby and what isn't.

I take Ruby as a message from Matz as to what is Ruby :slight_smile: And if you
write something in Ruby, then what you've written is a Ruby program --
so if Ruby contains the seeds of its own alteration, then so be it.

But I don't think the case we're talking about really has to get that
philosophical. I'm thinking more in practical terms, that having "x =
10" occasionally be a method call, when it (normally, by default, in
"current Ruby", whatever) isn't, would be confusing and awkward, with
no gain.

I think the above might not be interesting for general usage, but in
some cases it could be useful (for instance when one disguises Ruby as
a domain specific language, in which case there is no concern about the
"Ruby nature" of the resulting language)

Definitely. I think Ruby can and should be used for all sorts of
things, including domain-specific languages. In such a case there's a
clarity of context and expectation which is very different from just
having a method or two in Ruby inside of whose code blocks the rules
of assignment are rewritten.

David

···

On Tue, 24 Aug 2004, Mauricio Fernández wrote:

On Tue, Aug 24, 2004 at 07:49:19PM +0900, David A. Black wrote:

--
David A. Black
dblack@wobblini.net

my_obj.with (
  x: 0,
  y: 10
  width: 100
  height: 100
)

Ruby2 ?

···

On Tuesday 24 August 2004 07:21 am, Mauricio Fernández wrote:

my_obj.with do
  @x = 0
  @y = 10
  @width = 100
  @height = 100
end

--
T.

Mind packaging Arrow and submitting to the repository?

http://www.rubycrafters.com/projects/Arrow/

···

----------------------------------------
-- Name: David Ross
-- Phone: 865.539.3798
-- Email: drossruby [at] yahoo [dot] com
----------------------------------------

_______________________________
Do you Yahoo!?
Win 1 of 4,000 free domain names from Yahoo! Enter now.
http://promotions.yahoo.com/goldrush

This won't work for method calls, though, will it? What would be really
nice is

my_obj.with {
  .x = 1
  .y = 2
  .move_to(10,10)
  .col = :RED
  .repaint
}

martin

···

T. Onoma <transami@runbox.com> wrote:

On Tuesday 24 August 2004 07:21 am, Mauricio Fernández wrote:
> my_obj.with do
> @x = 0
> @y = 10
> @width = 100
> @height = 100
> end

my_obj.with (
  x: 0,
  y: 10
  width: 100
  height: 100
)

Ruby2 ?

It looks nice, but it spawns a series of other ports as dependencies.
http://dev.rubycrafters.com/arrow-manual/install.html#ruby_libs

+1 , though

···

On Wed, 25 Aug 2004 00:48:50 +0900, David Ross <drossruby@yahoo.com> wrote:

Mind packaging Arrow and submitting to the repository?

http://www.rubycrafters.com/projects/Arrow/

----------------------------------------
-- Name: David Ross
-- Phone: 865.539.3798
-- Email: drossruby [at] yahoo [dot] com
----------------------------------------

_______________________________
Do you Yahoo!?
Win 1 of 4,000 free domain names from Yahoo! Enter now.
http://promotions.yahoo.com/goldrush

--
--- vruz

> my_obj.with (
> x: 0,
> y: 10
> width: 100
> height: 100
> )
>
> Ruby2 ?

This won't work for method calls, though, will it?

The #with method would be defined to act just like the earlier given #set_all
example (no instance_eval). That's all.

What would be really
nice is

my_obj.with {
  .x = 1
  .y = 2
  .move_to(10,10)
  .col = :RED
  .repaint
}

and

  ..class_method

instead of

  self.class.class_method

?

I agree that would be nice shorthand for self, if it could be done. Either
that or perhaps:

  my_obj.with {
    @.x = 1
    @.y = 2
    @.move_to(10,10)
    @.col = :RED
    @.repaint
  }

so

  @. == self
  @@. == self.class

···

On Tuesday 24 August 2004 10:25 am, Martin DeMello wrote:

--
T.

I have packaged the sw. that was requested in
http://rpa-base.rubyforge.org/wiki/wiki.cgi?Package_Requests
and most of Arrow's dependencies. It won't take too long before that
gets packaged too.

Today, I've uploaded the following:

formvalidator 0.1.3-1 Form validation library.
gurgitate-mail 1.4-1 An easy-to-use mail filter.
html-parser 19990912-1 Parser for SGML and HTML documents.
pluginfactory 0.01-1 Factory pattern implementation with on-demand subclasses loading.
prettyexception 0.9.3-1 Create prettified HTML output for Ruby exceptions.
rbtree 0.1.2-1 Red-Black tree implementation.
rpa-base 0.2.1-2 A port/package manager for the Ruby Production Archive (RPA)

aeditor 1.7 will be packaged as soon as rcrchive.net gets up (hint, hint :slight_smile:

···

On Wed, Aug 25, 2004 at 08:01:11AM +0900, vruz wrote:

It looks nice, but it spawns a series of other ports as dependencies.
http://dev.rubycrafters.com/arrow-manual/install.html#ruby_libs

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

T. Onoma said:

I agree that would be nice shorthand for self, if it could be done. Either
that or perhaps:

  my_obj.with {
    @.x = 1
    @.y = 2
    @.move_to(10,10)
    @.col = :RED
    @.repaint
  }

Well, how about ...

  module Kernel
    def with(obj) yield(obj) end
  end

  with obj do |s|
    s.x = 1
    s.y = 2
    s.move_to(10,10)
    s.col = :RED
    s.repaint
  end

"s" is easier to type than "@".

Hmmm, some people might find "s" rather non-mnemonic. Perhaps this is
better ...

  with obj do |obj|
    obj.x = 1
    obj.y = 2
    # ...
  end

···

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

hehe nice joke

···

On Wed, Aug 25, 2004 at 08:38:19PM +0900, Jim Weirich wrote:

  with obj do |obj|
    obj.x = 1
    obj.y = 2
    # ...
  end

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

but still useful, if you're programming with e.g. FXRuby,
as you can do something like the following (pseudo-code)

with FX.create do |parent|
  FX.create_child(parent)
end

and avoid cluttering of local namespace.

s.

···

On Wed, 25 Aug 2004 21:07:01 +0900, Mauricio Fernández <batsman.geo@yahoo.com> wrote:

On Wed, Aug 25, 2004 at 08:38:19PM +0900, Jim Weirich wrote:

  with obj do |obj|
    obj.x = 1
    obj.y = 2
    # ...
  end

hehe nice joke

Stefan Schmiedl wrote:

···

On Wed, 25 Aug 2004 21:07:01 +0900, > Mauricio Fernández <batsman.geo@yahoo.com> wrote:

On Wed, Aug 25, 2004 at 08:38:19PM +0900, Jim Weirich wrote:

with obj do |obj|
   obj.x = 1
   obj.y = 2
   # ...
end

hehe nice joke

but still useful, if you're programming with e.g. FXRuby,
as you can do something like the following (pseudo-code)

with FX.create do |parent|
  FX.create_child(parent)
end

and avoid cluttering of local namespace.

...unless parent is already in the namespace. (Of course that may change in future ruby.)

But it's a good point anyway. I often define #initialize to 'yield self if block_given?', but this version of #with is a way of getting that effect without touching initialize. Nice.