Keyword "with"

Hi all,

did anybody think of this?

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

It’s so simple that I barely dare to propose it. Of course, one could use
instance_eval directly, but the keyword is IMHO a bit more intuitive and
it is known from other programming languages. (Pascal, which else?)

Now you can do

anAwfulLongIdentifierThatYouWontLiktToTypeOften = “foo”

with anAwfulLongIdentifierThatYouWontLiktToTypeOften do
puts length
concat "bar"
puts length
puts self
end

What do others think? Is this worthwile to be included in the Ruby std
lib?

Regards

robert

Pascal:
http://www.cs.qub.ac.uk/~S.Fitzpatrick/Teaching/Pascal/EBNF.html#with-statement

Yes :slight_smile: Unfortunately ruby-talk.org is down at the moment, but I’ve seen
this suggested several times.

···

On Wed, Jul 16, 2003 at 06:26:04PM +0900, Robert Klemme wrote:

Hi all,

did anybody think of this?

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

Hi all,

did anybody think of this?

Me too :slight_smile:

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

It’s been reinvented several times in the past :slight_smile:

It’s so simple that I barely dare to propose it. Of course, one could use
instance_eval directly, but the keyword is IMHO a bit more intuitive and
it is known from other programming languages. (Pascal, which else?)

Now you can do

anAwfulLongIdentifierThatYouWontLiktToTypeOften = “foo”

with anAwfulLongIdentifierThatYouWontLiktToTypeOften do
puts length
concat “bar”
puts length
puts self
end

What do others think? Is this worthwile to be included in the Ruby std
lib?

Dunno, guess there’s no real interest since this must have been around
for ages now.

···

On Wed, Jul 16, 2003 at 06:26:04PM +0900, Robert Klemme wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Computers are not intelligent. They only think they are.

This has apparently been proposed before. The resistance to
including it may simply come from the fact that, from a general
design perspective, instance_eval is a Bad Thing™. It violates
encapsulation and removes an object’s ability to manage its own data.
There are legitimate uses for it on occasion, so the capability is
good to have, but if it were easier to do, it would probably be
(ab)used more often.

-Mark

···

On Wed, Jul 16, 2003 at 06:41:11PM +0900, Mauricio Fernández wrote:

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030716094107.GA806@student.ei.uni-stuttgart.de

did anybody think of this?

Me too :slight_smile:

Ah, welcome to the club!

It’s been reinvented several times in the past :slight_smile:
[…]
Dunno, guess there’s no real interest since this must have been around
for ages now.

Hm, that is a bit contradicting, don’t you think?

Computers are not intelligent. They only think they are.

What about humans? :slight_smile:

robert
···

On Wed, Jul 16, 2003 at 06:26:04PM +0900, Robert Klemme wrote:

Possibly. Also, doing

def bar
some_long_variable_name.instance_eval {
… code …
}
end

means that ‘code’ loses access to the instance variables of the enclosing
object, so it’s not as useful as you might think.

Regards,

Brian.

···

On Wed, Jul 16, 2003 at 08:27:04PM +0900, Mark J. Reed wrote:

On Wed, Jul 16, 2003 at 06:41:11PM +0900, Mauricio Fernández wrote:

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

This has apparently been proposed before. The resistance to
including it may simply come from the fact that, from a general
design perspective, instance_eval is a Bad Thing™. It violates
encapsulation and removes an object’s ability to manage its own data.

Robert Klemme wrote:

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag

Dunno, guess there’s no real interest since this must have been around
for ages now.

Hm, that is a bit contradicting, don’t you think?

Not really, when someone new comes to ruby they always ask for features
from the language they know best.

The call for pre/post increment/decrement operators is pretty frequent.

We’ve had VB programmers ask for ‘on error gosub’ because they had a
blind spot for exceptions.

We’ve had Java/C++/Whatever programmers ask for type checking, operator
overloading, polymorphism and a whole host of compile time checking.

Lisp programmers have enquired about macros (occasionally).

We’ve had programmers who wanted ‘initialize’ changed to ‘new’ so that
they would have less to type.

And we’ve had tcl/php programmers who wanted elseif rather then elsif
(or was that the other way round).

The common theme is that all these requests come from ‘I am an X
programmer’, where X is the one and only language they understand :slight_smile:

Peter (having a bad day) Hickman

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

This has apparently been proposed before. The resistance to
including it may simply come from the fact that, from a general
design perspective, instance_eval is a Bad Thing™. It violates
encapsulation and removes an object’s ability to manage its own data.

As regards the encapsulation issue – it depends on
how the real ‘with’ was implemented. If it were a
real language construct and not just a call of
instance_eval, then stuff inside the block could be
interpreted as calls to accessors and we could disallow
direct access to instance vars.

Then it just becomes a shorthand – which is the whole
point after all, I think.

Possibly. Also, doing

def bar
some_long_variable_name.instance_eval {
… code …
}
end

means that ‘code’ loses access to the instance variables of the enclosing
object, so it’s not as useful as you might think.

That part can be solved even using the instance_eval
version of ‘with’ – just pass in arguments as they
are needed. A little clunky, of course.

def with(obj,*args,&blk)
obj.instance_eval &blk
end

@foo, @bar = 34,45
with(some_obj,@foo,@bar) do |x,y|
@foo = x + y
end

(Note that the block at the end is a special case –
normally a starred argument can only go at the end.)

The version of this I’m used to is a trifle different –
I added ‘with’ to Object so that I could always do
obj.with { … }

Same thing, of course.

I think a big reason ‘with’ has not been accepted is that
Matz remains unconvinced. It’s rather a Pascalism, and I
recall he said he never liked Pascal.

What’s more, I don’t think it was ever an RCR.

Hal

···

----- Original Message -----
From: “Brian Candler” B.Candler@pobox.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, July 16, 2003 7:03 AM
Subject: Re: Keyword “with”

On Wed, Jul 16, 2003 at 08:27:04PM +0900, Mark J. Reed wrote:

On Wed, Jul 16, 2003 at 06:41:11PM +0900, Mauricio Fernández wrote:


Hal Fulton
hal9000@hypermetrics.com

Hrm, well I’m a Ruby/Java/C/C++/Python/Perl/Lisp/Javascript/PHP…
um… and others programmer.

We’ve had Java/C++/Whatever programmers ask for type checking,
operator overloading, polymorphism and a whole host of compile time
checking.

Is there a good way to get what type checking does for you? Maybe some
kind of ruby-lint program that looks through your source code and tries
to see if you’re making odd assumptions about the type of your
variables? Or (much more useful in my opinion) something that will try
to catch the use of uninitialized variables? This would be helpful in
catching typos, like calling the class variable @my_var, but ending up
using it as @myvar.

Lisp programmers have enquired about macros (occasionally).

Are there good ways of doing what Lisp macros do for you?

Maybe the fact people keep asking for this points to the need for a set
of FAQs that pick features from other languages and explain if they
exist in Ruby, how to use them, and if they’re not there, why not.
Maybe such a FAQ already exists, I don’t know.

Ben

···

On Wednesday, July 16, 2003, at 09:36 AM, Peter Hickman wrote:

Peter (having a bad day) Hickman wrote:

Not really, when someone new comes to ruby they always ask for features
from the language they know best. The common theme is that all these
requests come from ‘I am an X programmer’, where X is the one and only
language they understand :slight_smile:

Given that one of Ruby’s main inspirations is Perl (another
being SmallTalk, obviously), and that Perl has, ahm, “borrowed”
liberally from many other languages, it’s not automatically
unreasonable to add more borrowings to Ruby. Each request should be
considered on its own merits, not dismissed on the basis that the
requestor is “obviously” only trying to make Ruby more Xlike where
X is whatever language they are coming from.

And even if they are looking for Xicity, that doesn’t mean X is the
one and only language they understand; it’s probably the language
that they wound up using because it’s the one they liked the best.
Now they’ve decided they like Ruby better but they would still like
to bring along some of the things that attracted them to language
X in the first place. That doesn’t seem unreasonable to me.

The call for pre/post increment/decrement operators is pretty frequent.

Well, that’s because they’re useful. :slight_smile: I mean, sure, x += 1
works everywhere that ++x would, but if what you really want is
x++ then you have to break it up into two statements. Not that
there’s anything wrong with that; I’m all for legible code. But 30
years after C pushed these operators into the realm of widely-used
high-level programming languages, every programmer on the planet
should be able to understand them instantly; and when you can get
clarity and concision at the same time, that’s the way to go. :slight_smile:

We’ve had VB programmers ask for ‘on error gosub’ because they had a
blind spot for exceptions.

Okay, well, VB programmers don’t count. :wink:

