in reply to Re^6: Some thoughts around the "is Perl code maintainable" discussion
in thread Some thoughts around the "is Perl code maintainable" discussion

If 'cool' is too subjective, transient, and divisive; then feel free to substitute 'fun' in my original sentence, but you might loose that sense of novices looking on at what the masters do and wanting to emulate them.

Maintainance is enhanced by composability and the reduction of special cases - things that can be affected by language syntax.

I'm glad you brought up the IC design example, it enhances my argument. There are many ways to design your own transistor, AND gate, or flip-flop, but the digital designer is NOT given the choice. there are very few types of basic gates at his disposal and through the base uniformity, tested methods of (de/)composition, testing, and training in manufacturability, the designer is freed to make such advances.
On the quote by Brian W. Kernighan, It is about debugging which can be a part of maintenance and writing clever code. I mentioned some very clever coding practices above it. I still think its a fair quote. I am aware of the pitfalls of a poorly used quote back-firing but would rather modify what you said to "Mis-quoting smart people does not make one smart", which causes me to quote rarely :-)

I do not argue that assembler is more maintainable than C, and know that you never said that, it was part of one of your examples. I could however take the first sentence of your paragraph introducing the example to highlight some of our differences of opinion:

Perl's many idiomatic constructs allow the concise representation of a high level algorithm in an unnecessary number of sets of a few short statements.
Furthermore, this is seen as a good thing in the community. I think this goes against maintenance, as does "Do What I Mean" rather than "Do What I Say".


Here are two concrete Perl features that make it harder to maintain Perl programs, not un-maintainable, but definitely harder to maintain:
 * The explicit use of references.
 * The method of passing of arguments into subroutines.
You can't mandate against their use in a style-guide and they can be used so deceptively that they get through code reviews.

- Paddy.
  • Comment on Re^7: Some thoughts around the "is Perl code maintainable" discussion

Replies are listed 'Best First'.
Re^8: Some thoughts around the "is Perl code maintainable" discussion
by BrowserUk (Patriarch) on Aug 13, 2007 at 00:46 UTC

    Update: I couldn't find this last night, but as far as

    the concise representation of a high level algorithm in an unnecessary number of sets of a few short statements.

    goes, this beats any Perl example I've seen into a cocked hat.


    By "method of passing of arguments into subroutines.", I assume you mean 'by reference', making that essentially the same 'problem' as "The explicit use of references". Reading between the lines of your mentioning those, and "composability", I assume that you favour pure FP languages.

    So when you rail against Perl for these features, you are essentially railing against side-effectful languages. Ie. Every imperative language in existance along with a good number of FP languages, that allow call-by-reference and mutable variables. And yet, the vast majority of software in existance, and most new software being written, is being written in languages that allow both. This is an old argument and one that scopes well beyond Perl.

    As for DWIM -v- DWIS. Here is an example of Perl DWIMming:

    sub perms { return !@_ ? [] : map{ my $next = $_; map{ [ $_[ $next ], @$_ ] } perms( @_[ 0 .. $_-1, $_+1 .. $#_ ] ); } 0 .. $#_; } print @$_ for perms qw[ a b c ];; a b c a c b b a c b c a c a b c b a

    Take a careful look at that array slice: @_[ 0 .. $_-1, $_+1 .. $#_ ], and note that $_ takes the values 0 .. $#_. That means that in the first iteration of the slice, the indexes are 0 .. -1, +1 .. $#_. And at the other extreme it will be 0 .. $#_ -1, @_ .. $#_.

    When I first encountered Perl and started using the range operator (..), I was disappointed that it didn't work for descending ranges. Do you see how Perl is DWIMming there, and how, if it always DWIS, then I would have to explcitly code conditional checks to ensure that the slice didn't address out-of-bounds indices. Whilst not hugely difficult to do, adding those checks and tests to the routine above would destroy its simplicity and clarity, and obscure the algorithm. And this is just one example of DWIM, that greatly simplifies the concise and expressive coding of algorithms in Perl.

    Try a brute force conversion of the above to C and you'll understand how much complexity this well chosen 'irregularity' in Perl avoids. And Perl is full of these. Not that I agree with all the DWIMs, but then maybe I just haven't yet encountered the situations where they make sense.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      (It was nice to smile at that Haskel example again. I think there was a series of blogs doing similar in different languages :-)

      There is another thread: Practical example of "Is Perl code maintainable" that has some comments on implicit use of @_ versus explicit. It also has people who know that their code will need to be maintained, advocating not writing their code as 'cleverly' as they can, to ease maintenance, which was the reason I added a quote in an earlier post to this thread.

      - Paddy.
        It also has people who know that their code will need to be maintained, advocating not writing their code as 'cleverly' as they can, to ease maintenance, which was the reason I added a quote in an earlier post to this thread.

        Yes. As I tried to indicate earlier, there is nothing at all wrong with the quote. The controversy (from my perspective) is on its applicability to particular situations. For example in that other thread, it centres around the use of one of Perl's "features", namely implicit arguments. These are pervasive in Perl, and have, at points in time, been heralded as one of the features that makes Perl so productive and useful. At other times, certain schools of thought seek to deem this feature, in whole or in part, a mis-feature.

        Many of those same people would trounce all over anyone who wrote:

        I went to my doctor the other day because I had a problem with my leg. The doctor inspected my leg and the doctor told me that the problem with my leg was a strained muscle within my leg through incorrectly exercising my leg.

        Instead of

        I went to my doctor the other day because I had a problem with my leg. He told me that the problem was a strained muscle due to incorrectly exercising it.

        It's always dangerous for someone who can't write English to save their life, to use English as an analogy, but what the hey.

        No one would deem the use of implication within the second example as 'clever'. It is simply 'normal'. 5 years olds and younger learn to do this without effort or strain, or even special instruction.

        There are two implicit targets of shift. They exist in clearly defined and very obviously different contexts. One could argue that having two different defaults is 'dangerous' or 'confusing'. One could argue that it might have been better for @ARGV to have simply been @_ at the root level of package main;. Ie. equivalent to argv[] in a C program, @_ would simply be seen as the arguments to the main 'function' in the program, just as it is the arguments to all the other functions in the program. Pah! History.

        But given that history, and that it isn't going to change now, then there are 3 (+1) possible responses to the ambiguity:

        1. Do nothing. An unadorned shift does what ever it does according to its context.

          For many people this is an non-issue and this is their chosen response.

        2. Eschew the defaults feature (at least for this particular usage) and always explicitly state the target.

          In my view, overkill. It makes me wonder what's next.

        3. Decide that one default is enough and explicitly state the target in the other context.

          Two possibles:

          • Always state @_.
          • Always state @ARGV.

          If any response is necessary, and as someone who never recalls having found the two defaults confusing I don't, but if it is, then as @ARGV is the least used, elect that one to be explicitly stated.

          Actually, I think I have always done this anyway, without ever consciously making a decision to do so.

        Perl, by design, uses defaults and implicit parameters. You can argue whether that is a good design decision or not, but it is an integral part of the language philosophy. Deeming their use 'clever' does not seem appropriate to me. It's just using the language as it was designed.

        As features go, I find this feature far less confusing than some features of many other languages.

        Take Haskell's type diagrams as an example.

        The use of single character identifiers as placeholders for types, combined with reusing that same identifier to represent all different arguments and returns of the same type, in the type diagram for a given function (or chain of curried functions?). I did, and do, find this confusing in the extreme.

        Haskellers will say: you'll get used to them as your understanding of the language grows with use; and maybe it will.

        And so it is with Perl's implicit arguments. You just get used to them. And very quickly. Far more quickly in my experience than Haskell's type notations.

        And that leads to Haskell's almost universal use of single character variable names--albeit that 'variable' is probably the semantically the wrong term:). Yes, they are always locally scoped and it takes extreme effort to define a Haskell function that extends much beyond a handful of lines, but if I presented code here that used that many single character identifiers; and reused the same ones over and over; and used the same character for both actual and formal parameters; (not forgetting their reuse in the type notations!), then I would be hounded mercilessly.

        Then there is that 'the whole meaning of a function can be altered--silently--due to the incorrect usage of an invisible character' feature. That caught me out no end of times until I tweaked my editor to prevent it. Talk about a mis-feature. But take that argument to a Haskell forum and you'll be laughed out of court (mixed metaphor).

        Basically, judging parts of a languages design philosophy as 'clever', because they differ from those of your preferred language (an assumption), is ... long pause for thought ... let's just leave it as 'unproductive'.

        It is more debatable when the argument is made by those seriously well versed in the language. But it is still debatable.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.