What's the rationale/history for the # convention of identifying methods in Ruby?
Asked Answered
S

2

9

For example, I've always seen methods referred to as String#split, but never String.split, which seems slightly more logical. Or maybe even String::split, because you could consider #split to be in the namespace of String. I've even seen the method alone, when the class is assumed/implied (#split).

I understand that this is the way methods are identified in ri. Which came first?

Is this to differentiate, for example, methods from fields? I've also heard that this helps differentiates instance methods from class methods. But where did this start?

Slotter answered 26/6, 2010 at 9:57 Comment(1)
I want to know why this convention isn't mentioned/explained in books/tutorials when discussing ruby's naming conventions. I found it confusing to see method names with the '#' prefix in various discussions and only being able to guess what significance the prefix had. The fact that # begins a comment in .rb source makes it doubly confusing. As you can imagine, it's not the easiest thing to search for, so thanks for having asked this somewhere I was able to stumble on it. I wonder if I'll be able to find it again when I forget these details in 6 months of non-ruby activity...Pinite
S
8

The difference indicates how you access the methods.

Class methods use the :: separator to indicate that message can be sent to the class/module object, while instance methods use the # separator to indicate that the message can be sent to an instance object.

I'm going to pick the Complex class (in Ruby 1.9) to demonstrate the difference. You have both Complex::rect and Complex#rect. These methods have different arity and they serve entirely different purposes. Complex::rect takes a real and an imaginary argument, returning a new instance of Complex, while Complex#rect returns an array of the real and imaginary components of the instance.

ruby-1.9.1-p378 > x = Complex.rect(1,5)
 => (1+5i) 
ruby-1.9.1-p378 > x.rect
 => [1, 5] 
ruby-1.9.1-p378 > x.rect(2, 4) # what would this even do?
ArgumentError: wrong number of arguments(2 for 0)
    from (irb):4:in `rect'
    from (irb):4
    from /Users/mr/.rvm/rubies/ruby-1.9.1-p378/bin/irb:17:in `<main>'

I think the reason that they don't use . as the separator for everything is that it would be ambiguous whether the method belongs to a class or an instance. Now that I'm used to Ruby doing this, I actually see it as a drawback to other languages' conventions, to be honest.

Also, this is somewhat of a completely unrelated topic from fields because all messages you can send are messages, properly speaking, even if it looks like a publicly accessible field. The closest thing you have to fields are attributes or instance variables, of course, which are always prefixed with @ and are not directly accessible from outside the instance unless you are using inheritance or Object#instance_variable_get/_set.

As to specifically why they chose :: and #? :: makes sense to me because it conventionally separated namespaces, but # was probably just a symbol that wasn't used in other nomenclature and could unambiguously be recognized as an instance-method separator.

Scheller answered 26/6, 2010 at 12:32 Comment(6)
Now for bonus points: why not use :: for invoking class methods while using # for invoking instance methods? Then there's no ambiguity both in reading the docs and in the actual code.Fibriform
@JUST: You can do Complex::rect(1,5). But since # starts a line-comment, I don't think the latter is going to be adopted anytime soon.Scheller
I'm aware of this. The point is that it's still pretty damned odd to document with # instead of .. Especially since you can invoke with ::. It's one of these ineffable mysteries of Ruby for me. Since we already have the @ and @@ prefix rules, why not do the same for methods and force (not allow, force) class methods to be invoked with :: and force (not allow, force) instance methods to be invoked with .?Fibriform
@JUST: That's a legitimate question. I don't have an authoritative answer on this, but I'd guess the main reason is that it would break all backwards-compatibility. Also it would scare off newcomers to some extent, but that's a lesser concern.Scheller
@JUST MY correct OPINION: The reason why there are no different calling conventions for different kinds of methods in Ruby is quity simply because there are no different kinds of methods in Ruby. There are only instance methods.Exum
What the...Math::sqrt(9) blew me away.Slotter
G
3

I understand that this is the way methods are identified in ri. Which came first?

Yes, this is where it came from. When you use #, it automatically hyperlinks your methods, so references to other methods in documentation began being prefixed by the # sign. See here:

Names of classes, source files, and any method names containing an underscore or preceded by a hash character are automatically hyperlinked from comment text to their description.

You can't actually invoke a method this way, however. But that shouldn't be surprising; after all, <cref ...> is an invalid statement in C# despite being a valid documentation tag.

Goldfarb answered 26/6, 2010 at 12:45 Comment(3)
So this the first place methods were referred to by hashes?Slotter
@Justin L.: It's what created the convention, yes.Goldfarb
Was this because the rdoc files used method names as anchor ids, and html uses # to seperate the location hash from the document identifier?Introductory

© 2022 - 2024 — McMap. All rights reserved.