Open KES777 opened 3 years ago
length is a string operation, but == is a numeric comparison. Why would you check length?
What would this do if applied to strings?
Would be nice to just: $v === 0
It sounds like you're describing a defined-and operator for numerical comparisons.
defined-and-do-something operators have been discussed before (probably in multiple places). For example, on the P5P mailing list a couple of years ago, a discussion started from a suggestion to simplify things like: if(defined($foo) && $foo =~ /bar/)
. That particular discussion stalled because adding multiple variants of existing operators seemed undesirable, but unfortunately, no-one suggested a multi-operator syntax that (1) was nice (2) covered enough operators to be worthwhile (3) didn't clash with existing syntax.
===
has the same problem, in that it only helps with one operator.
Also, given that ===
is used in other languages to force same-type comparisons, @haarg's point is a good one:
What would this do if applied to strings?
(Including if one of $v === $y
is a number and the other is a string.)
Also complicating any operator like this is that values are not numbers or strings, just used as such by certain operators.
@haarg : here I use length to escape from situation when ""==0
With my code I try to filter out all values which are undef
, empty string
, true
@richardleach : What is the best way to find those discussions? May we link those to this ticket? Thank you.
@KES777 - the specific p5p discussion I mentioned starts at https://www.nntp.perl.org/group/perl.perl5.porters/2019/02/msg253742.html
I would prefer it if the ===
operator implemented a functionality similar to this function:
use Scalar::Util 'refaddr';
use experimental 'signatures';
sub eqq ($x, $y) {
return !defined $y unless defined $x;
return !!0 unless defined $y;
return !!0 unless ref $x eq ref $y;
return length(ref $x) ? refaddr $x == refaddr $y : $x eq $y;
}
This way we would be closer to JS's meaning of ===
which is (I think) checks whether the two operands are identical.
Benefits:
if ($x === $y)
if either operand is undef
.$x === $y
is true if both are undef.{} === "HASH(0x562c769ce470)"
will never return true. Safety.undef === ''
, undef === 0
, and '' === 0
will return true.A drawback I see is that ===
will return true if two numbers have the same text representation but differ only by a tiny amount, whereas ==
wouldn't make that mistake. This is demonstrated in the following example:
my $x = 0.1 + 0.2; # = 0.30000000000000005, but stringifies to 0.3
my $y = 0.3; # = 0.3
say int(eqq($x, $y)); # 1
say int($x == $y); # 0
But maybe that could be solved if we had a separate eqq
infix operator that would check for string equality at the end (like the above example), and a ===
operator to check for numeric equality at the end of the 4th line of the function's body.
I mean something like this:
sub === ($x, $y) {
return !defined $y unless defined $x;
return !!0 unless defined $y;
return !!0 unless ref $x eq ref $y;
return length(ref $x) ? refaddr $x == refaddr $y : $x == $y;
}
I think it's a terrible idea to introduce an ===
operator that does something fundamentally different from what it does in other languages, and it's emphatically impossible to make it do the same without a type system.
@akarelas : Please add for 4
the case: '' === 0
will return false. Also may you please provide an example of drawback
@Leont What fundamentally different? It is like JS: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality
If the operands are of different types, return false.
If both operands are objects, return true only if they refer to the same object.
If both operands are null or both operands are undefined, return true.
If either operand is NaN, return false.
Otherwise, compare the two operand's values:
Numbers must have the same numeric values. +0 and -0 are considered to be the same value.
Strings must have the same characters in the same order.
Booleans must be both true or both false.
Perl have next types: string/number, HASH, ARRAY, GLOB. It will be very helpful if this operator will be implemented only for these.
Perl if fundamentally different from other languages: it has no type system. So it will be Ok if ===
will lack functionality for types also as whole perl does.
Language popularity is not based on that one language do same as another. Popularity is based on usefulness of language. Personally I like Perl because it has not type system
Here perl get more benefit if we compare values inside hash/array one level deep ( ===*
all levels, ===*3
3 level) . To compare addresses we can do usual:
$x == $y
this would be useless if ===
will do same comparison
Please add for
4
the case:'' === 0
will return false. Also may you please provide an example of drawback
Done (see my edited message above). The example I provided is not a big drawback, since you'd like 0.1 + 0.2
to equal 0.3
anyway. I can't think of a better example at the moment, sorry.
What fundamentally different?
What do you do when one operant is "1"
and the other is 1
? (note that neither is unambiguously marked as string or number)
What fundamentally different?
What do you do when one operant is
"1"
and the other is1
? (note that neither is unambiguously marked as string or number)
It's also unclear to me how this would work with overloading.
For example, given a hypothetical $overloaded
object that normally behaves as if it is the number 1
:
$result = 1 + $overloaded;
- $result contains the value 2
if (defined $overloaded)
- this conditional is trueif ($overloaded == 1)
- this conditional is trueif ($overloaded != 1)
- this conditional is falseif($overloaded === 1)
- this conditional is false using @akarelas' suggested definition, because ref $x eq ref $y
is not true.Whilst the last result might make sense for users who do care about types, it seems inconsistent with the existing operators and would not help users who do not care about the underlying type details.
'1' === 1
will result to true because values are same.
'1.000' === 1
will result to true, because both mean same value
Same for overloaded: despite on how it is located at memory it means value 1
so comparison should return true:
$overloaded === 1
-- true
===
in compare to ==
should compare values.
Perl is type less so here we should not care about types for ===
. Just compare values.
{} === {}
-- true
[] === []
-- true
{ a => 1, b => 2 } === { a => 1, b => 2 }
-- true
[ 0, 3, 7 ] === [ 0, 3, 7 ]
-- true
[ 0, 3, 7 ] === [ 0, 7, 3 ]
-- false ( 7 and 3 are swapped )
"" === 0
-- false
undef === 0
-- false
undef === ""
-- false
undef === undef
-- true
'0' === 0
-- true
"" === ""
-- true
Or, probably, use same
operator instead of ===
. Just like PostgreSQL implements IS NOT DISTINCT FROM
operator. (Here I mean usage of letters instead of symbols. Now I remembered perls: cmp
, eq
)
=> select '{"a":2,"b":1}'::jsonb is not distinct from '{"b":1,"a":2}'::jsonb;
?column?
----------
t
(1 row)
The same
operator is not obligated by other languages ;-)
'1' === 1 will result to true because values are same.
Then what about '1.000' === 1
(they are ==
but not eq
)
@Leont I have updated last my post.
In my example:
sub eqq ($x, $y) {
return !defined $y unless defined $x;
return !!0 unless defined $y;
return !!0 unless ref $x eq ref $y;
return length(ref $x) ? refaddr $x == refaddr $y : $x eq $y;
}
...maybe we could replace the last eq
with an ==
only in the case where both $x
and $y
scalars both have a numeric component. Otherwise do eq
like above.
I found only this article: http://www.dlugosz.com/Perl6/web/eqv.html
Describe the solution you'd like Perl comparison is great and save more typing, but when we want specifically compare something with
0
then we should type more, even more:Would be nice to just: $v === 0
At the article was mentioned that
===
is used to compare addresses. For this we can do derefference:so it should not be clash with
===
What do you think about new operator
===
?Thank you.