> Answering a later question you had, the above singleton method could be
> defined like:
>
> class << test2
> def size
> 10
> end
> end
Quite interesting. I understand its semantic, but not its syntax. That is
to say "class" is a keyword. So this is a "new syntax"?
'class' here is doing what you expect it to do - defining a class. But
the class that's being defined is a singleton class belonging to the
object on the rhs of the <<. Basically, objects in ruby can have two
classes - the class of which they are an instance, and a singleton class
that relates to (and supplies methods for) just that object. This syntax
is for use with the latter.
I think that since I can << array the syntax is not *that* new. Still quite
impressive... well as I said
Every time I do
class << something
code
end
I'm evaluating "code" in the "something" context? No.. this is not correct.
I understand the example, but I'm not able to make abstraction.
Not quite. You're actually evaluating it in the context of an instance
of Class, that being the singleton class for 'something'.
Try this:
class << something
p self
end
Since almost everything in Ruby is an expression, you can also do this:
class SomeClass
def singclass
class << self
self
end
end
end
s = SomeClass.new
# => #<SomeClass:0xb7e85d9c>
s.singclass
# => #<Class:#<SomeClass:0xb7e85d9c>>
Notice how the Class returned relates to just that SomeClass instance.
(this for the sake of example, if you were to need it you'd probably
define it elsewhere).
I also suppose i can
module << something
code
end
No, singleton modules aren't (AFAIK) supported.
So I suppose than
class Something
# code
end
is "synactic sugar" for
Somtheing = Class::new do
# code
end
Mostly that's true, but there is at least one difference to keep in mind
- multiple class SomeClass ... definitions will 'reopen' the existing
class and allow new methods to be added:
class TooClz
def a; "a"; end
end
# => nil
TooClz.new.a
# => "a"
class TooClz
def b; "b"; end
end
# => nil
TooClz.new.a
# => "a"
TooClz.new.b
# => "b"
While the assignment here scuppers that (notice Ruby complaining about
the constant being already initialized):
Clz = Class.new { def a; "a"; end }
# => Clz
Clz.new.a
# => "a"
Clz = Class.new { def b; "b"; end }
(irb):24: warning: already initialized constant Clz
# => Clz
Clz.new.a
NoMethodError: undefined method `a' for #<Clz:0xb7e7ad34>
from (irb):26
> Well, you can't subclass Class. You can do a bit of this kind of thing
> with Module (a superclass of Class), but bear in mind that class names
> are just like any other constant in Ruby, so you could do
>
> class OtherClass
> def new
> "Aha!"
> end
> end
>
> Foo = OtherClass.new
>
> Foo.class
> # => OtherClass
>
> Foo.new
> # => "Aha!"
>
> which is all very confusing, so probably best not to (outside of a few
> cases you'll find later I guess).
Well it looks like a factory object, since then if I Foo.new.class I get
(correctly) String.
Exactly, which is kind of how I see classes in Ruby, too (especially
since instances can change after instantiation thanks to the singleton
class).
> Yes, everything in Ruby is an object, at least from the point of view of
> your Ruby code.
I knew it was an object. I suppose I can say it is an Object.
Yes, sorry, I meant both object and Object there 
Then the main question: am I supposed to do this sort of things or is
someone gonna kill me? For example suppose I want to create kind of
synchronized methods (in the Java sense).
Syntactically it is quite beautiful to
synchronize :foo
[ and I think in Monitor.synchronize I would alias :foo, define a
synchronized version of foo that wraps the old :foo ]
Yes, you could do something like that:
class Module
def synchronize(sym)
alias_method("__orig_#{sym}", sym)
define_method(sym) do |*args|
puts "Sync"
send("__orig_#{sym}", *args)
puts "Done"
end
end
end
class SomeClass
def syncme(a)
puts a
end
synchronize :syncme
end
SomeClass.new.syncme("hello")
# output:
# Sync
# hello
# done
And no, no-one is going to get upset about it (well, no-one who does
Ruby anyway). I consider this kind of metaprogrammability to be one of
Ruby's sleekest features. Whether your boss, or your customer, or
whoever else, gets upset about it depends on too many external factors
to predict 
As you mentioned, there are other tools to help with synchronization
(e.g. Mutex) - this is just an example of what you _could_ do.
> For most purposes you'll want to define on Module instead, which allows
> your method in both class and module definition contexts.
I never thought to modules that way. I'm quite used to Python, where
namespaces are authomatically managed using files. Good.
> In Ruby Mammal would have to be a module, and I'd say
> self.kind_of?(Mammal) 
Why it would be a Module? In fact I could have functions and methods that
manipulate mammals and I may want to have the forementioned Donkey class to
subclass it.
It's probably a question of Ruby style I've not yet encountered.
The more I thought about this, the more I imagined an enormous class
hierarchy representing the natural world, so I decided to stop thinking
about it in the end 
> As you saw, a lot of stuff in Ruby is done with blocks. You can attach
> blocks to method calls, and one of the ways this is done is by declaring
> the final argument with a leading ampersand.
Yes. And I do like them a lot. It's one of those things you say "how have I
done _before_?".
But it does work even without...
def blrun(a)
puts a
yield
end
def blrun2(a, &b)
puts a
yield b
end
blrun("a") { puts "b" }
blrun2("a") { puts "b" }
I suppose it is useful if you want to "give a name" to the block. Am I
correct?
'yield' is usually the way I'd recommend you go, but yes, sometimes you
need to do something with the block other than call it right away.
The & can also be used with block methods to allow an existing Proc to
be used as the method's block, e.g.
blk = lambda { puts "b" }
blrun("a", &blk)
This comes in handy too when you want to pass a block attached to one
method to another method.
(Aside, the 'yield b' in your second example above will actually pass
the block as an argument to itself).
> Well, in Ruby functions are methods :).
Whose methods are them? I suppose it should be Object or maybe Kernel
(which in fact should be the same since Object includes Kernel, right?)
But I tried to define a method and call it with Object.method and gives
error...
Top-level 'functions' are private methods on Object (I was sure it was
Kernel but it doesn't appear so):
def amethod
"Hey!"
end
p Object.private_instance_methods.include?('amethod')
# => true
Object.new.send(:amethod)
# => "Hey!"
Since they're private, and on Object, you get the expected behaviour
that you can only call them with no receiver, and from anywhere.
路路路
On Tue, 2006-02-28 at 20:18 +0900, Mc Osten wrote:
On Tue, 28 Feb 2006 07:57:19 +0900, Ross Bamford wrote:
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk