[curiousity] why aren't declarations just syntactic sugar?

Hello!

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

Lionel Thiry wrote:

Hello!

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?

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

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

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... :slight_smile:

Regards,

Bill

···

From: "Lionel Thiry" <lthiryidontwantspam@skynetnospam.be>

Hi,

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

Lionel Thiry wrote:

Hello!

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.

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 :slight_smile:

Lionel Thiry

E

"Bill Kelly" <billk@cts.com> scribbled:

It'd probably at least have to be:

(MyClass ||= Class.new) do

so we can re-open classes as we currently do.

"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

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:

···

On Wed, 6 Apr 2005, Saynatkari wrote:

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 :slight_smile:

----------
     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 <cjs@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
      Make up enjoying your city life...produced by BIC CAMERA

Dave Burt wrote:

"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.

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

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.

"Florian Groß" <florgro@gmail.com> responded:

Dave Burt wrote:

"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

No, they won't :wink:

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

···

On Fri, 08 Apr 2005 07:24:54 +0200, Jon Raphaelson <jonraphaelson@gmail.com> wrote:

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

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.

cjs

···

On Fri, 8 Apr 2005, Jon Raphaelson wrote:

Both of those will produce the output
Oh yes!

--
Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
      Make up enjoying your city life...produced by BIC CAMERA

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.

cjs

···

On Sun, 10 Apr 2005, Dominik Bathon wrote:

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.

--
Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
      Make up enjoying your city life...produced by BIC CAMERA

Curt Sampson schrieb:

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

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

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