OOP in Ruby?

A

aidy

| Hi,
|
| Anyone know of any good resources regarding OOP in Ruby?

Err, about everything, I guess. ;P

~From personal experience: The PickAxe (Programming Ruby), and The Ruby
Way by Hal Fulton cover this nicely. And I suspect the O'Reilly book The
Ruby Programming Language (co-written by Matz) covers that in-depth, too.

Pickaxe informs us about Ruby, but not OOA\D\P. Like Python and Java,
with Ruby you can still implement procedurally.

Aidy
 
A

aidy

Ruby is so object oriented that's it's almost impossible *not* to learn
about OOP by using it.


I feel that you could learn about OO Ruby, but the language does not
necessitate OO development. I could write everything in modules. I
could use classes as a container but not in an OO way (inheritance,
polymorphism and encapsulation).

Aidy
 
M

Mark Wilden

It's not quite as dead as it seemed. At any rate, in August they
announced the end of development. Then in January, they announcded a
new
beta: http://www.object-arts.com/content/news/x61beta1.html

That news made my day. I don't use Smalltalk or even Windows anymore,
but the six months or so I spent working on a Smalltalk project with
Dolphin was the most enjoyable of my whole career.

Dolphin is the best IDE I've ever used. Next comes Visual Studio. :)

///ark
 
H

Huw Collingbourne

aidy said:
The 'if' expression is not an object.

There are many things in Ruby that are not objects - not only keywords
but also, for example, blocks. While blocks can be 'converted' into
objects (Proc objects), unlike in some other languages (such as
Smalltalk), Ruby blocks do not automatically have an independent
existence - that is, just writing a block in code does not make it an
instance of a Block (or Proc) class.

best wishes
Huw

SapphireSteel Software
Ruby and Rails In Visual Studio
http://www.sapphiresteel.com
 
R

Robert Dober

There are many things in Ruby that are not objects - not only keywords
but also, for example, blocks. While blocks can be 'converted' into
objects (Proc objects), unlike in some other languages (such as
Smalltalk), Ruby blocks do not automatically have an independent
existence I agree upto here, but...
- that is, just writing a block in code does not make it an
instance of a Block (or Proc) class.
I however believe it does, if you write a block in Ruby it is always
passed on to a method, let that be Kernel#proc, Enumerable#map or
whatever, that means that a Proc object referring to the block is
always accessible via either the prefixed &blk parameter in this
method or in case there is not &blk parameter and yield is used in the
method it still is accessible as Proc::new without parameters

Example from a unit test

def a &blk
b = Proc::new
assert_equal blk, b
assert_equal b, Proc::new
assert_kind_of Proc, blk
end

Not using this reference does not mean it does not exist IMHO.
Cheers
Robert
 
H

Huw Collingbourne

Robert said:
I agree upto here, but...
I however believe it does, if you write a block in Ruby it is always
passed on to a method

Therein lies the difference. If you write a block in Smalltalk it has an
independent existence. It does not demand a receiver method in order to
justify its existence. In other words, a Smalltalk block is just the
same as an other object. It is an instance of its class and comes with
all the methods of its class. In fact, send it the 'class' message and
it will reply Block (or BlockClosure or whatever a specific Smalltalk
class library may have named it).

In Ruby, if you create a free-standing block, Ruby regards it as a
syntax error. So, unless a Proc object is instantiated using a block, I
don't believe that a Ruby block meets the essential criterion required
to be described as an object.

best wishes
Huw

SapphireSteel Software
Ruby and Rails In Visual Studio
http://www.sapphiresteel.com
 
R

Rick DeNatale

Therein lies the difference. If you write a block in Smalltalk it has an
independent existence.

In theory, but not necessarily in practice. In reality most Smalltalk
implementations will not reify the "block" arguments to methods like
ifTrue:, ifFalse:, ifTrue:ifFalse, and ifFalse:ifTrue: instead they
cheat and compile test and branch bytecodes, and throw an exception if
the 'receiver' isn't a boolean.

http://talklikeaduck.denhaven2.com/...d-to-stop-using-ruby-and-go-back-to-smalltalk

The real difference, I think, is that in Smalltalk you can have
multiple arguments in a message which are coded as block literals,
where as in Ruby block literals can only be used as the final argument
to a method, and that that argument doesn't need to be explicitly
named if is invoked by the method using yield, or if it's ignored by
the method.

