4 ms·
I don't understand the love for Perl. I wrote maybe 10k-20k lines of Perl between maybe 1996 and 2003 and at the time I was happy it worked. But ... more than
by tokyodude 8y ago
I don't understand the love for Perl. I wrote maybe 10k-20k lines of Perl between maybe 1996 and 2003 and at the time I was happy it worked.
But ... more than any other language I've used it seems the most hacked and confusing. Global variables abound. Crazy cryptic syntax. Ridiculous scoping rules with hacked on workarounds.
I really don't get the continued love. Sometime around 2003 IIRC I got introduced to Python and never looked back. When someone hands me a perl script I don't look forward to trying to get it to work.
Speaking of which tho even Python now makes me crazy. NPM might suck for various reasons but at least all deps are installed local to each project. I'm sure there are secret incantations for doing the same in perl and python but by default most stuff I download requires global libraries to be installed. If there is one thing I love about npm is that it defaults to project local installs and I have yet to run into a project that requires a global install
- Benjamin_Dobell 8y ago> I'm sure there are secret incantations for doing the same in perl and python but by default most stuff I download requires global libraries to be installed. I'm not a Python developer, just dabble, but I've had decent success with Pipenv[1] and Pipfiles. [1] https://github.com/pypa/pipenv https://github.com/pypa/pipenv
- nopacience 8y agoBest method to achieve that is one of 2 options: perlbrew local::lib Or, specify it when executing the module, ie: bash$ perl -I../project_modules/Module1/lib -I../project_modules/Module2/lib your_project.pl Or, specify it at the top of your_project.pl ie: use lib '../project_modules/Module1/lib'; use lib '../project_modules/Module2/lib'; Or, set enviroment var export PERL5LIB=/home/project_modules/ ; perl your_project.pl Or, make a BEGIN statement on top of your main project, ie: BEGIN { push @INC, glob "/home/project_modules/*/lib"; } You dont need to use anything global, and its better you dont. Never execute anything as root. You are able to execute local modules just like node, rvm, etc. Its all the same. Some linux installs come with perl/python installed. It is used by the system and is refered to as "system perl" or "system python" or "system ruby", etc.. and it is not recommended to make upgrade on those "system XXX". Only your system should upgrade the libraries it uses. That is why you should always use a local perl/python/ruby install. If you didnt like it, its good you moved on.
- petre 8y agoI use plenv instead of perlbrew. It's written in shell script and bugs are actually fixed in a timely manner.
- nine_k 8y agoOne thing to remember is to never install anything into system Python. It's for running system stuff, managed by OS's package manager. For any project, create a virtualenv. Write and maintain a requirements.txt file. It will save your day many times. It does not completely solve system-dependent problems, like TLS support (unless you run something like nix or guix).
- mst 8y agoYep, similarly local::lib and a cpanfile for perl5. (I prefer perl but this is a general principle and I agree)
- theonemind 8y agoI like perl for short throw-away programs, personally. It works really well for that. You can just hack away until it works and not think much about it. If you thought about it a little strangely, perl will probably support you to the end of your weird solution.
- Wwhite 8y agoYeah, not everything needs to be coded like you're showing it off on github. Not that you can't do some nifty stuff, elegantly, in Perl. Should you write your entire codebase in Perl, in 2018? hell no But you probably shouldn't be writing anything more than 10-20 lines in Bash, either, and this class of organically evolving script, with little attention to design at the start (much like the language itself) is where Perl really shines.
- isostatic 8y agoI always regret writing bash scripts, which start really simple, but tr require refactoring into perl after a few days. Only problem with perl I've run into is analysing text at speed - 60,000 lines a second of regex doesn't work on a raspberry pi or other low end processor.
- anthk 8y agoJust use awk.
- pcwalton 8y ago> Ridiculous scoping rules with hacked on workarounds. If you use "my", Perl's scoping rules are better than those of Python. It's a shame that Python and Ruby are a step backward from the proper (Scheme-like) lexical scoping of idiomatic Perl 5.
- yxhuvud 8y agoHmm, can you explain the difference?
- latk 8y agoPython's variables spring into existence at the moment of first assignment and are function-scoped (or module-scoped). The scope can also be terminated with the "del" statement. This has three problems: 1. The lifetime of a variable depends on control flow, and is not statically determined (in the general case). The exact scope is dynamic. 2. Many variables are not used throughout a function, but only within a small region of a function, e.g. an "else" block. Python's variables have a too large scope. To add confusion, a few Python constructs like "except" clauses or list comprehensions are block-scoped. 3. Working with nested functions is extra complicated. While you can read variables from outer scopes, you cannot assign them, unless you declare them as "nonlocal" or "global" in the nested function. As a special case of 3, consider closures that are declared within a loop: adders = [] for x in range(10): adders.append(lambda y: x + y) All these lambdas close over the same "x" variable which is reassigned. After the loop terminates, "x = 9" for all lambdas. Python's common workaround is to use an immediately invoked function that binds the value to a scoped argument. In lambda calculus terms, we have to desugar the "let" abstraction to function application: ... adders.append((lambda x_: lambda y: x_ + y)(x)) (Another alternative is to capture by value by using default arguments, as the defaults are executed at function definition time: "lambda y, x=x: x + y".) A similar language that shares Python's problems is PHP, where a nested function has to explicitly "use" outer variables it wants to capture. Perl (like most languages since Algol, Scheme, and C) requires explicit variable declaration (unless "use strict" is not enabled). In Perl, "my" declares a local/block-scoped variable. Consequences: 1. The lifetime of a variable is easy to determine statically: from the declaration to the end of the current scope (in Perl: to the next "}" that marks the end of the current block). This is called "lexical" scope. 2. I can restrict a variable to the smallest scope where it is needed, thus simplifying my code. 3. Nested functions are much easier. If I assign a variable, it uses existing (outer) bindings, unless I explicitly shadow the variable with a local declaration. If we return to the closures in loops problem, Perl creates a new variable for each loop iteration, thus avoiding Python's problems: my @adders; for my $x (0..9) { push @adders, sub ($y) { $x + $y }; }
- kbenson 8y ago> Global variables abound. There's a couple, but mostly just if you want to hack something, and usually there's another way to do it. They're useful for one-liners, but if you're doing it in production, you're usually doing it wrong. Sure, you can use them, just like you can do some stupendously bad things in most languages. Perl does give you more options for that, but the trade-off is that you can often do quick testing or one-off processing from the command line with one liners. E.g. Maybe you might run into $| (AKA $OUTPUT_AUTOFLUSH) or $/ (AKA $INPUT_RECORD_SEPARATOR) because those are useful and common. The rest are holdovers from awk. If you see them often in your code base, someone did you wrong. > Crazy cryptic syntax. I find it usually pretty straightforward, but that's how I write my Perl. The Perl I write these days is usually functions full of params with validation. E.g. use Function::Parameters qw(:strict); ... fun find_changesets_after( DateTime $last_processed, # No default, so required Maybe[DateTime] :$cutoff = undef, # :$ prefix denotes named variable Bool :$debug = 0, HashRef :$cache = {}, ) { # just use $last_processed, $cutoff, etc without instantiating them ... } # Called like so find_changesets_after( $last, cutoff=>$not_after, cache=>$CACHE ); That's a bit on the complex side, but it's a far cry from what I was writing 20 years ago, and in a good way. The language is marching forward, sometimes through code advancements, sometimes through best practices modules (Moose, etc). > Ridiculous scoping rules with hacked on workarounds. Err, what? The scoping rules are almost the same as C. There's some weirdness with $_, but don't go crazy with nested functions in maps and greps (and name your loop variables otherwise) and it's usually fine. > When someone hands me a perl script I don't look forward to trying to get it to work. Well, neither do I, because usually when I've been "handed a $LANG script" it's because it's problematic because it was written based on differing business requirements at a past time, or by by someone that was under extreme time constraints, or someone that didn't know what they were doing, or some combination thereof. So yeah, being handed a script can suck, just like being handed any codebase can suck. If you were being handed scripts that you are just expected to run and use but aren't working, it sounds like someone didn't include or define the dependencies. If they did, there should be no problem, since a vanishingly small number of things could cause a Perl script written in the last two decades to not work anymore. Backwards compatibility is taken very seriously. Based on the time period you're talking about, it sounds like you got handed a lot of hacked together CGI's and system scripts that were the glue for the beginning of the web. I feel for you, I got handed a lot of the same. Keep in mind a lot of it was written by Perl novices, extended by Perl novices, and then left to age ungracefully. Perl was everywhere in the late 90's, and a lot of beginning programmers were being thrust into tasks they didn't have a lot of experience for, so it makes sense that the average quality of a Perl program during this period would be very low. > NPM might suck for various reasons but at least all deps are installed local to each project. I'm sure there are secret incantations for doing the same in perl and python but by default most stuff I download requires global libraries to be installed. In Perl it's "cpan install $MODULENAME" or "cpanm $MODULENAME" (now) and it will download, compile (if required for bindings), test[1], and install all dependencies. Perl's had this done well for almost a couple decades too. For module authors, on uploading a module it's automatically spun out across a testing network and tested across a large matrix of Perl version, operating systems, and architectures, and the results are emailed to you (and visible online).[2] The cpan command was the appropriate way There are valid criticisms of Perl, but I you have to set the bar pretty high to find major faults in CPAN (at least compared to contemporaries). > If there is one thing I love about npm is that it defaults to project local installs and I have yet to run into a project that requires a global install I've not run into a global module install problem in Perl in... well ever. It's supported local modules fine since I first started using it in the late 1990's. If you're talking about interpreter installations, that use dto be much more painful (you had to actually install them and manage them manually), but since 2010 there's been perlbrew (inspired from the equivalent in Ruby or Python, I believe), which automates all this, allows multiple interpreters and libraries, etc. It sounds like that was past the time you were using the language, which is a shame, because it's really nice. I think you'd be very surprised at the average level of Perl code these days. Part of that is a community that's not getting a huge amount of new blood, so the people that are left are mostly veterans, but that has some benefits at least, as few as they are. 1: And fail if the module or a dependency's tests fail (unless you specifically force it), as is right. If a module can't pass it's tests, you sure as hell don't want it 6 levels deep in a dependency chain acting oddly. 2: http://matrix.cpantesters.org/?dist=Path-Tiny http://matrix.cpantesters.org/?dist=Path-Tiny
- mst 8y agoperl5's scoping with 'my' is proper lexical/block scope - same as javascript's new 'let' python's scoping is "invent a new variable in the current function when you mention the name" since I actually prefer explicit to implicit, I prefer perl5 to python scoping-wise
- tokyodude 8y agoI prefer no collisions to be the default. So foo = 12 No need to worry there's some global "foo" I overwrote (since it means knowing the entire program 10 lines or a million). That's actually one thing I think python got right over C/C++/C#/Java in that "foo=12" is always a local variable. It's never a member of the class. That's explicit as in "self.foo = 12". No ambiguity. JavaScript got that part right "this.foo = 12" but it got the other part wrong "foo=12" could be the global scope and there's no warning, just "you just crapped on the global namespace, good luck finding your bug" :( Fortunately modern tools like eslint catch that bug for me in JS
- mst 8y agoIn perl5 $foo is never a class member either. Also, you can use 'our' to restrict access to a global to a specific scope. Also, javascript now has 'use strict' (stolen from perl5) which prevents that problem there too. I fear you have been misinformed about both languages.
- tokyodude 8y agoThe problem with both is it's not the default. I shouldn't have to know some special syntax that makes my code safe (having to put $ in front or use `var` or `let`. It should be hard to mess up, not hard to not mess up. You can see the progression of perl from bad to tacked on workarounds. First "local" was added to manually copy values to some stack. Then "my" was added. But all the old problems are still there. Then there's all the massive mess of $foo vs %foo vs @foo vs &foo. That's super cryptic and leads to really hard to parse code (IMO obviously). And all the ridiculous cryptic globals https://www.perlmonks.org/?node_id=353259 https://www.perlmonks.org/?node_id=353259 No thank you
- SmirkingRevenge 8y ago> NPM might suck for various reasons but at least all deps are installed local to each project. I'm sure there are secret incantations for doing the same in perl and python but by default most stuff I download requires global libraries to be installed No magic required in Python at all for this. Just use virtualenv from your project directory (don't bother with vitrualenvwrapper). $ virtualenv venv; . ./venv/bin/activate
- tokyodude 8y agoIMO it *is" magic because it's not the default. with npm I have to go through special effort to get anything to install globally. With both python and perl I've read countless books and websites over the last 20 years and never once ran into that incantation. They all just say type install Chocolate::Belgian or cpan Chocolate::Belgian or python -m pip install SomePackage etc..
- tech2 8y agoLikewise don't bother with `activate`, just use the tools from the virtualenv directly `venv/bin/pip`, `venv/bin/python` etc.
- emilper 8y ago"Global variables abound." Must have been Perl 3 or 4. In Perl 5 you have to work extra to make global variables, and they're not really pushed in the global scope, only have global visibility in their own namespace ... unless you work even more and export them by default when you write the module they're in.
- tokyodude 8y agoHmmm https://www.perlmonks.org/?node_id=353259 https://www.perlmonks.org/?node_id=353259
- zbentley 8y ago> Ridiculous scoping rules That's fair, but Python definitely causes its share of confusion there as well. If anything, Perl's scoping (in modern perl5 with warnings and strict) is one of the nicest I've had the pleasure of working with in a scripting language: closures Just Work (tm), and having the choice of dynamic scopes when you need them is quite powerful.
- marlencrabapple 8y agoI think carton and plenv can do just that, but it seems from the comments that there are other just as popular solutions too.