21 ms·
I was recently asked to add some trivial code to the end of an existing unmaintained Perl script written long ago. Something along the lines of $x = `cat FO
by amenbrother 12y ago
I was recently asked to add some trivial code to the end of an existing unmaintained Perl script written long ago. Something along the lines of
$x = `cat FOO 2>/dev/null`;
if ($x == "foo") {
system("BAR");
}
When I tested it I found BAR was executed no matter what FOO contained without any errors or warnings. WTF? After a little more searching I found the problem was that I should have written
$x = `cat FOO 2>/dev/null`;
if ($x eq "foo") {
system("BAR");
}
I have absolutely no patience for this kind of crap, but I don't have time to replace the whole thing right now so I just suck it up and move on. I can understand how Perl may never die completely but I'm never going to use it for anything new.
- shadowfox 12y agoThis sort of distinction exists in other languages though: Java has == and equals. OCaml has = and == etc. (Not that Perl doesn't have its issues; but this is very low in that list imho)
- TheMiller 12y agoAhd in Common Lisp, EQ, EQL, EQUAL, and EQUALP. See http://www.nhplace.com/kent/PS/EQUAL.html http://www.nhplace.com/kent/PS/EQUAL.html for an explanation of why.
- sillysaurus3 12y agoMistakes from other languages are still mistakes. One could try to call them tradeoffs rather than mistakes, but then you'd have to explain why the programmer benefits from such circuitous thinking.
- pcwalton 12y agoI don't think that one is a mistake. At least, if it's a mistake, it's not a mistake in the equals operator. PHP attempted to use one set of comparison operators and the fallout has been far worse: there have been security problems due to the semantics of PHP's == operator attempting to guess whether to perform string or numeric comparison when doing password comparisons. The mistake, if any, is that numbers and strings are unified into one scalar type in Perl. This allows some tricks, such as being able to use sprintf to perform rounding, but it has fallout in other places in the language, such as here. Given that numbers and strings are unified, having two operators for comparison is the correct decision: it makes the semantics much simpler by having the language not guess which kind of comparison to perform.
- TheMiller 12y agoThey're not mistakes; read the article. "Equality" is not the singular, unambiguous concept that many programmers think it is.
- tobinfricke 12y agoBut in those languages, the equivalent to ($x == "foo") will return false (almost) all of the time. The poster here says that this expression is true (almost) all of the time in Perl. Why?
- kamaal 12y agoBut what is $x? Integer? String? Character? Some_Object? How do you evaluate this, depends on the context. Wasn't that the whole point of a dynamic language anyway?
- CatMtKing 12y agoAfter learning Haskell, I'm not sure what the benefits of dynamic typing are anymore.
- keypusher 12y agoNo, not at all. Type coercion is orthogonal to type safety.
- AlexanderDhoore 12y agoAmen, brother! I call this "weak typing". But some others use weak typing to mean different things (like "unsafe typing") [1]. Javascript, PHP and Perl are weakly typed. Smalltalk, Lisp, Python, Ruby... are strong typed. But all of them are dynamic. [1] http://en.wikipedia.org/wiki/Strong_and_weak_typing#Predictability http://en.wikipedia.org/wiki/Strong_and_weak_typing#Predicta...
- girvo 12y agoI love dynamic languages with strong typing. You get most of the dev time developments, but without the inherent subtle bugs that creep in via automatic type coercion.
- mst 12y agoBecause if you disable warnings, it silently coerces 'foo' to 0. This is why disciplined (i.e. non-tiny-script-y) perl code starts off with use strict; use warnings; just like disciplined javascript starts off with /* use strict */ and disciplined C code enables compiler warnings, and truly disciplined C code makes those fatal, just like in perl you can do use warnings FATAL => 'all'; If you don't do that, then you get the short script/one liner style behaviour where, just like sed, awk or bash, it assumes you know what you're doing. If you don't, then you should be asking the VM to help tell you when those problems exist, same as 'set -x' in bash is incredibly useful if you don't plan to add '|| exit 255;' onto the end of every command.
- amenbrother 12y agoThose languages are far more maintainable and their communities have far more respect for practices which prevent programming errors. I don't particularly care how many forms of equality or comparison a language has as long as the compiler or runtime is capable of telling me the particular one I'm using is probably wrong. If == can't be used with strings the damn interpreter should tell me so instead of silently and improperly coercing the arguments.
- cubancigar11 12y agoYou should have used strict and warnings. RTFM, I know. Btw, Java will silently compare references instead of value. Learning a language != increasing vocabulary.
- mercurial 12y agoTell me about it. At least Python can make the difference between equality and identity, while a non-overriden equals() in Java actually means "is X Y?" instead of "is X equal to Y?".
- aphexairlines 12y agoThe interpreter does tell you. $ perl -e 'use warnings; use strict; print "content" == "foo", "\n"' Argument "foo" isn't numeric in numeric eq (==) at -e line 1. Argument "content" isn't numeric in numeric eq (==) at -e line 1. 1
- amenbrother 12y agoThanks - I'll try to remember that if I ever have to touch perl again.
- Someone 12y agoThat is not what perl and bash do. They distinguish between "comparing as strings" and "comparing as numbers". For example, the strings "03" and "3" are different, but as numbers, they are equal (and, I guess "010" is equal to "8", numerically. I didn't try, because I don't want to know) For bash, read http://unix.stackexchange.com/questions/16109/bash-double-equals-vs-eq http://unix.stackexchange.com/questions/16109/bash-double-eq... (especially http://unix.stackexchange.com/a/120235 http://unix.stackexchange.com/a/120235) and weep. For perl, see for example http://www.perlmonks.org/?node_id=276023 http://www.perlmonks.org/?node_id=276023
- mst 12y agoI guess you've never written any bash either, wherein the exact same problem exists except that == and eq are the other way around, for reasons I can't quite remember. Plus, of course, if you'd enabled perl's warnings system, via 'use warnings;', it would have complained at the use of == on a non-numeric value. If you don't enable the compiler features that catch problems, then, yes, you can run into problems. Welcome to programming. Edited to add: I got downvoted within five minutes. If you disagree that my bash analogy is inaccurate, I'd love to hear why.
- scrollaway 12y agoI did not downvote you, but comparing a language to Bash is certainly in no way flattering, and I would definitely not put it in the "good defense analogy" category.
- mst 12y agoComparing a final conditional in a systems-style script that is then calling another program, shell-style, to bash, which is the most common language where you'd execute a conditional then call another program, seems reasonable. Maybe not flattering, maybe not a good defense, but I think under the circumstances an acceptable comparison.
- amenbrother 12y agoThanks for the 'use warnings;' suggestion. Keep in mind the subject here is maintainence - where small changes with minimal impact to production is the rule and the work is often done by programmers with incomplete knowledge and no patience for explanations. For maintenance you want KISS, not TMTOWTDI. I'm no big fan of bash but at least bash gets the common case right here without any special settings. For example, if I use -eq instead of == and write #!/bin/bash x=`cat FOO 2>/dev/null` if [ $x -eq 'bar' ]; then echo baz fi as you imply, bash won't be silent. It will say bash-3.2$ ./example.sh ./example.sh: line 3: [: bar: integer expression expected
- 12y ago