There's quite a discussion going on right now on ruby-core about the
esthetics of the new '->' "fallen over lambda" operator in 1.9 and
whether it would be better to allow a call like:

a.m({|b|...}, {|| ...})

where the |..| distinguish a block from a hash.

I don't know the ultimate fate of the proposal, but it DOES make ruby
syntax look a bit more like Smalltalk.

It makes me wonder what Ruby would look like had Matz chosen square
brackets rather than braces to delimit block literals.
 
R

Robert Dober

In Ruby, if you create a free-standing block, Ruby regards it as a
syntax error. So, unless a Proc object is instantiated using a block, I
don't believe that a Ruby block meets the essential criterion required
to be described as an object.
This might become very interesting, please do not take any offense but
I really cannot follow you.
Anyway, I will tell you what is important to me:
Blocks in Ruby are Proc objects, always, can you agree with this
statement, if I render to your subtle arguement about the conditions
blocks need to exist?

I feel this is more important to a nuby than comparing to Smalltalk as
you did, although it is a very interesting thing. I however feel that
the substential difference is what Rick said in his post.

Please note also Eric's patch making
{|x| x} equivalent to
lambda{|x| x}
this shows clearly that we are talking syntax here and not object semantics.

Cheers
Robert Dober
 
R

Rick DeNatale

Anyway, I will tell you what is important to me:
Blocks in Ruby are Proc objects, always, can you agree with this
statement,

I don't think that this is true Robert.

For example:

def foo
yield
end

foo {}

doesn't create a proc.
Please note also Eric's patch making
{|x| x} equivalent to
lambda{|x| x}
this shows clearly that we are talking syntax here and not object semantics.

Except that Eric had to redo the patch because he ran into an issue
with yield vs. call semantics.
 
J

Joel VanderWerf

Robert said:
I however believe it does, if you write a block in Ruby it is always
passed on to a method, let that be Kernel#proc, Enumerable#map or
whatever, that means that a Proc object referring to the block is
always accessible via either the prefixed &blk parameter in this
method or in case there is not &blk parameter and yield is used in the
method it still is accessible as Proc::new without parameters

def foo
p ObjectSpace.each_object(Proc){}
end

def bar(&bl)
p ObjectSpace.each_object(Proc){}
end

GC.disable
foo {} # ==> 59
foo {} # ==> 59
foo {} # ==> 59
bar {} # ==> 60
bar {} # ==> 61
bar {} # ==> 62
 
H

Huw Collingbourne

Robert said:
Anyway, I will tell you what is important to me:
Blocks in Ruby are Proc objects, always, can you agree with this
statement,

No, it doesn't seem to me that they are. As I said before, in Ruby a
block does not, by default, have its own independent existence. Let me
illustrate by comparison with Smalltalk. When we write blocks and use
them with methods (e.g. times in Ruby or timesRepeat: in Smalltalk) they
may appear to be more or less the same:

1) SMALLTALK

i := 0.
10 timesRepeat: [ i := i + 1 ].
i.

2) RUBY

i = 0
10.times{ i += 1 }
puts( i )


BUT, a Smalltalk Block can be its own object. It is not obliged to be
used with some 'block-aware' method. Compare the following:

1) SMALLTALK

i := 0.
myBlock := [ i := i + 1 ].
10 timesRepeat: myBlock.

2) RUBY (a)

i = 0
myBlock = { i += 1 } # <= error: Ruby thinks this is a hash
10.times{ i += 1 }
puts( i )

2) RUBY (b)

i = 0
myBlock = { || i += 1 } # <= syntax error
10.times{ i += 1 }
puts( i )

3) RUBY (c)

i = 0
myBlock = proc{ i += 1 } #<= Hurrah! Works by explictly 'converting' to
Proc
10.times{ i += 1 }
puts( i )


In Smalltalk, a block is always an instance of its class. e.g.

myBlock := [ i := i + 1 ].
myBlock class.
...Smalltalk replies: BlockClosure.


It's a subtle point, I know, and I don't want to make any big deal of
it. After all, when a Proc object block is explicitly created from a
Ruby block, it works in a comparable way to a Smalltalk block. However,
that doesn't alter the fact that, in Ruby, blocks (chunks of code
delimited by {..} or do..end) are not normally instances of the Proc
class. They are, well, just chuncks of code but not objects. To
demonstrate that, try evaluating a block:

1) SMALLTALK
[ i := i + 1 ] class.
...Answers: BlockClosure

2) RUBY
{ i += 1 }.class
...Answers: syntax error, unexpected '}', expecting $end { || i += 1
}.class

do i += 1 end.class
...Anwsers: syntax error, unexpected kEND, expecting $end do i += 1
end.class


best wishes
Huw

SapphireSteel Software
Ruby and Rails In Visual Studio
http://www.sapphiresteel.com
 
D

David A. Black

Hi --

Robert said:
Anyway, I will tell you what is important to me:
Blocks in Ruby are Proc objects, always, can you agree with this
statement,

No, it doesn't seem to me that they are. As I said before, in Ruby a
block does not, by default, have its own independent existence. Let me
illustrate by comparison with Smalltalk. When we write blocks and use
them with methods (e.g. times in Ruby or timesRepeat: in Smalltalk) they
may appear to be more or less the same:
[snip]

It's a subtle point, I know, and I don't want to make any big deal of
it. After all, when a Proc object block is explicitly created from a
Ruby block, it works in a comparable way to a Smalltalk block. However,
that doesn't alter the fact that, in Ruby, blocks (chunks of code
delimited by {..} or do..end) are not normally instances of the Proc
class. They are, well, just chuncks of code but not objects. To
demonstrate that, try evaluating a block:

I agree that this subtle point is important. It's one of these things
where it seems like splitting hairs to say that the code block is
syntax and the Proc is an object, but if one doesn't make that
distinction, then there's a kind of off-by-one condition later on,
when things like Proc.new taking a block starts to seem weird (why
would Proc.new take a Proc?).

It's similar, I think, to hair-splitting between "message-sending" and
"method-calling". Much of the time it doesn't matter, but if there's
no separation of the terminology, then the very concept of sending an
object a message it can't map to a method gets harder, rather than
easier, to grasp.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 23-26 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
D

Dave Bass

In Ruby you only need to add "lambda" to make a block into an object:

irb(main):006:0> x = lambda { i += 1 }
=> #<Proc:0x02e13cf8@(irb):6>
irb(main):007:0> x.class
=> Proc
irb(main):008:0> lambda { i += 1 }.class
=> Proc

I suppose the need to prepend "lambda" is a good thing in that it gives
you the flexibility of choosing whether you want to make your block into
an object or not, whereas in Smalltalk presumably all blocks are
automatically objects. There may be some small overhead associated with
this, I don't know.

Declaring blocks with "lambda" is a bit like declaring variables before
you can use them, something I miss with Ruby.
 
R

Robert Dober

Rick, Huw, David

you might be right, I finally understand what you mean know :).

I can esaily imagine a conceptual view in which you are right

def foo
yield
end

foo {}

does not create a Proc object, I however believe, but agree that this
of minor importance,
that the interpreter creates a temporary proc object, how else could
Proc::new return the correct value?

I feel it is important to know that you can always get to an object
representing the block, that was good enough for me.

I start understanding better that indeed the lack of syntactic
facilities can be interpreted how you did, but it took me a while to
work it out :)

Just to be double sure I get you right, if one implemented Eric's
patch and we could write
pr = do 42 end
or = {|| 42 }
would you agree with my original statement?

Cheers
Robert
 
R

Robert Dober

I suppose the need to prepend "lambda" is a good thing in that it gives
you the flexibility of choosing whether you want to make your block into
an object or not, whereas in Smalltalk presumably all blocks are
automatically objects. There may be some small overhead associated with
this, I don't know.
I am not sure, is it not simply a question of optimization, assume this case

def a &blk
end
a {}
Ruby could not create an object for {}, but does it, I do not think so
for 1.8, maybe in 1.9?

Same thing in Smalltalk
...
[ :i | i + 1 ].
...
Smalltalk could as well not compile this code at all or create a NOP,
probably most Smalltalk implementations will ignore it I guess
Declaring blocks with "lambda" is a bit like declaring variables before
you can use them, something I miss with Ruby.
And I am missing your unit tests, that said it might be a good feature
safeguarding you against typos in quick hacks sometimes.
Overall I still think it is not worth it, maybe your methods are a tad
too long too?

Cheers
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

OOP Through Animations and Dogs 0
General Ruby OOP question 4
How do I solidify my Python skills 1
ruby graphs and hudson 1
Any project ideas for landing a job ? 3
TDD with Ruby 2
OOP only in modules 3
oop 0

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top