Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Yeah, I've got a Perl codebase that's conservatively tens of thousands of lines, and it's honestly a struggle to write anything in it that isn't a big ball of mud. There's about 50 different ways to do anything in the language, the syntax is infuriatingly obtuse, and you can't rely on any documentation because it will recommend doing things that experts don't recommend doing.

The system is from like 2013 and still going, but I really wish I could rewrite it in a language I can actually train people on in a reasonable amount of time. It took the one junior I have about 6 months to get to the point where he could read the syntax without tearing his hair out. It's not really built to create maintainable structures.

The libraries and stuff are full of opinionated little "gotchas." As an example, the Test::Simple module will throw errors if you use a number to title a test which is infuriating when you're writing a test which tests all the numbers in the space of acceptable or possible inputs.



Perl's syntax is really confusing.

Especially for example how variables have symbols for different types ($ for scalars, % for hashes, @ for arrays). And if you want to for example pass an array to a function you have to send it manually referenced with like method(\@myArray) which then inside the method is contained in a $scalar.

Compared to Python for example where you'd literally just pass the array to the method like method(array).


For many years Perl subroutines didn't even have method signatures so you had to unroll @ on the first line of every sub. I think even today it may still be considered experimental. Jeez!


The reason for the @_ is that it is a simple way to get both pass by value and pass by reference semantics.

The values in @_ are aliased to the values in the subroutine call.

Most of the time, you want pass by value semantics, so you unpack the array and copy the values into function variables. If you want to modify an argument, it's typically passed in as a reference, and you can mess with it that way.

However, there are times when it would be horribly inefficient to make those copies, or when you need to do some magic (generally best avoided in 99.999% of your code), that this makes possible.

Also, since Perl functions are always variadic, it means that it's easy to work with a variable list of arguments in a function. For example, if you are expecting a list of key value pairs for your function, you can simply write:

  my %args = @_
Making signatures default will be a big improvement, but the power of the simple abstraction @_ provides should not be underestimated. It's actually an elegant solution to a complex problem.


Yeah it's pretty archaic. Shortest hand way of doing it is like this:

  sub method {
    my ($self, $a, $b, $c) = @_;
  }
$self being a reference to the current module (ala Javascript's 'this')


$self is only for OOP so not needed in a regular subroutine.


> Compared to Python for example where you'd literally just pass the array to the method like method(array).

How does one tell Python to pass the contents of said array as distinct parameters to the function, instead of as a lone array parameter?

In Perl, that's the difference between foo(@bar) and foo(\@bar) or foo(1, 2, 3) vs foo([1, 2, 3]).


> How does one tell Python to pass the contents of said array as distinct parameters to the function, instead of as a lone array parameter?

With an asterisk: method(*array)


Right, which I sorta kinda get why coming from C - a *something is the thing pointed to by that something.

How is that more understandable than @ vs \@ without knowing the language? My guess is it isn't.


Python is "relatively" consistent about * and being used to expand or contract arrays and dicts, respectively.

   a, *, b = [1,2,3,4]
   def foo(*args):
   bar(*[1,2,3])
all do "what you'd expect" from the single concept that "* is sort of pattern-matchy for an array".

But the more important bit is just that you don't have to prefix variables with @ and $. Python is optimized for writing code that acts on variables, while perl is optimized for code that acts on strings. While strings are certainly a common data type, most code isn't modifying strings directly. So optimizing for that case doesn't make a lot of sense.


As someone who learned python first - the idea that `myfn(@xs)` would call `myfn(1,2,3)` is... unnerving. Implicitly splicing in arguments makes me wonder what other kind of syntactic oddities are going over my head in my code.


a = [1]

def f(b):

   print(b)
f(a)

f(*a)


I can say the same thing about a legacy Java codebase that I had to work with at a big "enterprise" software company a few years ago. The code was so convoluted, with some files over 12k lines long. You can write spaghetti code in any language.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: