Feature #10683
openfix inconsistent behavior of Kernel.Hash()
Description
I find the way the global function Hash
(aka Kernel.Hash
) works a bit confusing.
To illustrate:
Hash(nil) #=> {} (1)
Hash({}) #=> {} (2)
Hash([]) #=> {} (3)
# but
Hash([[1,2]]) #! TypeError (4)
Case (1) and (2) make perfect sense to me (calling Hash(var)
when var
is an optional argument defaulting to nil
will always give a (possibly empty) Hash or a TypeError, which is very useful).
Case (3) however seems inconsistent, since (4) doesn't work.
To contrast this with the respective String
function:
String([]) #=> "[]"
String('') #=> ""
String({}) #=> "{}"
String(0) #=> "0"
String(nil) #=> ""
it seems that calling String(obj)
is equivalent to calling obj.to_s
.
Thus I would assume Hash(obj)
being equivalent to calling obj.to_h
.
It is not though (calling to_h
on [[1,2]]
gives {1=>2}
, while using Hash()
raises a TypeError
).
I propose to do one of the following changes:
- either remove the special handling of
[]
, such that onlynil
or aHash
are valid values to be passed toHash()
, or - change
Hash()
to callto_h
on it's argument, when the argument is neithernil
nor aHash
.
Updated by shevegen (Robert A. Heiler) almost 10 years ago
Interesting. [] is indeed treated differently than
Hash([nil])
TypeError: can't convert Array into Hash
Hash([1,2])
TypeError: can't convert Array into Hash
Perhaps there is a reason for [] as input is being
treated differently?
Updated by sawa (Tsuyoshi Sawada) almost 10 years ago
Since nil.to_h
is {}
, which equals Hash(nil)
, and some_hash.to_h
is some_hash
, which equals Hash(some_hash)
, your claim:
- change
Hash()
to callto_h
on it's argument, when the argument is neithernil
nor aHash
.
is equivalent to
- change
Hash()
to callto_h
on it's argument.
I don't think either of your proposed options will be accepted.
Updated by recursive-madman (Recursive Madman) almost 10 years ago
I don't think either of your proposed options will be accepted.
I can see that making Hash(obj)
equivalent to obj.to_h
would be a major change in functionality.
The primary reasons for opening up this issue are two points:
- The special case of
[]
- what does it accomplish? - The inconsistency between the global
Hash
andString
functions --String(obj)
being equivalent toobj.to_s
, whileHash(obj)
being roughly equivalent toobj.to_hash
(instead ofobj.to_h
)
As written elsewhere, the short conversion methods (to_i, to_s, to_h, ...) are supposed to be for explicit conversion, while the long ones (to_int, to_str, to_hash, ...) are for implicit conversion.
Now how do these global functions fit into the picture? What can a ruby developer expect them to do without having to read their individual documentation?