Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
TheFluff
Dec 13, 2006

FRIENDS, LISTEN TO ME
I AM A SEAGULL
OF WEALTH AND TASTE

Hammerite posted:

This sounds extremely bad and needlessly confusing, and likely to be a huge source of bugs. It seems to me that it would be much better to have the user explicitly indicate what sort of behaviour they want than try to be clever and let them change the program's behaviour subtly through context. Can someone explain why I'm wrong?

You're not really wrong, but Perl's gimmick is preferring idiomatic shorthand convenience over almost everything else, and the differences are usually not subtle. There's very intentionally no consistency whatsoever in what the builtin functions that can return lists do in scalar context - the documentation uses the (in)famous phrasing "in general, they do what you want, unless you want consistency". localtime() returns a string representation instead of a C-like time struct if used in scalar context. map() - which is more like what many other languages would call flatMap since each input element can map to any number of output elements, and in fact even to zero elements - returns the number of elements of the resulting list rather than the list itself. Some of the file I/O functions like readline() and readdir() return the next entry and advances the filehandle pointer in scalar context, while using them in list context reads until EOF and returns a list of files/lines/whatever, so they're stateful in one context but not really in the other. splice() - which splices like an array like Array.splice() in JavaScript - returns the last element removed in scalar context, or undefined if no elements were removed. sort() in scalar context has undefined behavior.

In Perl's defense though it's usually not hard to see what the context is because of the sigils that prefix variables - scalars are prefixed with $, arrays with @. You declare the context with the sigil, like
Perl code:
@array = ('a', 'b', 'c');
$foo = @array; # foo now contains the value 3 (length of array)
@foo = @array; # foo now contains the array ('a', 'b', 'c')
If you balk at this little bit of subtlety though I'm sure you'd be delighted to know that Perl encourages the use of implicit arguments and variables. For example, if you have a list of hexadecimal numbers as strings and want to print them in decimal form, knowing that the builtin function hex() converts a hexadecimal string to a number, you might write
Perl code:
@numbers = ('0x10', '0x20', '0x30');
foreach (@numbers) {
  print(hex(), "\n");
}
If you're not familiar with Perl, you might be wondering where the iterator/loop variable is, and why there's no argument being passed to hex(). The answer is that if you don't explicitly declare a loop variable, you get a default one called $_ automatically, and most functions that only take one argument will let you omit that argument, operating on $_ instead if you do so. Except in some cases, of course - shift() (array shift, removes the first element from an array and returns it) defaults to shifting @_ (implicit list of arguments) inside of functions/subroutines, but not if used in the global scope - there it defaults to shifting @ARGV (the list of command line arguments to the program) instead.

Another example of this focus on idioms is the return values from low-level syscalls that return 0 or a positive integer on success but a negative value on failure. In languages with modern exceptions you'd write something like
code:
result = fcntl(...)
if (result < 0) {
  throw SomeError()
}
but in Perl, where you raise an exception by calling die(), the idiom is

Perl code:
my $flags = fcntl($filehandle, F_GETFL, 0)
    or die "Can't fcntl F_GETFL: $!";
Now, if fcntl() returned 0, you'd throw even though the call succeded because 0 is falsey, the or wouldn't shortcircuit and you'd reach the die() statement. So to fix that, fcntl() and a bunch of other syscalls return the string "0 but true" instead of just 0 - it's truthy in boolean context but implicitly converts to 0 in numeric context. Normally in Perl trying to use a string that starts with a valid numeric value but has other stuff after that as a number would work but cause a runtime warning, but the string "0 but true" is specifically exempt from this particular warning.

Perl is full of little weirdnesses like this and that's why it's fun. It's a very old language, which shows, and it has wildly different design goals from basically any language that's in common use today, but that's part of the charm. Unlike some of the more obnoxious languages like PHP or JavaScript that are full of weird and annoying issues because of historical mistakes, Perl isn't weird by accident - it was very intentionally designed to be weird.

It was the first language I learned back in the day and I have quite a bit of fondness for it. Wouldn't want to work with it, though.

TheFluff fucked around with this message at 17:41 on Jan 9, 2020

Adbot
ADBOT LOVES YOU

TheFluff
Dec 13, 2006

FRIENDS, LISTEN TO ME
I AM A SEAGULL
OF WEALTH AND TASTE
Man, writing that up made me remember how hilarious Perl is. Did you know that substr() can be used as the left hand side of an assignment?

Perl code:
    my $name = 'fred';
    substr($name, 4) = 'dy';         # $name is now 'freddy'
pyf perl trivia

TheFluff
Dec 13, 2006

FRIENDS, LISTEN TO ME
I AM A SEAGULL
OF WEALTH AND TASTE

Ape Fist posted:

Isn't Perl supposed to be, like, profound unpleasant to write?

Where did you get that idea? It's completely the opposite. Perl is loving hilarious to write, you'll sit there giggling to yourself about whatever cleverness you might've come up with. It can be really annoying to read though because there are so many ways to express the same thing and there are many subtleties hidden everywhere.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply