I'd like to know why in ruby, a construction like:
class MyClass
...
end
isn't just a syntactic sugar for:
MyClass = Class.new do
...
end
Is it a problem about block variable binding? Is it a problem of speed?
Something else?
Thanks in advance.
--
Lionel Thiry
It'd probably at least have to be:
(MyClass ||= Class.new) do
so we can re-open classes as we currently do.
Other than that... I dunno... :)
Regards,
Bill
I've seen this discussed... I think it's just historical reasons
first of all. I'm not sure this kind of unification was "thought of"
at the beginning.
But there are also other considerations, I think. For example, a block
is a closure, whereas the body of a class definition is not. A question
of scope.
Hal
At Wed, 6 Apr 2005 08:24:39 +0900,
Lionel Thiry wrote in [ruby-talk:137002]:
> class MyClass
> ...
> end
class hides outer scope, so this causes an error.
x = 1
class MyClass
p x # => Name Error
end
> isn't just a syntactic sugar for:
> MyClass = Class.new do
> ...
> end
But block doesn't.
--
Nobu Nakada
I, I think that is a good idea. On the other hand, I also think that
def foo(x)
do_something_with x
end
Should be syntactic sugar for
def(:name => :foo,
:bind => binding,
:body => {|x| do_something_with x}
)
Then again, the current system works well too :)
> Lionel Thiry
E
"MyClass do ..." looks like a syntax error to me.
How about a Class#| for this (think set union like Array#|)?
MyClass |= Class.new do
...
First-class methods would make implementation of something like this
convenient.
Cheers,
Dave
> "MyClass do ..." looks like a syntax error to me.
>
> How about a Class#| for this (think set union like Array#|)?
>
> MyClass |= Class.new do
> ....
>
> First-class methods would make implementation of something like this
> convenient.
That would not work though as the block can not bind to the | operator.
I know that. I was thinking, "what if you could add all the methods defined
in that anonymous class to MyClass?"
This would effectively be a way of doing multiple inheritance, and has all
the problems associated with that. (e.g. Class.new will make a class that
inherits from Object, and those methods would have to be "ORed" into MyClass
as well as any explicitly defined.) So it's a bad thing.
It makes more sense if the RHS is a Module. And you can do that already,
with mix-ins (extend, include)
I still think it's an interesting thought.
Cheers,
Dave
> I, I think that is a good idea. On the other hand, I also think that
>
> def foo(x)
> do_something_with x
> end
>
> Should be syntactic sugar for
>
> def(:name => :foo,
> :bind => binding,
> :body => {|x| do_something_with x}
> )
>
> Then again, the current system works well too :)
Nah, your suggestion is much better. [(let f (lambda ...))]
This is the thing that kills me about ruby, and makes it a very
difficult language to learn well: all the stupid "tricks" you need to
learn, at great pain and expense.
For example: explain the results of these two programs to me:
----------
def do_me_harder
puts "Oh yes!"
end
puts do_me_harder
----------
module Foo
def do_me_harder
puts "Oh yes!"
end
puts do_me_harder
end
----------
cjs
--
Curt Sampson <c...@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
Make up enjoying your city life...produced by BIC CAMERA
Both of those will produce the output
Oh yes!
nil
which is absolutly correct. I'm not sure what the problem with those is.
If it is that you are confused about the nil, that's because puts
returns nil, and you are puts'ing the result of do_me_harder, which is
the result of the last expression in do_me_harder, which is a puts and
hence nil.
If the confusion is that the program wrapped in a module prints
something, that is because, unlike other programming languages where the
class/module defintions are read but not executed, in ruby those
definitions are executed. This is really useful, for example this is the
way alias works and mixins I believe (but I don't know for sure, so if
I'm worng sorry), as well as most domain specific language stuff.
> Curt Sampson wrote:
> <snip>
>> For example: explain the results of these two programs to me:
>> ----------
>> def do_me_harder
>> puts "Oh yes!"
>> end
>> puts do_me_harder
>> ----------
>> module Foo
>> def do_me_harder
>> puts "Oh yes!"
>> end
>> puts do_me_harder
>> end
>> ----------
>> cjs
>
> Both of those will produce the output
>
> Oh yes!
> nil
No, they won't ;-)
The 2nd will raise an exception:
NameError: undefined local variable or method `do_me_harder' for Foo:Module
do_me_harder is an instance method (you can only call it on an instance of
a class including Foo):
class A
include Foo
end
A.new.do_me_harder
But the following would work:
module Foo
def Foo.do_me_harder
puts "Oh yes!"
end
puts do_me_harder
end
In this case do_me_harder is a singleton method of module Foo.
HTH,
Dominik
> Both of those will produce the output
> Oh yes!
You and I must be using different versions of ruby:
$ cat z.rb
module Foo
def do_me_harder
puts "Oh yes!"
end
do_me_harder
end
$ ruby z.rb
z.rb:5: undefined local variable or method `do_me_harder' for Foo:Module (NameError)
Whereas:
$ cat z1.rb
def do_me_harder
puts "Oh yes!"
end
do_me_harder
$ ruby z1.rb
Oh yes!
Now care to try again with an explanation?
Two notes on the previous post, BTW. First the doubled "puts" was not
intentional; just me typing without proof-reading. Second, this may have
worked for you because you put both code samples into the same file and
ran them in the order I gave orginally, which was reversed from above.
> module Foo
> def Foo.do_me_harder
> puts "Oh yes!"
> end
> puts do_me_harder
> end
>
> In this case do_me_harder is a singleton method of module Foo.
Oops! Shoulda read your post first. Anyway, so what's going on with this,
as compared to doing the same thing outside a module declaration, which
I'd understood to mean you were defining stuff in the "top-level module."
Well, it's really the top-level class (i.e., Object), right? But then,
def hello
puts "hello"
end
class Object
def goodbye
puts "goodbye"
end
end
Object.new.goodbye # prints "goodbye"
goodbye # prints "goodbye"
class Object
hello # prints "hello"
end
Object.new.hello # private method `hello' called for #<Object:...
I dunno; a lot of my predictions about what should happen in Ruby don't
work out very well.
I wish that there were a two-page document somewhere explaining just the
language syntax itself that would, if read very carefully, explain all
of this.
This defines a private instance method of Object. You define the method
without specifying a class, just like a procedure in a non-OO language.
Because it is defined in Object, you can call it everywhere:
hello
class X
hello
def m
hello
end
end
You can really treat it like a standalone procedure. But you cannot
treat it like an object's method, because it is private. Private methods
can only be called without specifying the receiver of the method.
"foo".hello # => error, private method...
There's a trick for calling private methods, though:
"foo".send( :hello ) # => hello
The method is there (inherited from Object), but it is private. This is
a clever way to be able to either write procedural or OO code and to
even use both together.
> class Object
> def goodbye
> puts "goodbye"
> end
> end
This defines a public (per default) instance method of Object.
> Object.new.goodbye # prints "goodbye"
Send the message to a new object, which inherits the (public) method
"goodbye" from Object (as all objects do).
> goodbye # prints "goodbye"
Send the message to self, the top level object (main). This is an
Object, so it inherits method "goodbye" from Object, too.
> class Object
> hello # prints "hello"
> end
Send the message to the class Object. Since classes are instances of
Object in Ruby, even the class Object inherits method "goodbye" from Object.
> Object.new.hello # private method `hello' called for #<Object:...
Send the message to a new object. The object inherits method "hello"
from Object, but it is a private method, so it can't be called with an
explicit receiver.
> I dunno; a lot of my predictions about what should happen in Ruby don't
> work out very well.
When learning Ruby, I made the experience that most of the times the
code I wrote just worked. Without thinking about the language's
internals I wrote some kind of pseudocode in Ruby syntax and more than
often found that I just could run it. Sometimes I really was surprised
that the code I had written was working, and I thought "how is Ruby
doing this?" Then I started to experiment with the language and I had
many surprises, but it finally made sense most of the times, at least
for me. I got the most POLS out of Ruby when not thinking about Ruby.
> I wish that there were a two-page document somewhere explaining just the
> language syntax itself that would, if read very carefully, explain all
> of this.
I don't think that the syntax alone would have helped you in this case.
Regards,
Pit