Snippet request: Ruby Web Server written in under an hour

Hello Paul,

Tuesday, October 29, 2002, 9:56:04 PM, you wrote:

In Ruby, attributes are method calls. However, they are a special type
of method call. Attributes are guaranteed to never modify the object.
And if the object isn’t modified, then the attribute should remain the
same. I think the distinction is supported by the semantics of
attributes, if not by the language itself.

attributes is just methods, automatically defined by attr_reader/…
built-in methods. you can write such methods as attr_reader himself
and some advanced OO libraries actually do this. it’s easy:

class Class
def reader attr
module_eval <<-END_OF_EVAL
def #{attr}
@#{attr}
end
END_OF_EVAL
end
end

class A
def initialize(x0)
@x = x0
end
reader “x”
end

a1 = A.new(23)
p a1.x
a2 = A.new(34)
p a2.x

···


Best regards,
Bulat mailto:bulatz@integ.ru

Hi –

···

On Thu, 31 Oct 2002, William Djaja Tjokroaminata wrote:

Bulat Ziganshin bulatz@integ.ru wrote:

This is just my personal style. When I write network simulations (not
Ruby code fragments), I never put () for methods that are defined simply
using “attr_reader”, but other methods I usually put () to remind
me that I am “doing some real action” here.

i think real difference that you you want to highlight is between pure
functions and functions which have side-effect

Hi Bulat,

Yes, I agree with you; I think you have made it clearer, similar to Paul’s
post.

Aren’t there cases where that might change, if the implementation changes?
It seems that () is serving as a comment, potentially a fragile one.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

dblack@candle.superlink.net wrote:

Aren’t there cases where that might change, if the implementation changes?
It seems that () is serving as a comment, potentially a fragile one.

Hi David,

I agree with you that () has the potential of serving as an incorrect
comment. However, unlike other types of comments, in my opinion the
consequence of this type of incorrect comment is almost negligible.

(Probably one exception is if, like in my other post, because of the
special convention, a person who sees “obj.stuff” will assume the
existence of “@stuff” when he derives a class from the class of “obj”.)

Regards,

Bill

It is possible for a method to change its behavior. However, if a
method changes from a method that has no side effects to a method that
has side effects, then the interface has considerably changed, and any
code that calls that method is going to have to be re-evaluated. It’s
generally a bad idea to change an object’s interface.

(By side-effect here I mean logical side-effects; a method that
lazy-evaluates a value and then stores that value somewhere has the same
semantics as an accessor).

Paul

···

On Thu, Oct 31, 2002 at 12:42:25AM +0900, dblack@candle.superlink.net wrote:

Aren’t there cases where that might change, if the implementation changes?
It seems that () is serving as a comment, potentially a fragile one.

Hello dblack,

Wednesday, October 30, 2002, 6:42:25 PM, you wrote:

i think real difference that you you want to highlight is between pure
functions and functions which have side-effect
Aren’t there cases where that might change, if the implementation changes?
It seems that () is serving as a comment, potentially a fragile one.

it’s some like redefining Fixnum.+ :slight_smile:

···


Best regards,
Bulat mailto:bulatz@integ.ru

Hi –

Aren’t there cases where that might change, if the implementation changes?
It seems that () is serving as a comment, potentially a fragile one.

Hi David,

I agree with you that () has the potential of serving as an incorrect
comment. However, unlike other types of comments, in my opinion the
consequence of this type of incorrect comment is almost negligible.

(Probably one exception is if, like in my other post, because of the
special convention, a person who sees “obj.stuff” will assume the
existence of “@stuff” when he derives a class from the class of “obj”.)

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

David

···

On Thu, 31 Oct 2002, William Djaja Tjokroaminata wrote:

dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

> It is possible for a method to change its behavior. However, if a > method changes from a method that has no side effects to a method that > has side effects, then the interface has considerably changed, and any > code that calls that method is going to have to be re-evaluated. It's > generally a bad idea to change an object's interface. >

For those who are OOP newbies, a distinction must be drawn between what is a
bad idea in a production system and what is a bad idea during development; A
class’s interface will likely change often during development. Good OOP
design is like sculpting in clay, rather than stone. Refactor vigorously and
often.

···

On Wednesday 30 October 2002 11:47 am, Paul Brannan wrote:

Paul


Best essay I’ve read in years:

dblack@candle.superlink.net wrote:

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

Hi David,

Well, it looks like a contrieved example, so it is really a matter of
personal style/convention. But now suppose that someone really writes a
code like above in a class, and I want to derive a new class from it, and
I need to access “the object logically represented by
stuff/thing”. In my derived class, should I use “@thing” or should I use
“self.stuff”?

Regards,

Bill

Hello Albert,

Wednesday, October 30, 2002, 10:18:05 PM, you wrote:

It is possible for a method to change its behavior. However, if a
method changes from a method that has no side effects to a method that
has side effects, then the interface has considerably changed, and any
code that calls that method is going to have to be re-evaluated. It’s
generally a bad idea to change an object’s interface.

For those who are OOP newbies, a distinction must be drawn between what is a
bad idea in a production system and what is a bad idea during development; A
class’s interface will likely change often during development. Good OOP
design is like sculpting in clay, rather than stone. Refactor vigorously and
often.

but don’t build the home before you fixed the fundament :slight_smile:

···


Best regards,
Bulat mailto:bulatz@integ.ru

Hi –

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

Hi David,

Well, it looks like a contrieved example, so it is really a matter of
personal style/convention. But now suppose that someone really writes a

Yeah, I was worried I couldn’t get away with that dinkiness :slight_smile: But
still, I’m not convinced that “def stuff; @stuff; end” really deserves
to be looked at as a special case.

code like above in a class, and I want to derive a new class from it, and
I need to access “the object logically represented by
stuff/thing”. In my derived class, should I use “@thing” or should I use
“self.stuff”?

Memories of a thread from a month or two ago… :slight_smile: I can’t remember
what the thread was called, but I don’t think it reached a consensus.
Some interesting things along the way, though.

David

···

On Thu, 31 Oct 2002, William Djaja Tjokroaminata wrote:

dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Definitely use self.stuff to avoid breaking encapsulation.

Imagine if the class was instead:

def stuff=(x)
@thing = x + 1
end

def stuff
@thing - 1
end

Using @thing as a synonym for self.stuff would give the wrong result.

···

On Wed, 2002-10-30 at 17:38, William Djaja Tjokroaminata wrote:

dblack@candle.superlink.net wrote:

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

Well, it looks like a contrieved example, so it is really a matter of
personal style/convention. But now suppose that someone really writes a
code like above in a class, and I want to derive a new class from it, and
I need to access “the object logically represented by
stuff/thing”. In my derived class, should I use “@thing” or should I use
“self.stuff”?


Dr. Nathaniel Pryce, Technical Director, B13media Ltd.
Studio 3a, 22-24 Highbury Grove, London N5 2EA, UK
http://www.b13media.com

> But now suppose that someone really writes a > code like above in a class, and I want to derive a new class from it, and > I need to access "the object logically represented by > stuff/thing". In my derived class, should I use "@thing" or should I use > "self.stuff"?

I would say: “It depends…” In a real program, a method that only returns an
instance variable for use only by subclasses is silly in my opinion. I see
only two reasons for such a method:

  1. It is intended for use by something other than a subclass, or
  2. The class is under development and it is anticipated that addional code
    will be added to that method.

As in real life, what you inherit is yours to do with as you see fit.

···

On Wednesday 30 October 2002 11:38 am, William Djaja Tjokroaminata wrote:

Regards,

Bill


Best essay I’ve read in years:

Hi Nat,

Actually an answer like this is what I am waiting for. There are other
answers such as “it depends” and “no concensus”, but this particular
answer is in my opinion the most interesting because it may actually deny
the need for the existence of two distinct types of instance variables
(“protected” variables and “private/local” variables).

From the interface point of view, I agree that using “self.stuff” is
better than using “@thing”, because then the derived class needs not be
changed if there is a change in the parent class in the
implementation of “stuff”. In this sense we separate the interface from
its implementation. Well, it may look “silly” to do “def
thing; @thing; end”, but as Ruby already incurs some overhead as compared
to C, probably the gain in software robustness is more than the relative
loss in code performance (more on this later).

I know that this will break a lot of existing Ruby codes, but suppose now
every Rubyist agrees to use “self.stuff” instead of “@thing” in a derived
class. Then the Ruby internal can actually be changed so that every
instance variable is private/local to the class. Access for the child
classes is simply controlled by providing or not providing a protected
method such as “stuff” in above. With this, there will be no need for two
different kinds of instance variables; all instance variables are private, and
“protected” variables are emulated through the use of protected methods.

Next, regarding the need for “protected\n attr_accessor :thing”. If
the concern is efficiency, people can always transform it into C. For
example, in my simulation case, for efficiency reason, the fundamental
objects’ attributes are not actually stored as instance variables but as C
struct members (so that when we are completely in C there is no
performance penalty). Therefore, for each attribute, a child class has
actually to use “self.thing” instead of “@thing” (because “@thing” simply
does not exist at all).

As I already mentioned, the only drawback is the backward
compatibility. However, if people can start accessing a parent class
attribute using “self.thing” instead of “@thing”, probably at some point
in the future we can by default make all instance variables
private/local. (Well, if it cannot be done, probably this is an idea for
a new programming language?)

Regards,

Bill

···

Nat Pryce nat.pryce@b13media.com wrote:

Definitely use self.stuff to avoid breaking encapsulation.

Imagine if the class was instead:

def stuff=(x)
@thing = x + 1
end

def stuff
@thing - 1
end

Using @thing as a synonym for self.stuff would give the wrong result.

Of course they give different results: @thing is a state variable, stuff=
modifies the state variable, and stuff is simply an algorithm that happens to
utilize the state variable. Assuming that stuff and @thing are synonymous is
what is wrong.

···

On Wednesday 30 October 2002 12:13 pm, Nat Pryce wrote:

On Wed, 2002-10-30 at 17:38, William Djaja Tjokroaminata wrote:

dblack@candle.superlink.net wrote:

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

Well, it looks like a contrieved example, so it is really a matter of
personal style/convention. But now suppose that someone really writes a
code like above in a class, and I want to derive a new class from it, and
I need to access “the object logically represented by
stuff/thing”. In my derived class, should I use “@thing” or should I use
“self.stuff”?

Definitely use self.stuff to avoid breaking encapsulation.

Imagine if the class was instead:

def stuff=(x)
@thing = x + 1
end

def stuff
@thing - 1
end

Using @thing as a synonym for self.stuff would give the wrong result.


“I invented the term Object-Oriented, and I can
tell you I did not have C++ in mind.”
-Alan Kay

> (Well, if it cannot be done, probably this is an idea for > a new programming language?)

That’s exactly what it is.

···

On Thursday 31 October 2002 8:59 am, William Djaja Tjokroaminata wrote:

Regards,

Bill


“I invented the term Object-Oriented, and I can
tell you I did not have C++ in mind.”
-Alan Kay

Exactly my point! And it looks like a trivial point when illustrated
with the code above. However, the point is as valid, although much less
obvious to many programmers, when illustrated with David Black’s
original code, which was a direct assignment to and return from an
instance variable. And the point is even less obvious when the accessor
functions have the same name as the instance variable:

def stuff
    @stuff
end

def stuff=( new_stuff )
    @stuff = new_stuff
end

Cheers,
Nat.

···

On Thu, 2002-10-31 at 16:04, Albert Wagner wrote:

On Wednesday 30 October 2002 12:13 pm, Nat Pryce wrote:

On Wed, 2002-10-30 at 17:38, William Djaja Tjokroaminata wrote:

dblack@candle.superlink.net wrote:

I don’t think one should make that assumption; it’s awfully rigid. I
might have:

def stuff=(x)
@thing = x
end

def stuff
@thing
end

which is a dinky example at best… but meaning there is no necessary
connection between the methods and the implementation.

Well, it looks like a contrieved example, so it is really a matter of
personal style/convention. But now suppose that someone really writes a
code like above in a class, and I want to derive a new class from it, and
I need to access “the object logically represented by
stuff/thing”. In my derived class, should I use “@thing” or should I use
“self.stuff”?

Definitely use self.stuff to avoid breaking encapsulation.

Imagine if the class was instead:

def stuff=(x)
@thing = x + 1
end

def stuff
@thing - 1
end

Using @thing as a synonym for self.stuff would give the wrong result.

Of course they give different results: @thing is a state variable, stuff=
modifies the state variable, and stuff is simply an algorithm that happens to
utilize the state variable. Assuming that stuff and @thing are synonymous is
what is wrong.


Dr. Nathaniel Pryce, Technical Director, B13media Ltd.
Studio 3a, 22-24 Highbury Grove, London N5 2EA, UK
http://www.b13media.com

> > Of course they give different results: @thing is a state variable, stuff= > > modifies the state variable, and stuff is simply an algorithm that > > happens to utilize the state variable. Assuming that stuff and @thing > > are synonymous is what is wrong. > > Exactly my point! And it looks like a trivial point when illustrated > with the code above. However, the point is as valid, although much less > obvious to many programmers, when illustrated with David Black's > original code, which was a direct assignment to and return from an > instance variable. And the point is even less obvious when the accessor > functions have the same name as the instance variable: > > def stuff > @stuff > end > > def stuff=( new_stuff ) > @stuff = new_stuff > end > > Cheers, > Nat.

Hi, Nat.
I guess I misunderstood the comment:

“Definitely use self.stuff to avoid breaking encapsulation.”

I am still unsure of what is meant here. I can only see using self.stuff to
differentiate between a var named stuff and a method named stuff. But,
personally, I would never use the same name for both.

···

On Thursday 31 October 2002 10:42 am, Nat Pryce wrote:


“I invented the term Object-Oriented, and I can
tell you I did not have C++ in mind.”
-Alan Kay