48

If I run this file as "ruby x.rb":

class X
end
x = X.new

What is the thing that is calling "X.new"?

Is it an object/process/etc?

lorz
  • 1,129
  • 1
  • 11
  • 14

6 Answers6

54

Everything in Ruby occurs in the context of some object. The object at the top level is called "main". It's basically an instance of Object with the special property that any methods defined there are added as instance methods of Object (so they're available everywhere).

So we can make a script consisting entirely of:

puts object_id
@a = 'Look, I have instance variables!'
puts @a

and it will print "105640" and "Look, I have instance variables!".

It's not something you generally need to concern yourself with, but it is there.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • 1
    Some of the other answers are saying that the "ruby interpreter" is calling the new method. But I think you're saying that there's an intermediate step before that happens. And that is that an instance of Object is created and all execution is mediated through that object. I'm really just trying to fill in the blanks in my understanding of how the "new" method gets passed as a message to the X object. From what you're saying it seems the main (Object instance) passes the new method as a message to the X Class instance. Am I getting closer? – lorz May 27 '09 at 20:37
  • Well, I guess technically you can say it's the Ruby interpreter that does *everything*, since it's what actually executes your code. But from the standpoint of the language, yes, your description sounds exactly right. At the top level, when you first start typing in Ruby, you're in the context of that object. Most people don't use the top level like an object, but it is one. – Chuck May 27 '09 at 20:54
  • @steel Do you know where this magical behavior is documented? – Jonah May 18 '20 at 01:59
  • From the standpoint of the language? From the standpoint of Smalltalk? Maybe yes, the sender is the `main` object. Not sure, and not sure how applicable all that is here. Surely Ruby is influenced by Smalltalk. But to send a message explicitly we do `X.send(:new)`, not `send(X, :new)`. Neither that is the case in Smalltalk. And we have the [`caller` method](https://ruby-doc.com/core-2.5.5/Kernel.html#method-i-caller), not `sender`. So I think involving Smalltalk is far-fetched. And that's the terms I suggest to think in. `main` is the caller. `main` calls method `new` on class `X`. – x-yuri May 28 '21 at 09:12
  • I feel like w/o the other [question/answer](https://stackoverflow.com/a/917311/52499) this one makes less sense. – x-yuri May 28 '21 at 09:13
  • Added as an instance method of `Object`? I don't see that: `ruby -e 'def m; end; p [Object.instance_methods.include?(:m), Object.methods.include?(:m), Object.new.methods.include?(:m)]'` gives `[false, false, false]`. And do you know by any changes where `main` is created in the `ruby` source code? **UPD** I've got an answer to the first question. `ruby -e 'def m; end; p Object.private_instance_methods.include?(:m)'` gives `true`. That leaves the second one. – x-yuri Jan 04 '23 at 08:05
  • [Here](https://github.com/ruby/ruby/blob/v3_2_0/vm.c#L4078-L4080)'s the declaration of the main object. – x-yuri Jan 07 '23 at 07:15
  • I must confess I didn't like the "special property" part of your answer the first time I saw it. And at this point I don't see anything special about it. `def` defines a method of some class/module. At the top level that's `Object`. It would be special if at the top level `def` defined a function. Also `self` should refer to some object, unless you want to introduce a special case. At the top level that's the `main` object. So I'd rather say that `ruby` just follows suit. More on the way you can think about it in [my answer](https://stackoverflow.com/a/75066706/52499). – x-yuri Jan 10 '23 at 07:42
  • @x-yuri Ordinarily, `def` defines a method on `self`. So if the top level worked like any other context, `def foo` would define a foo method for `main` specifically, not for the Object class. For example, `fake_main = Object.new; fake_main.instance_eval { def foo; "bar"; end }; fake_main.foo` works, but `fake_main = Object.new; fake_main.instance_eval { def foo; "bar"; end }; foo` doesn't because the method only exists on `fake_main`, not any other Objects. That's the special property I'm talking about. – Chuck Feb 09 '23 at 00:40
  • `Ordinarily, def defines a method on self` You can think of it that way. But that is an oversimplification. In reality `def` defines methods on a `cref` (class reference). You can use `def` inside a method, and that would [define an instance method](https://gist.github.com/x-yuri/4ac40caddf2f9fc3e8eb09d947c1bb30), not a singleton method. Now if you imagine that ruby code is executed as part of a singleton method of an instance of `Object` (`main`), as I suggest in my answer, and as such `cref` points to `Object`, then it comes as no suprise... – x-yuri Feb 09 '23 at 07:39
  • ...that a method you define becomes an instance method of `Object`. But my abstraction is also leaky, and I bet you can't avoid special cases (sort of axioms) in any language... Anyways, I don't think I like your phrasing. To be precise and borrowing from the descriptions of `class_eval`/`instance_eval`, I'd say, "At the top level the code is executed within the context of the `Object` class and `self` points to an instance of `Object` called `main`." Or, "...within the scope of the `Object` class..."... – x-yuri Feb 09 '23 at 07:40
  • ...I must admit here, that descriptions of `class_eval`/`instance_eval` are also confusing. "In the context" means or happens to mean different things there. Do they fear mentioning the word "singleton class"?.. In all these cases (top level, `class_eval`, `instance_eval`) you want to know [where 2 things point to](https://stackoverflow.com/a/75125938/52499): `cref` and `self`. To not introduce unnecessary details you can call the first one scope/context. Anything less than that is an oversimplification, or vague wording. Or so I think. – x-yuri Feb 09 '23 at 07:40
13

The top-level caller is an object main, which is of class Object.

Try this ruby program:

p self
p self.class
Igor Krivokon
  • 10,145
  • 1
  • 37
  • 41
3

It's the X class. You're invoking the method "new" that creates an object of class X. So, if you run this text as a script, Ruby:

  • creates a new class X which is a subclass of Object, and which automatically (as a subclass of Object) inherits some methods, of which new is one.
  • sets up a name x
  • calls the new method on that new class X, creating an X instance object; x gets a reference to that object.
MarkDBlackwell
  • 1,994
  • 18
  • 27
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • "You're invoking the method "new"..." Jokingly or not, the question is, who are "you." :) Or rather, who is the sender. – x-yuri Dec 29 '22 at 08:14
2

It's the ruby interpreter running the line

x = X.new

As with many scripting languages, the script is interpreted from top to bottom rather than having a standard entry point method like most compiled languages.

workmad3
  • 25,101
  • 4
  • 35
  • 56
  • Yeah, I think the person asking this question was referring to `main` from the perspective of a C programmer. Everyone else here seems to be thinking of the top-level object named `main` in Ruby, which isn't quite the same thing. – Ajedi32 Jul 01 '15 at 14:57
1

main is the object in the context of which the top level code is executed. Which means that self at the top level refers to the main object:

$ ruby -e 'p self'
main

And that ruby follows the main's method lookup chain to determine which method to call:

$ ruby -e 'p singleton_class.ancestors'
[#<Class:#<Object:0x00007f9e9fdee230>>, Object, Kernel, BasicObject]

There could be more, but that's what you get from the get-go.

main itself is an instance of Object:

$ ruby -e 'p self.class'
Object

It has a singleton class with 2 methods (a method and an alias to be more precise):

$ ruby -e 'p singleton_class.instance_methods(false)'
[:inspect, :to_s]
$ ruby -e 'p singleton_methods'
[:inspect, :to_s]

It's defined here.

As you can see its to_s method returns "main" (overrides the Object's behavior), which is what you get when you do p self.

You can think that the code you execute is put into a main's method, after which the method is called. Along the lines of:

main = Object.new
class Object
  def main.go
    <your code here>
  end
end
main.go

That is a rough idea. Let me justify it in a couple of steps.

In Ruby you can actually nest methods, but every time you call the outer method, the inner one gets defined/redefined. More importantly, it's defined as an instance method of the enclosing class:

class A
  def m
    def m2; end
  end
end
A.new.m
p A.instance_methods(false)  # [:m2, :m]

The same happens here, but the enclosing class in this case is the singleton class of A:

class A
  class << self
    def m
      def m2; end
    end
  end
end
A.m
p A.singleton_class.instance_methods(false)  # [:m2, :m]

And what if we use the def self.<name> notation?

class A
  def self.m
    def m2; end
  end
end
A.m
p A.singleton_class.instance_methods(false)  # [:m]
p A.instance_methods(false)                  # [:m2]

So, self. affects only m, m2 becomes an instance method of A.

Actually, instead of self there can be some random object:

o = Object.new
A = Class.new do
  def o.m
    def m2; end
  end
end
o.m
p o.singleton_class.instance_methods(false)  # [:m]
p A.instance_methods(false)                  # [:m2]

I had to use Class.new because with class o wouldn't be visible inside the class definition.

Or actually I hadn't:

class A
  o = Object.new
  def o.m
    def m2; end
  end
  o.m
  p o.singleton_class.instance_methods(false)  # [:m]
  p A.instance_methods(false)                  # [:m2]
end

But let's ignore this branch of thought.

A couple of changes and you get this:

main = Object.new
Object.class_eval do
  def main.go
    @a = 1
    def m2
      puts @a
    end
    m2                            # 1
  end
end
main.go
p Object.instance_methods(false)  # [:m2]
p main.instance_variables         # [:@a]

I had to use class_eval for it to not complain that I'm trying to redefine the Object constant.

You can also add:

def main.to_s
  "main"
end
main.instance_eval { alias inspect to_s }

for completeness.

Another way is to use global variables:

$main = Object.new
class Object
  def $main.go
    @a = 1
    def m2
      puts @a
    end
    m2                            # 1
  end
end
$main.go
p Object.instance_methods(false)  # [:m2]
p $main.instance_variables        # [:@a]

Of course variables main/$main and the go method don't exist. But no more flaws come to mind when I think about this idea. The idea that it works as if your code is put into a main's method and executed by running the method.

Also this kind of explains why methods defined at the top level are visible everywhere:

a.rb:

f
$ ruby -e 'def f; puts "f"; end; require "./a"'
f

Because they become instance methods of Object.

And you can use instance variables, which are instance variables of the main object.

UPD I noticed that you can't define constants (in the usual way), classes and modules in main.go. So the abstraction appears to be leaky. I might try to amend it:

Object.class_eval do
  <your constants, classes, modules, methods>
  def main.go
    <the rest of the code>
  end
end

But at this point I'd rather say, that at the top level self points to the main object, and the current class reference to the Object class. More on class references here.

x-yuri
  • 16,722
  • 15
  • 114
  • 161
1

As Charlie Martin said, X.new is a call to the constructor on the X class, which returns an object of type X, stored in variable x.

Based on your title, I think you're looking for a bit more. Ruby has no need for a main, it executes code in the order that it sees it. So dependencies must be included before they are called.

So your main is any procedural-style code that is written outside of a class or module definition.

Tim Hoolihan
  • 12,316
  • 3
  • 41
  • 54