11

I am relatively new to Ruby and find it confusing that the following pairs of examples work equally well:

File.included_modules
File::included_modules

File.stat('mbox')         # Returns a '#<File::Stat..>' object
File::stat('mbox')

File.new("foo.txt", "w")
File::new("foo.txt", "w")

"asdf".size               # An instance method
"asdf"::size

2 + 3
2::send(:+, 3)            # An extreme example

File::new, in particular, is something I quite frequently encounter.

My question: Would it be non-idiomatic for me to avoid ever using the :: operator for qualifying the names of anything but classes, modules, and constants and, instead, consistently to use only dot syntax for all methods (class methods, module methods, and instance methods)?

To be clear: are there any situations in which I would want to refer to a method (whether in code or in documentation) using anything other than dot syntax?


Sources consulted:

Community
  • 1
  • 1
Tom Baker
  • 683
  • 5
  • 17
  • I use dot syntax for methods and double colon syntax for constants. I don't know if it's idiomatic or not, but doing it consistently makes it much easier to read and reason about code later. I personally think of the :: operator as the "namespace traversal" operator. – Chris Heald Dec 20 '15 at 21:32
  • Really, I think it depends on your preference and the way you're taught, I've been taught to only use `::` for constants. But if it works then go for it man. – 13aal Dec 21 '15 at 01:32

3 Answers3

4

Would it be non-idiomatic for me to avoid ever using the :: operator for qualifying the names of anything but classes, modules, and constants and, instead, consistently to use only dot syntax for all methods (class methods, module methods, and instance methods)?

No, it would in fact be idiomatic. Nobody ever uses :: to call methods, ever. Period.

The only time :: is used in conjunction with methods is when talking about methods. In that case, Foo#bar is used to talk about instance methods (i.e. a method bar that can be called on instances of Foo like foo.bar) and Foo::bar is used to talk about singleton methods (i.e. a method bar that can be called on Foo itself like Foo.bar). However, we only use :: for talking about methods, never for calling them.

Some notes:

  1. Technically speaking, there are no class methods or module methods in Ruby. Every object can have methods defined only for itself (so-called singleton methods), and since classes and modules are also objects, they can also have singleton methods. So, we will sometimes talk about "class methods" or "module functions", but in reality, those are just singleton methods.
  2. Well … actually, I lied. Sorry. Singleton methods don't exist either. They are really just normal instance methods of the singleton class of the object. But saying "instance method of the singleton class of the object" is a mouthful, so we just say "singleton method of the object", and likewise instead of "instance method of the class object's singleton class", we say just "class method". However, we only say this in the knowledge that those things actually don't really exist, and especially when talking to newbies, I prefer to use the long form instead of the short-form jargon.
  3. :: is used to dereference constants inside modules. The fact that those constants often point to modules or classes is not significant. Here is an example of resolving a constant which doesn't point to a module or class inside a module that isn't referenced by constant:

    module Foo; BAR = 42 end
    foo = Foo
    
    foo::BAR # => 42
    # ^   ^------------ not a module
    # |
    # +---------------- not a constant
    
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 2
    All absolute statements are wrong, always. Period :-D Yeah, you're right. – Jörg W Mittag Dec 21 '15 at 17:46
  • Thank you very much, @jörg-w-mittag -- this answers my question _and_ clarifies for me references like `Foo#bar` and `Foo::bar` that I find in documentation (hence the part of my question about "whether in code or in documentation"). – Tom Baker Dec 21 '15 at 18:56
1

Would it be non-idiomatic for me to avoid ever using the :: operator for qualifying the names of anything but classes, modules, and constants and, instead, consistently to use only dot syntax for all methods (class methods, module methods, and instance methods)?

Regarding the :: for method calls, I don't think there is any situation where you cannot substitute it with ., or where :: is preferred.

[A]re there any situations in which I would want to refer to a method (whether in code or in documentation) using anything other than dot syntax?

When the receiver is self, it is generally preferred to omit the self and . unless the method is either of foo= form, or is either []= or class.

When there is need to distinguish from a local variable with the same name as the method, explicit receiver and . can also be used, but () can be used instead.

When you need to call a private method with a receiver other than self, you can use receiver.send(:method_name) or receiver.instance_eval{method_name}.

sawa
  • 165,429
  • 45
  • 277
  • 381
  • 1
    Thank you, @sawa - good points re: `self`, though the first part of your response (re: `.` and `::`) already answers my main question. – Tom Baker Dec 21 '15 at 18:48
1

Are there any situations in which I would want to refer to a method (whether in code or in documentation) using anything other than dot syntax? [emphasis mine]

Some style guides (e.g. bbatsov's) recommend using :: syntax to call methods that are made to look like constructors.

# good
...
SomeModule::SomeClass()

"Methods that look like constructors" are generally methods with a capitalized first letter, such as Kernel#String, which looks like String(123) when you use it, or (as cited in the style guide linked above) Nokogiri::HTML(a_string), which is a singleton method on Nokogiri that has been made to look like a constructor for the class Nokogiri::HTML.

user513951
  • 12,445
  • 7
  • 65
  • 82
  • Thank you, @JesseSielaff - this is not something I have encountered yet but is good to know. – Tom Baker Dec 21 '15 at 19:00
  • Aha - so in my question above, I cite `File::new("foo.txt", "w")`, which I believe I have seen in documentation. So would this usage actually be idiomatic (according to some people) because it looks like, or is, a constructor? – Tom Baker Dec 21 '15 at 19:35
  • One [ruby-doc page](http://ruby-doc.org/core-1.9.3/Regexp.html) refers in the first paragraph to the "`Regexp::new` constructor, and in the very next paragraph to the "`Regexp.new` constructor". Now I'm unsure whether that is even a "constructor"... – Tom Baker Dec 22 '15 at 04:03