Project

General

Profile

Actions

Feature #8377

closed

Deprecate :: for method calls in 2.1

Added by Anonymous almost 11 years ago. Updated over 10 years ago.

Status:
Rejected
Assignee:
-
Target version:
[ruby-core:54850]

Description

=begin
(({::})) is usually a constant lookup operator, but it can also be used to call methods. This can confusing to people learning Ruby.

I propose deprecating (({::})) as a method call operator in Ruby 2.1, then removing it in 2.2 (or whichever version comes after 2.1).

As part of the deprecation, Ruby's parser should emit a warning whenever (({::})) is used as a method call operator. This warning should be emitted even if (({-w})) is not enabled.
=end

Updated by Hanmac (Hans Mackowiak) almost 11 years ago

i am against that, what about methods that are defined in Kernel, but you want when you are inside an BasicObject?
you need something like:
Kernel::Array([])
or
Kernel.Array([])
what does make more sense for you?

Updated by Eregon (Benoit Daloze) almost 11 years ago

Hanmac (Hans Mackowiak) wrote:

i am against that, what about methods that are defined in Kernel, but you want when you are inside an BasicObject?
you need something like:
Kernel::Array([])
or
Kernel.Array([])
what does make more sense for you?

You need :: before Kernel, unless you define const_get
::Kernel::Array(3)
And in that case I much prefer
::Kernel.Array(3)
even if it does not look as nice because at least is is clear :: is constant resolution.

This is a weird case due to the upper case first letter, what do you think about:
::Kernel::puts "Hello"
versus
::Kernel.puts "Hello"

Updated by Anonymous almost 11 years ago

On Wednesday, 8 May 2013 at 4:35 AM, Hanmac (Hans Mackowiak) wrote:

i am against that, what about methods that are defined in Kernel, but you want when you are inside an BasicObject?
you need something like:
Kernel::Array([])
or
Kernel.Array([])
what does make more sense for you?

I actually prefer the '::Kernel.Array' example here (although I can see both sides of the argument), just because it makes it perfectly obvious that 'Array' is actually a method call and not something else.

On Wednesday, 8 May 2013 at 6:03 AM, Eregon (Benoit Daloze) wrote:

This is a weird case due to the upper case first letter, what do you think about:
::Kernel::puts "Hello"
versus
::Kernel.puts "Hello"

I definitely think '::Kernel.puts' is better here.

Updated by henry.maddocks (Henry Maddocks) almost 11 years ago

charliesome (Charlie Somerville) wrote:

(({::})) is usually a constant lookup operator, but it can also be used to call methods.

Is it? I thought it was the scope resolution operator.

charliesome (Charlie Somerville) wrote:

This can confusing to people learning Ruby.

It depends what language you're coming from.

Updated by Anonymous almost 11 years ago

+1

Updated by phluid61 (Matthew Kerwin) almost 11 years ago

=begin
henry.maddocks (Henry Maddocks) wrote:

charliesome (Charlie Somerville) wrote:

(({::})) is usually a constant lookup operator, but it can also be
used to call methods.

Is it? I thought it was the scope resolution operator.

While I know better, my gut instinct is always to agree; and that, by contrast, (({.})) is for the receiver of a method. For example:

 
::Kernel::Array(3)
#=> in global namespace,

in nested namespace 'Kernel',

invoke method 'Array' with no receiver

perlish: @::Kernel::Array(3)

::Kernel.Array(3)
#=> in global namespace,

in nested namespace 'Kernel',

invoke method 'Array' with 'Kernel' as receiver

perlish: @::Kernel->Array(3), or @::Kernel::Array(::Kernel,3)

However I know that's not the case; and in fact (({::})) means different things if the right-hand parameter thingy is a constant or function. I.e. (({obj.foo})) ~ (({obj::foo()})) ~ (({obj::foo})), but (({obj.FOO})) ~ (({obj::FOO()})) ≁ (({obj::FOO})), irrespective of ((|obj|)) being a Class or not.

The whole thing would be made much more clear if (({::FOO()})) and (({::foo})) were removed, and (({::})) was always only used to resolve constants.

charliesome (Charlie Somerville) wrote:

This can confusing to people learning Ruby.

It depends what language you're coming from.

Unless you're coming from Ruby, I'm pretty sure it's confusing for everyone.

=end

Updated by yorickpeterse (Yorick Peterse) almost 11 years ago

I'm in favour of deprecating :: for method calls as well. I'm all for
"multiple roads to Rome" but when it comes to the method calling syntax
I really want it to be consistent.

Actually getting rid of the operator is going to be interesting though
since I believe it's used in various places of MRI's core/std library as
well as third-party projects. This is probably something that shouldn't
be removed until at least 2.2.

Yorick

Updated by dgutov (Dmitry Gutov) almost 11 years ago

+1

"::" method call syntax has no advantages over ".", and it should be relatively simple to search through any codebase and convert the instances of using the former into the latter automatically.

Updated by bozhidar (Bozhidar Batsov) almost 11 years ago

+1

Apart from having no advantages over ".", "::" for method calls is very rarely used even anyways. It has been effectively deprecated by the Ruby community and it now has to be deprecated by Ruby itself :-)

Updated by rubiii (Daniel Harrington) almost 11 years ago

I'm also very much in favour of this change for simplicity.

When I learned about Nokogiri, I had no idea how this was supposed to work: Nokogiri::XML('')
Simply changing the code to use a '.' instead of '::' makes it clear, that we're sending the '.XML' message.
So why not encourage people to write code that is easier to read?!

Updated by henry.maddocks (Henry Maddocks) almost 11 years ago

phluid61 (Matthew Kerwin) wrote:

=begin
henry.maddocks (Henry Maddocks) wrote:

charliesome (Charlie Somerville) wrote:
It depends what language you're coming from.

Unless you're coming from Ruby, I'm pretty sure it's confusing for everyone.

=end

C++ and PHP also use the scope resolution operator.

As for the rest of what you said, I don't understand.

Updated by henry.maddocks (Henry Maddocks) almost 11 years ago

rubiii (Daniel Harrington) wrote:

I'm also very much in favour of this change for simplicity.

When I learned about Nokogiri, I had no idea how this was supposed to work: Nokogiri::XML('')
Simply changing the code to use a '.' instead of '::' makes it clear, that we're sending the '.XML' message.
So why not encourage people to write code that is easier to read?!

But '.' and '::' mean different things.
'::' means you are calling the method that is defined inside the Nokogiri module/namespace. Changing it to use a dot means that you are sending a message to the object Nokogiri.

Updated by yorickpeterse (Yorick Peterse) almost 11 years ago

Although in PHP you can also abuse the :: for both static and non
static method calls it's actually not used for namespaces (unlike Ruby),
instead it uses backslashes for that. Although this means that there's
still two ways to call a method (syntax wise) you at least don't end up
using a syntax feature meant for something completely unrelated to
method calls.

PHP is also a terrible language so I don't think it's worth comparing to
at all.

Yorick

Updated by Anonymous almost 11 years ago

henry.maddocks (Henry Maddocks) wrote:

But '.' and '::' mean different things.
'::' means you are calling the method that is defined inside the Nokogiri module/namespace. Changing it to use a dot means that you are sending a message to the object Nokogiri.

This isn't correct. Nokogiri.XML() and Nokogiri::XML() are equivalent.

Updated by matz (Yukihiro Matsumoto) almost 11 years ago

  • we haven't reached consensus to remove double colons for method calls from the language.
  • even if we do, 2.2 is not the right time to remove, maybe 3.0.
  • we have convention of Array class and Array(obj) conversion method, why not Foo::Bar and Foo::Bar(obj)?

Matz.

Updated by dgutov (Dmitry Gutov) almost 11 years ago

we haven't reached consensus to remove double colons for method calls from the language.

That's what this issue is about, isn't it?

even if we do, 2.2 is not the right time to remove, maybe 3.0.

I agree. But deprecating it would already be beneficial.

we have convention of Array class and Array(obj) conversion method, why not Foo::Bar and Foo::Bar(obj)?

Foo.Bar(obj) is much better. Writing it another way makes it confusing for a human reader, like it's somehow a special, callable class.

Updated by headius (Charles Nutter) almost 11 years ago

More cases of ambiguity:

obj::FOO is always a constant lookup. obj::FOO() is always a method call.

obj::foo is always a method call. There's no way to omit parens for a :: call if the method name is capitalized.

I support removal as well. It doesn't add anything and it confuses more often than not.

Updated by jeremyevans0 (Jeremy Evans) almost 11 years ago

headius (Charles Nutter) wrote:

More cases of ambiguity:

obj::FOO is always a constant lookup. obj::FOO() is always a method call.

obj::foo is always a method call. There's no way to omit parens for a :: call if the method name is capitalized.

obj::FOO 1 is a method call. You don't even need parens for a capitalized method that takes no arguments if you get creative: obj::FOO *[] :)

Updated by alexeymuranov (Alexey Muranov) almost 11 years ago

This is related and has not yet been rejected: #6806

Updated by jballanc (Joshua Ballanco) almost 11 years ago

=begin
I'm not sure how I feel about this. I understand the potential for confusion, but at the same time there's a certain congruity of being able to inherit from classes or methods that create classes in the same way. For example:

module Foo
  class Bar
    def say
      "Hello from Bar!"
    end
  end

  def self.Bar(greeting)
    klass = Class.new
    klass.class_eval <<-END
      def say
        "#{greeting} from parameterized Bar!"
      end
    END
    klass
  end
end

class Baz < Foo::Bar
  def shout
    say.upcase
  end
end

class Quux < Foo::Bar("Howdy")
  def shout
    say.upcase
  end
end

puts Baz.new.shout
puts Quux.new.shout

If we remove the ability to call methods with (({::})), then the class definition lines don't match as nicely:

class Baz < Foo::Bar
...
class Quux < Foo.Bar("Howdy")
...

Though I'd be interested to hear Mr. Evans opinion, since I think Sequel is where I've seen this used to the greatest effect...
=end

Updated by jeremyevans0 (Jeremy Evans) almost 11 years ago

jballanc (Joshua Ballanco) wrote:

If we remove the ability to call methods with (({::})), then the class definition lines don't match as nicely:

class Baz < Foo::Bar
...
class Quux < Foo.Bar("Howdy")
...

Though I'd be interested to hear Mr. Evans opinion, since I think Sequel is where I've seen this used to the greatest effect...

I'm against removing it, since I think there are places where the syntax looks nicer with :: (constructors such as Sequel::Model() and Nokogiri::XML()). Having only one way to do something for its own sake is not the ruby way, and I think the loss of backwards compatibility and nicer syntax outweighs the reduced confusion. I don't train new ruby programmers, though, so maybe I underestimate the confusion this causes.

Updated by judofyr (Magnus Holm) almost 11 years ago

On Sat, May 11, 2013 at 7:11 PM, jeremyevans0 (Jeremy Evans) <
> wrote:

Issue #8377 has been updated by jeremyevans0 (Jeremy Evans).

jballanc (Joshua Ballanco) wrote:

If we remove the ability to call methods with (({::})), then the class
definition lines don't match as nicely:

class Baz < Foo::Bar
...
class Quux < Foo.Bar("Howdy")
...

Though I'd be interested to hear Mr. Evans opinion, since I think Sequel
is where I've seen this used to the greatest effect...

I'm against removing it, since I think there are places where the syntax
looks nicer with :: (constructors such as Sequel::Model() and
Nokogiri::XML()). Having only one way to do something for its own sake is
not the ruby way, and I think the loss of backwards compatibility and nicer
syntax outweighs the reduced confusion. I don't train new ruby
programmers, though, so maybe I underestimate the confusion this causes.

Can't you use use #[] for this?

class Quuz < Foo::Bar["Howdy"]
end

class User < Sequel::Model[:User]
end

doc = Nokogiri::XML[data]

Updated by jeremyevans (Jeremy Evans) almost 11 years ago

On 05/14 04:01, Magnus Holm wrote:

On Sat, May 11, 2013 at 7:11 PM, jeremyevans0 (Jeremy Evans) <

I'm against removing it, since I think there are places where the syntax
looks nicer with :: (constructors such as Sequel::Model() and
Nokogiri::XML()). Having only one way to do something for its own sake is
not the ruby way, and I think the loss of backwards compatibility and nicer
syntax outweighs the reduced confusion. I don't train new ruby
programmers, though, so maybe I underestimate the confusion this causes.

Can't you use use #[] for this?

class Quuz < Foo::Bar["Howdy"]
end

class User < Sequel::Model[:User]
end

doc = Nokogiri::XML[data]

In the case of Sequel::Model, no, since Sequel::Model.[] is already
defined and does something different than creating a subclass.

Usage of [] for constructors seems fairly uncommon (Hash.[] is the
exception that comes to mind), so from a syntax level it is more likely
to be confusing. Using capitalized methods for constructors is much
more common in ruby (e.g. Kernel::{String,Array,Integer,Float,...}).

Jeremy

Updated by zzak (zzak _) almost 11 years ago

  • Target version changed from 2.1.0 to 3.0

Updated by tenderlovemaking (Aaron Patterson) over 10 years ago

  • Status changed from Open to Rejected
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0