We’ve had Java/C++/Whatever programmers ask for type checking, operator
overloading, polymorphism and a whole host of compile time checking.

That would be a more fundamental change, obviously; Ruby is just not a
strongly-typed language. See Perl prototypes for an example of what happens
when you try to graft on a compromise. I mean, they’re potentially useful
and have a fair amount of power, but they’re rarely used, and when they
are it’s usually just to eliminate the need for extra parentheses
and/or backslashes in the calling code.

Now, as an O-O language Ruby automatically supports some forms
of polymorphism. And I do think it would occasionally result in
clearer code if we could define multiple methods with the same name
distinguished by number of arguments, rather than manually checking
and dispatching within a single method, but that’s a minor quibble.

Lisp programmers have enquired about macros (occasionally).

Metaprogramming in general is quite useful, though ripe for
abuse; see the recent discoveries about C++ templates. (“Hi, I can make
your compiler run arbitrary code at compile time! You don’t even have
to run my code to get infected by my virus, just try to compile it!
Ha! Ha ha ha! Mwa ha ha ha ha ha hah!”)

We’ve had programmers who wanted ‘initialize’ changed to ‘new’ so that
they would have less to type.

Again, I’m all for concision (even though I know that it’s not
a real word), wherever it doesn’t impede clarity. In this case
it would even enhance it - you call MyClass.new and that results
in MyClass#new being executed. Not only less typing, but also
a more logical connection, easier to remember, and no conflicts
since class methods and instance methods have separate namespaces.
Sorry, why is this a bad idea again? :slight_smile:

And we’ve had tcl/php programmers who wanted elseif rather then elsif
(or was that the other way round).

You can’t make everyone happy with your spelling choices, to be sure.
Ruby uses “elsif” because Perl uses “elsif”, and Perl uses “elsif”
because it was more aesthetically pleasing to Larry Wall. Besides,
almost every time you add a suffix to an English word ending in a silent
‘e’, the ‘e’ is dropped first. :slight_smile:

I wouldn’t object to the introduction of “elseif” as a
synonym, just to cut down on typos when people are switching back
and forth between languages. But not “elif”. Have to draw the
line somewhere. :slight_smile:

-Mark

this would be also good for another reason, people will no
longer get confused by mistyping “s” and “z” in initialize :wink:

Richard

···

On Wed, Jul 16, 2003 at 10:36:51PM +0900, Peter Hickman wrote:

We’ve had programmers who wanted ‘initialize’ changed to ‘new’ so that
they would have less to type.

  def with(obj,*args,&blk)
    obj.instance_eval &blk
  end

  @foo, @bar = 34,45
  with(some_obj,@foo,@bar) do |x,y|
    @foo = x + y
  end

Euh, what version of ruby are you using ?

Guy Decoux

Mark J. Reed wrote:

Given that one of Ruby’s main inspirations is Perl (another
being SmallTalk, obviously), and that Perl has, ahm, “borrowed”
liberally from many other languages, it’s not automatically
unreasonable to add more borrowings to Ruby. Each request should be
considered on its own merits, not dismissed on the basis that the
requestor is “obviously” only trying to make Ruby more Xlike where
X is whatever language they are coming from.

This I understand, but I like Ruby, it is very good. However I dislike
Java and would be disappointed with Ruby becoming more Java like. If I
wanted Java like I would use Java itself. At the moment I am coding an
interface to my Ruby / Perl expert system in Tcl/Tk because it provides
the features I require for the interface and I dont have to learn RubyTk
and PerlTk and have the problem of duplicated functionallity (and the
maintenance nightmare that that would involve).

I am not asking for Ruby to be more Tcl like.

If we really wanted a kitchen sink language we would drop Ruby here and
now and start using Lisp and Ada. But no one likes to spend their day at
the kitchen sink.

All I ask it that the request adds functionality to the language and not
sugar. ‘with’, ‘x++’, ‘elseif’, ‘new’ and the rest are just plain sugar.

Actually, VB complements the ‘with’ block with a unary . operator, which
is IMO the cleanest way to scope both local and object variables and
methods. At least, when I thought of the instance_eval/with trick, I
gave up on it because I couldn’t think of a way to simulate unary .s

martin

···

Mark J. Reed markjreed@mail.com wrote:

Okay, well, VB programmers don’t count. :wink:

Is there a good way to get what type checking does for you? Maybe some

catching typos, like calling the class variable @my_var, but ending up
using it as @myvar.

Test First Design?

···


Regards,
JJ

Finally using a Mac!

In article D3E034C6-B798-11D7-ACD8-00039381462A@thingmagic.com,

Hrm, well I’m a Ruby/Java/C/C++/Python/Perl/Lisp/Javascript/PHP…
um… and others programmer.

We’ve had Java/C++/Whatever programmers ask for type checking,
operator overloading, polymorphism and a whole host of compile time
checking.

Is there a good way to get what type checking does for you?

Unit testing.

Maybe some
kind of ruby-lint program that looks through your source code and tries
to see if you’re making odd assumptions about the type of your
variables? Or (much more useful in my opinion) something that will try
to catch the use of uninitialized variables?

Well, that already happens:

def foo(bar)
puts a
end

foo(1)
NameError: undefined local variable or method a' for #<Object:0x401d1ce0> from (irb):5:in foo’
from (irb):8

…OK, admitedly, that’s at runtime, but that’s why you want unit tests.

This would be helpful in
catching typos, like calling the class variable @my_var, but ending up
using it as @myvar.

Lisp programmers have enquired about macros (occasionally).

Are there good ways of doing what Lisp macros do for you?

Perl has input filters (see the perlfilter docs) that sort of act like a pre-processor
for yout source. This was originally intended for encrypting source-code, but now is
used for lots of other purposes. Perl even has a command line argument (-p, I believe)
that will pass the source through the c pre-processor before Perl interprets it.

I wonder how difficult it would be to do input filters for Ruby?

On the otherhand, it’s probably not a feature needed in Ruby as much as it is in Perl.

Maybe the fact people keep asking for this points to the need for a set
of FAQs that pick features from other languages and explain if they
exist in Ruby, how to use them, and if they’re not there, why not.
Maybe such a FAQ already exists, I don’t know.

Ben

Phil

···

Ben Giddings ben@thingmagic.com wrote:

On Wednesday, July 16, 2003, at 09:36 AM, Peter Hickman wrote:

Taking this further, what if you could do (for example):

File.read {
.first_thing_to_do_to_the_file
.second_thing
.and_last_thing
}

instead of

File.read { |f|
f.first_thing_to_do_to_the_file
f.second_thing
f.and_last_thing
}

That is, if you introduce a unary dot operator, why not let it apply by
default to the single argument within a one-argument block?

Whether the above is a horrible idea or a great one, I really savor the
idea of having a “with” as a language construct. I’d want it to be
invokable both ways: Kernel.with(obj) {…} and obj.with {…}.

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

This has apparently been proposed before. The resistance to
including it may simply come from the fact that, from a general
design perspective, instance_eval is a Bad Thing™. It violates
encapsulation and removes an object’s ability to manage its own data.

As regards the encapsulation issue – it depends on
how the real ‘with’ was implemented. If it were a
real language construct and not just a call of
instance_eval, then stuff inside the block could be
interpreted as calls to accessors and we could disallow
direct access to instance vars.

Then it just becomes a shorthand – which is the whole
point after all, I think.

···

On Wednesday, Jul 16, 2003, at 07:59 America/Chicago, Hal E. Fulton wrote:

The version of this I’m used to is a trifle different –
I added ‘with’ to Object so that I could always do
obj.with { … }

Same thing, of course.

I think a big reason ‘with’ has not been accepted is that
Matz remains unconvinced. It’s rather a Pascalism, and I
recall he said he never liked Pascal.

What’s more, I don’t think it was ever an RCR.


John Platte
Principal Consultant, NIKA Consulting
http://nikaconsulting.com/

Peter (having a bad day) Hickman wrote:

[snip]

The call for pre/post increment/decrement operators is pretty
frequent.

Well, that’s because they’re useful. :slight_smile: I mean, sure, x += 1
works everywhere that ++x would, but if what you really want is
x++ then you have to break it up into two statements. [snip]

The x++ operator has been discussed extensively on this list on a
number of occasions. The likelihood of it ever being added to Ruby is
almost infintesimally close to zero. The fundamental reason, I think,
is that a Fixnum object (upon which such an operator would operate)
should never be mutable. The x+=1 operator emphasizes that a new Fixnum
object is being assigned to the applicable variable.

[snip]

We’ve had Java/C++/Whatever programmers ask for type checking,
operator
overloading, polymorphism and a whole host of compile time checking.

That would be a more fundamental change, obviously; Ruby is just not a
strongly-typed language. [snip]

There has been a lot of discussion on the list about this. Not
surprisingly, Dave Thomas’ contributions to the “type” discussions are
extremely lucid and helpful. Ruby is strongly-typed. It is, however,
dynamically typed and one does not declare types for variables (except
deliberately and after creating code to implement variable type
declaration). To the developer, Ruby is “duck-typed” – objects are
defined by the method calls they respond to.

Now, as an O-O language Ruby automatically supports some forms
of polymorphism. And I do think it would occasionally result in
clearer code if we could define multiple methods with the same name
distinguished by number of arguments, rather than manually checking
and dispatching within a single method, but that’s a minor quibble.
[snip]
Not to get into a paean to Dave Thomas, but a powerful way of
approaching this kind of problem area is to define a private initialize
method for a class and then create many methods with different names
that call the initialize method to create different but related
objects. There are some excellent discussions of this in the mailing
list archives.

We’ve had programmers who wanted ‘initialize’ changed to ‘new’ so that
they would have less to type.

Again, I’m all for concision (even though I know that it’s not
a real word), wherever it doesn’t impede clarity. In this case
it would even enhance it - you call MyClass.new and that results
in MyClass#new being executed. Not only less typing, but also
a more logical connection, easier to remember, and no conflicts
since class methods and instance methods have separate namespaces.
Sorry, why is this a bad idea again? :slight_smile:

[snip]

I have never felt the desire to want to change def initialize to def
new. For whatever reason, I have always felt comfortable with using the
word initialize in the “model” part of the design and the word “new” in
the controller part of the design.

Regards,

Mark

···

On Wednesday, July 16, 2003, at 10:28 AM, Mark J. Reed wrote:

“Hal E. Fulton” hal9000@hypermetrics.com schrieb im Newsbeitrag
news:0f0f01c34b9b$1dc0e220$0300a8c0@austin.rr.com

From: “Brian Candler” B.Candler@pobox.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, July 16, 2003 7:03 AM
Subject: Re: Keyword “with”

module Kernel
def with(obj, &blk)
obj.instance_eval &blk
end
end

This has apparently been proposed before. The resistance to
including it may simply come from the fact that, from a general
design perspective, instance_eval is a Bad Thing™. It violates
encapsulation and removes an object’s ability to manage its own
data.

As regards the encapsulation issue – it depends on
how the real ‘with’ was implemented. If it were a
real language construct and not just a call of
instance_eval, then stuff inside the block could be
interpreted as calls to accessors and we could disallow
direct access to instance vars.

Yes, that’s a good point: the instance_eval trick has the drawback that
instance variables of the other instance can be referenced. This can lead
to confusion and errors that are hard to find. I regard this the major
argument against the version of “with” that uses instance_eval.

Thank you all for helping in clearing my mind!

Then it just becomes a shorthand – which is the whole
point after all, I think.

Yes, exactly.

I think a big reason ‘with’ has not been accepted is that
Matz remains unconvinced. It’s rather a Pascalism, and I
recall he said he never liked Pascal.

Ooops… :slight_smile:

(Does anybody listen? No? Ok: I admit that I like Pascal as a language for
learning. It has some shortcomings especially with regard to IO but it
provides a verbose syntax that makes programs easy to read and understand.
But don’t tell matz…) :slight_smile:

Cheers

robert
···

----- Original Message -----

On Wed, Jul 16, 2003 at 08:27:04PM +0900, Mark J. Reed wrote:

On Wed, Jul 16, 2003 at 06:41:11PM +0900, Mauricio Fernández wrote:

“Richard Zidlicky” rz@linux-m68k.org schrieb im Newsbeitrag
news:20030717142158.GB2481@linux-m68k.org

We’ve had programmers who wanted ‘initialize’ changed to ‘new’ so that
they would have less to type.

this would be also good for another reason, people will no
longer get confused by mistyping “s” and “z” in initialize :wink:

I’d insist on having these still separated. “new” is different from
“initialize”: it allocates an instance and then invokes initialize which
is really only responsible for initializing. It might have come more
handy to use “init” instead, but I guess changing that now will do a lot
of harm. Btw: you can achieve that easily with

class Object
alias old_initialize :initialize

def initialize(*args, &block)
old_initialize
init(*args, &block)
end
end

now you can do

class Foo
def init(name)
@name = name
end
end

Regards

robert
···

On Wed, Jul 16, 2003 at 10:36:51PM +0900, Peter Hickman wrote: