Method names can have the name that begins with capital letter. How should they be handled?
-- matz.
I would actually rather see them (. and ::) dis-unified: namely, . for methods (messages to receiver), :: for changing scope and retrieving constants. Calling a method as Klass::meth, just because the receiver is a class, seems to me to be an unnecessary special case.
-- David Black
@Matz: In my opinion there shouldn't be any methods beginning with a capital letter. Ruby distinguishes between method/variable names and constant/module names by their first letter, so why allow inconsistent exceptions? Maybe I should add that to my RCR, or write a further one about first letters. -- Malte
Malte: When you're saying "there shouldn't be any methods beginning with a capital letter', do you mean that we should change existing methods despite of the incompatibility?
-- matz.
Well, incompatibility isn't nice; however my answer is yes. And furthermore: Ruby shouldn't allow methods beginning with a capital letter at all, as it doesn't allow constants beginning with a lower case letter, too. Just for consistency. --Malte
Name restriction is just for variables (and constants). Ruby have not restrcted method names from the beginning. Hence no inconsistency exists. Do you think it is fair to break compatibity to introduce new "consistency" that you've just brought in?
If so, what should we do to existing methods that begin with capital letter?
-- matz.
Concerning existing methods that begin with a capital letter: Well, it depends. The only such methods I know of are Float(), String() etc., which I never use (because I cannot remember the differences between using these methods or just kindly asking my object to do the job, using to_f, to_s etc.). In fact I also don't like Float() and String() because they look exactly like class names - I have to look at the context in order to know what it is. If there had been a rule that the first letter of method names is always lowercase, these methods would probably have been called to_float, to_string, or similar.
However, it seems that you aren't that enthusiastic about my proposal, are you? --Malte
No. I didn't design variable names and method names to share same rule. If you want to change my mind, define "consistency" first and tell me its benifits.
-- matz.
Well, I'm not in favor or against this, but I'm not sure I understand the problem with constants and methods having the same name. Am I wrong thinking that this problema already exists for constants and methods with the same name in the current scope? -- gabriele renzi
A few comments. First, the way :: is currently implemented, I see no useful reason why it should work for method calls. As David pointed out, some people do use :: when making method calls on a class (I used to do this myself). I don't know where this habit came from, but I suspect it's left over from C++ which requires this syntax when calling static member functions without an object. It makes sense in C++, though, because in C++ classes are not objects.
Secondly, using :: to call methods could be useful. For example, it would be nice if I could write:
class Foo
BAR = 42
end
#
def foo
puts Foo::BAR
end
then later change Foo to:
class Foo
remove_const :BAR
#
@@bar = 0
def BAR
@@bar += 1
return @@bar
end
end
and still have foo() work as before. This doesn't work, though; instead to get this behavior I have to resort to using const_missing(). Maybe that's a good thing -- having a constant evaluate to a different object every time probably isn't a good idea (though perhaps it's useful for lazily-evaluating a constant).
While I can think of a use for :: to work for methods (iff the method name begins with an uppercase letter), I can't think of a use for . to work for constants. Accepting this RCR without finding such a use would be foolish, IMO.
Lastly, and I think this is getting a little off the subject of the RCR, the Float()/Integer()/etc. methods have always confused me. The to_s method makes sense to me; converting an object to a string representation is a common task, and every object has some string representation. But given a string, how do I convert back to the original type? The to_f/to_i methods don't allow me to do any error checking, and their names don't include the name of the class, so it doesn't make sense to me to use to_xxx as a general method for converting to an object of a particular type. I could instead use Float()/Integer()/etc. but everyone seems so fixed on defining a to_xxx method for their user-defined types that this also doesn't work unless we all agree to start writing both to_xxx methods and toplevel methods for our classes. If we did this, then I could write a nifty method similar to boost::lexical_cast<>:
class Object
def to_type(t)
Kernel.send(t.name, self.to_s)
end
end
#
i = 42
p f.to_type(Float) #=> 42
(not that converting from one type to another using a string as an intermediate representation is generally a good idea, but I do like the idea of being able to convert any one type to any other type without having to look up how to do it in the documentation, only to find that the library author has picked yet another representation for this conversion, since it's not standardized).
As for why Float()/Integer()/etc. confuse me (bet you thought I was rambling and forgotten I'd said that, eh?), what in their name indicates that these methods take a string as an argument and construct an object of the same type as their name out of it (or in the case of Integer, an instance of a derived type)? Better IMO would be Foo.from_s, since this at least indicates that I'm converting from a string. Better yet would be a general solution that lets me convert any object to any other type (I'm not looking for an implementation -- that is impossible -- just a good representation). I haven't given this enough thought to write an RCR yet, but maybe someone else will read this and come up with a good idea.
-- Paul Brannan
If you're going to write an RCR about a generalized conversion framework I'd vote for it :) But the point of, say, Integer() vs to_i() is that they have different behaviour. How do you unify the various behaviours (exception on error/default result on error/magic conversion like to_str())? Anyway Object.as(aClass) is much nicer imho :)
-- gabriele renzi
The problem I don't know how to solve with Object.as(aClass) -- which is the same as #to_type -- is defining the conversion to work with multiple types. Ruby only supports dispatching based on the type of the receiver, so to define two types that can both be converted from an Integer would require overriding Integer#as and calling the original if the type doesn't match, which is ugly, IMO. I could combine this with some sort of double-dispatch mechanism, but that's the part I haven't thought through well.
-- Paul Brannan
I was thinking about some kind of structure somewhere (i.e. a @@Transformations Hash in Object) that could old procedures to convert objects indexed by a double key (self.class and aClass). Actually I believe that having some kind of Graph datastructure could be better, so that we could have convertions beetween type A and C if A->B and B->C exist.
-- gabriele renzi
I think all of this would have to be called something other than "type", "to_type", etc., keeping in mind that #type is itself deprecated due to the inadequacy of an object's class name to describe its type.
-- David Black
Actually this (in my vision, can't say Paul agrees) is much more powerful than pure class conversion. You could have object_with_read.as(Readable) where the convertion engine includes a module, or could define a behaviour(an_io.as(CapitalizedWriter) will just wraps calls). This even works fine with object with singleton methods.
You could even assert properties of an object like: 13.as(Prime)#=>13;12.as(Prime) #=>raise an Exception. This would actually work like Common LISP's soft typing+Python's adaption protocol, practically killing the need for to_*, kind_of?,is_a? and reduce the use of respond_to?, yet giving to the developer better conversion service,crash-early behaviour and documentation value.But we're OT, maybe this should go to c.l.r ?
-- gabriele renzi
Method names can have the name that begins with capital letter. How should they be handled?
-- matz.
I would actually rather see them (. and ::) dis-unified: namely, . for methods (messages to receiver), :: for changing scope and retrieving constants. Calling a method as Klass::meth, just because the receiver is a class, seems to me to be an unnecessary special case.
-- David Black
@Matz: In my opinion there shouldn't be any methods beginning with a capital letter. Ruby distinguishes between method/variable names and constant/module names by their first letter, so why allow inconsistent exceptions? Maybe I should add that to my RCR, or write a further one about first letters. -- Malte
Malte: When you're saying "there shouldn't be any methods beginning with a capital letter', do you mean that we should change existing methods despite of the incompatibility?
-- matz.
Well, incompatibility isn't nice; however my answer is yes. And furthermore: Ruby shouldn't allow methods beginning with a capital letter at all, as it doesn't allow constants beginning with a lower case letter, too. Just for consistency. --Malte
Name restriction is just for variables (and constants). Ruby have not restrcted method names from the beginning. Hence no inconsistency exists. Do you think it is fair to break compatibity to introduce new "consistency" that you've just brought in?
If so, what should we do to existing methods that begin with capital letter?
-- matz.
Concerning existing methods that begin with a capital letter: Well, it depends. The only such methods I know of are Float(), String() etc., which I never use (because I cannot remember the differences between using these methods or just kindly asking my object to do the job, using to_f, to_s etc.). In fact I also don't like Float() and String() because they look exactly like class names - I have to look at the context in order to know what it is. If there had been a rule that the first letter of method names is always lowercase, these methods would probably have been called to_float, to_string, or similar.
However, it seems that you aren't that enthusiastic about my proposal, are you? --Malte
No. I didn't design variable names and method names to share same rule. If you want to change my mind, define "consistency" first and tell me its benifits.
-- matz.
Well, I'm not in favor or against this, but I'm not sure I understand the problem with constants and methods having the same name. Am I wrong thinking that this problema already exists for constants and methods with the same name in the current scope? -- gabriele renzi
A few comments. First, the way :: is currently implemented, I see no useful reason why it should work for method calls. As David pointed out, some people do use :: when making method calls on a class (I used to do this myself). I don't know where this habit came from, but I suspect it's left over from C++ which requires this syntax when calling static member functions without an object. It makes sense in C++, though, because in C++ classes are not objects.
Secondly, using :: to call methods could be useful. For example, it would be nice if I could write:
then later change Foo to:
and still have foo() work as before. This doesn't work, though; instead to get this behavior I have to resort to using const_missing(). Maybe that's a good thing -- having a constant evaluate to a different object every time probably isn't a good idea (though perhaps it's useful for lazily-evaluating a constant).
While I can think of a use for :: to work for methods (iff the method name begins with an uppercase letter), I can't think of a use for . to work for constants. Accepting this RCR without finding such a use would be foolish, IMO.
Lastly, and I think this is getting a little off the subject of the RCR, the Float()/Integer()/etc. methods have always confused me. The to_s method makes sense to me; converting an object to a string representation is a common task, and every object has some string representation. But given a string, how do I convert back to the original type? The to_f/to_i methods don't allow me to do any error checking, and their names don't include the name of the class, so it doesn't make sense to me to use to_xxx as a general method for converting to an object of a particular type. I could instead use Float()/Integer()/etc. but everyone seems so fixed on defining a to_xxx method for their user-defined types that this also doesn't work unless we all agree to start writing both to_xxx methods and toplevel methods for our classes. If we did this, then I could write a nifty method similar to boost::lexical_cast<>:
(not that converting from one type to another using a string as an intermediate representation is generally a good idea, but I do like the idea of being able to convert any one type to any other type without having to look up how to do it in the documentation, only to find that the library author has picked yet another representation for this conversion, since it's not standardized).
As for why Float()/Integer()/etc. confuse me (bet you thought I was rambling and forgotten I'd said that, eh?), what in their name indicates that these methods take a string as an argument and construct an object of the same type as their name out of it (or in the case of Integer, an instance of a derived type)? Better IMO would be Foo.from_s, since this at least indicates that I'm converting from a string. Better yet would be a general solution that lets me convert any object to any other type (I'm not looking for an implementation -- that is impossible -- just a good representation). I haven't given this enough thought to write an RCR yet, but maybe someone else will read this and come up with a good idea.
-- Paul Brannan
If you're going to write an RCR about a generalized conversion framework I'd vote for it :) But the point of, say, Integer() vs to_i() is that they have different behaviour. How do you unify the various behaviours (exception on error/default result on error/magic conversion like to_str())? Anyway Object.as(aClass) is much nicer imho :)
-- gabriele renzi
The problem I don't know how to solve with Object.as(aClass) -- which is the same as #to_type -- is defining the conversion to work with multiple types. Ruby only supports dispatching based on the type of the receiver, so to define two types that can both be converted from an Integer would require overriding Integer#as and calling the original if the type doesn't match, which is ugly, IMO. I could combine this with some sort of double-dispatch mechanism, but that's the part I haven't thought through well.
-- Paul Brannan
I was thinking about some kind of structure somewhere (i.e. a @@Transformations Hash in Object) that could old procedures to convert objects indexed by a double key (self.class and aClass). Actually I believe that having some kind of Graph datastructure could be better, so that we could have convertions beetween type A and C if A->B and B->C exist.
-- gabriele renzi
I think all of this would have to be called something other than "type", "to_type", etc., keeping in mind that #type is itself deprecated due to the inadequacy of an object's class name to describe its type.
-- David Black
Actually this (in my vision, can't say Paul agrees) is much more powerful than pure class conversion. You could have object_with_read.as(Readable) where the convertion engine includes a module, or could define a behaviour(an_io.as(CapitalizedWriter) will just wraps calls). This even works fine with object with singleton methods.
You could even assert properties of an object like: 13.as(Prime)#=>13;12.as(Prime) #=>raise an Exception. This would actually work like Common LISP's soft typing+Python's adaption protocol, practically killing the need for to_*, kind_of?,is_a? and reduce the use of respond_to?, yet giving to the developer better conversion service,crash-early behaviour and documentation value.But we're OT, maybe this should go to c.l.r ?
-- gabriele renzi