Pascal-like 'with' statement?


(Philip Mak) #1

Is there something like Pascal’s with statement? I’d like to turn this
code:

Cfg = OpenStruct.new
Cfg.host = 'localhost’
Cfg.user = 'shoujoai’
Cfg.database = ‘shoujoai’

into something like this:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end


(Chris Morris) #2

Is there something like Pascal’s with statement?

I don’t think so …

I’d like to turn this
code:

Cfg = OpenStruct.new
Cfg.host = 'localhost’
Cfg.user = 'shoujoai’
Cfg.database = ‘shoujoai’

into something like this:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end

How 'bout this?

OpenStruct = Struct.new(‘OpenStruct’, :host, :user, :database)
Cfg = OpenStruct.new(‘localhost’, ‘shoujoai’, ‘shoujoai’)

Chris


(Sean O'Dell) #3

Philip Mak wrote:

Is there something like Pascal’s with statement? I’d like to turn this
code:

Cfg = OpenStruct.new
Cfg.host = 'localhost’
Cfg.user = 'shoujoai’
Cfg.database = ‘shoujoai’

into something like this:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end

That’s something I would LOVE to see added.

Sean

(Christian Rishoej) #4

Is there something like Pascal’s with statement? I’d like to turn this
code:

Cfg = OpenStruct.new
Cfg.host = 'localhost’
Cfg.user = 'shoujoai’
Cfg.database = ‘shoujoai’

into something like this:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end

If you have

class Cfg

end

…you could do:

c = Cfg.new
c.instance_eval {
@host = ‘localhost’
@user = ‘shoujoai’
}

Christian


(Thomas Hurst) #5

What about:

Cfg.set(
:host => ‘localhost’,
:user => ‘shoujoai’,
:database => ‘shoujoai’
)

set() just needs to accept a hash and iterate over it, calling
send(key + ‘=’, value) over each pair

···

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end


Thomas ‘Freaky’ Hurst - freaky@aagh.net - http://www.aagh.net/

A government that is big enough to give you all you want is big enough
to take it all away.
– Barry Goldwater


(Nobuyoshi Nakada) #6

Hi,

Is there something like Pascal’s with statement? I’d like to turn this
code:

IMO, `with’ statement is a misdesign of Pascal.

just a useless joke.

module Kernel
def as(me) yield(me) end
def self; self end
end

Cfg = OpenStruct.new.as {|my|
my.host = 'localhost’
my.user = 'shoujoai’
my.database = 'shoujoai’
my.self
}

···

At Thu, 6 Jun 2002 09:23:15 +0900, Philip Mak wrote:


Nobu Nakada


(Niklas Frykholm) #7

[Philip Mak]:

Is there something like Pascal’s with statement?

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end

I think “with” is confusing and evil, especially in Ruby where
variables are not declared. In the code above, it is impossible to
know whether “user” is an instance variable or a local variable to
the block, without checking the class definition of OpenStruct and
its ancestors.

What if OpenStruct defines #method_missing? Then we have to disallow
local variables in the with-block, because Cfg will want to handle
every ‘xxx=’ call.

I think its best to spell out the receiver, like

begin
	o=Cfg
	o.host = 'localhost'
end

// Niklas


(Avi Bryant) #8

Philip Mak pmak@animeglobe.com wrote in message news:20020606002438.GA9947@trapezoid.interserver.net

Is there something like Pascal’s with statement? I’d like to turn this
code:

Cfg = OpenStruct.new
Cfg.host = 'localhost’
Cfg.user = 'shoujoai’
Cfg.database = ‘shoujoai’

into something like this:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end

My favorite solution to this is Smalltalk’s cascades: end a method
call with a semicolon, and you can chain more calls to the same
receiver.
So a Ruby equivalent might look like

Cfg = OpenStruct.new
Cfg.host= ‘localhost’;
.user= ‘shoujoai’;
.database= ‘shoujoai’

Or, in more Smalltalky style,

Cfg = OpenStruct.new.host(‘localhost’);
.user(‘shoujoai’);
.database(‘shoujoai’);
.yourself

One nice property of this last style is that the whole thing becomes a
single expression, suitable for, say, putting in a return statement
without even using a local variable.

Matz, is there room for this in the parser? :wink:


(Paul Brannan) #9

There are a few implementations of ‘with’ out there. The one I wrote
(which I make no guarantees about):

http://rm-f.net/~cout/ruby/treasures/RubyTreasures-0.4/lib/hacks/with.rb.html
http://rm-f.net/~cout/ruby/treasures/RubyTreasures-0.4/ext/hacks/kernelless_object.c.html

and another one, which appears to point to a broken link:

http://www.ruby-lang.org/en/raa-list.rhtml?name=with-block

I think this latter one used to be implemented using instance_eval,
which can be dangerous.

Paul

···

On Thu, Jun 06, 2002 at 09:23:15AM +0900, Philip Mak wrote:

Is there something like Pascal’s with statement?


(Christian Rishoej) #10

…you could do:

c = Cfg.new
c.instance_eval {
@host = ‘localhost’
@user = ‘shoujoai’
}

…though I’m aware that you’re actually just asking for a short hand rather
than this instance evaluation.

Christian


(Chris Morris) #11

That’s something I would LOVE to see added.

FWIW, many Delphi programmers discourage the use of with – although that
may be in part to limitations of previous versions of the debugger (with
Delphi 5, you can mouse over a variable and get a pop-up watch, but not on
variables that resolve to the obj of the with block). Another reason is that
it can make the code less readable:

  • if the block under the with is too long
  • if multiple items are used in the with block, it can be confusing which
    one is being referenced

// this is legal
with AObj, BObj do
begin
MemberA := ‘x’;
MemberB := ‘c’;
end;

… does MemberB belong to BObj, does MemberA belong to AObj? There’s no way
to know just by looking at this block.

Chris


(Nobuyoshi Nakada) #12

Hi,

Or, in more Smalltalky style,

Cfg = OpenStruct.new.host(‘localhost’);
.user(‘shoujoai’);
.database(‘shoujoai’);
.yourself

One nice property of this last style is that the whole thing becomes a
single expression, suitable for, say, putting in a return statement
without even using a local variable.

It allows only each one methods, i.e., denies method chains in
cascades? If not, it needs to explicit the `start point’ of
the cascade. Once I’d thought out like this:

Cfg = OpenStruct.new.{host(‘localhost’)
user(‘shoujoai’)
database(‘shoujoai’)
method.chain
yourself}

But I concluded cascades must result only confusion if nested.

···

At Thu, 6 Jun 2002 17:42:27 +0900, Avi Bryant wrote:


Nobu Nakada


(Rob Partington) #13

I wrote a module that does that. It’s even on the RAA although the
hostname is wrong. Look at http://ipy.frottage.org/rjp/ruby/with.html

···

In message 3CFEACC6.5040208@BUHBYESPAMcelsoft.com, “Sean O’Dell” sean@BUHBYESPAMcelsoft.com writes:

Cfg = OpenStruct.new
with Cfg do
host = 'localhost’
user = 'shoujoai’
database = 'shoujoai’
end
That’s something I would LOVE to see added.


rob partington % rjp@browser.org % http://lynx.browser.org/


(Rob Partington) #14

and another one, which appears to point to a broken link:
http://www.ruby-lang.org/en/raa-list.rhtml?name=with-block

I’d update that, but the passphrase information is on the machine
that’s dead.

I think this latter one used to be implemented using instance_eval,
which can be dangerous.

Not unless someone changed my code without telling me. :slight_smile:

···

In message 20020606131350.P3001@atdesk.com, Paul Brannan pbrannan@atdesk.com writes:

rob partington % rjp@browser.org % http://lynx.browser.org/


(Sean O'Dell) #15

Chris Morris wrote:

That’s something I would LOVE to see added.

FWIW, many Delphi programmers discourage the use of with – although that
may be in part to limitations of previous versions of the debugger (with
Delphi 5, you can mouse over a variable and get a pop-up watch, but not on
variables that resolve to the obj of the with block). Another reason is that
it can make the code less readable:

  • if the block under the with is too long
  • if multiple items are used in the with block, it can be confusing which
    one is being referenced

// this is legal
with AObj, BObj do
begin
MemberA := ‘x’;
MemberB := ‘c’;
end;

… does MemberB belong to BObj, does MemberA belong to AObj? There’s no way
to know just by looking at this block.

I’ve never heard of its use discouraged, but then Pascal is hardly my
religion. :slight_smile: When you have a lot of operations to perform on a single
object in sequence, it’s quite handy.

I didn’t know the syntax you show is legal. Seems foolish that they
allowed such a thing. I would NOT recommend that ahem feature find
its way into Ruby.

Sean

(Avi Bryant) #16

nobu.nokada@softhome.net wrote in message news:200206061041.g56AfZf15706@sharui.nakada.kanuma.tochigi.jp

Hi,

Or, in more Smalltalky style,

Cfg = OpenStruct.new.host(‘localhost’);
.user(‘shoujoai’);
.database(‘shoujoai’);
.yourself

One nice property of this last style is that the whole thing becomes a
single expression, suitable for, say, putting in a return statement
without even using a local variable.

It allows only each one methods, i.e., denies method chains in
cascades? If not, it needs to explicit the `start point’ of
the cascade.

That’s right. Actually, it depends on dialect - I think Dolphin has
or had support for nested cascades - but in Squeak and most other
Smalltalks, once you start a cascade you can’t chain methods from that
point. This is almost never a restriction you notice, in my
experience.

···

At Thu, 6 Jun 2002 17:42:27 +0900, > Avi Bryant wrote:


(Paul Brannan) #17

My apologies; I didn’ have the source, so I was going by memory. :slight_smile:

This one uses instance_eval:

http://saxa.georgetown.edu/~jack/ruby/rosa/meth.php?c=1

and was also posted on Rubygarden at:

http://www.rubygarden.org/article.php?sid=109

Yours uses send(), which can be almost as bad if not used carefully.
It’s also a lot simpler and easier to understand than a solution that
doesn’t allow calls to private methods.

BTW, I think there’s a typo in the online source. Line 18 should be
changed from:
@curObj[-1].send(methname, args)
.to:
@curObj[-1].send(methname, *args)

Paul

···

On Fri, Jun 07, 2002 at 04:30:25AM +0900, Rob Partington wrote:

I think this latter one used to be implemented using instance_eval,
which can be dangerous.

Not unless someone changed my code without telling me. :slight_smile:


(Jean-Hugues ROBERT) #18

Hello,

I once designed a “with statement” in some language. Inside the body, one
had to use “.something” to take advantage of it:

with an_obj do # Eqv to:
.do_this() # an_obj.do_this()
.do_that() # an_obj.do_that()
.done = true # an_obj.done = true
end

In Ruby today, one can as simply write:

begin o = an_obj
o.do_this()
o.do_that()
o.done = true
end

I feel like it is almost as readable this way than it is with “with”.

Yours,

Jean-Hugues

···

Web: http://hdl.handle.net/1030.37/1.1
Phone: +33 (0) 4 92 27 74 17