Origin of frustrated perl idioms: & x (...) and sub x ($$) {...}

In my perl code, which I used earlier, the following two writing styles, which I found later, are discouraged in modern perl:

# Style #1: Using & before calling a user-defined subroutine &name_of_subroutine($something, $something_else); # Style #2: Using ($$) to show the number of arguments in a user-defined sub sub name_of_subroutine($$) { # the body of a subroutine taking two arguments. } 

Since we do not recommend that these styles be not recommended, I simply stopped using them.

However, out of curiosity, I would like to know the following:

  • What is the origin of these two writing styles? (I'm sure I havenโ€™t come up with my own styles.)
  • Why are these two writing styles disappointed in modern perl?
  • At one point in time, were styles considered the best?
+4
source share
3 answers

Sigil & is not commonly used with function calls in modern Perl for two reasons. Firstly, this is pretty much redundant, as Perl will look at everything that looks like a function (followed by parens). Secondly, there is a big difference between the way &function() and &function are executed, which may confuse less experienced Perl programmers. In the first case, the function is called without arguments. In the second case, the function is called with the current @_ (and can even make changes to the list of arguments, which will be visible by later operations in this area:

 sub print_and_remove_first_arg {print 'first arg: ', shift, "\n"} sub test { &print_and_remove_first_arg; print "remaining args: @_\n"; } test 1, 2, 3; 

prints

 first arg: 1 remaining args: 2 3 

Thus, ultimately, using & for each function call ends up hiding several calls to &function; , which can lead to difficulty finding errors. In addition, using a cigar & prevents prototyping of functions that may be useful in some cases (if you know what you are doing), but can also lead to complex error tracking. Ultimately, & is a powerful behavior modifier and should only be used when it is needed.

Prototypes are similar, and their use should be limited in modern Perl. What should be stated explicitly is that prototypes in Perl are not function signatures. They are hints for the compiler that tell it to parse calls to these functions in a similar way to built-in functions. That is, each of the characters in the prototype tells the compiler to impose this type of context on the argument. This function can be very useful when defining functions that behave like map or push or keys , which all handle their first argument differently from the standard list operator.

 sub my_map (&@) {...} # first arg is either a block or explicit code reference my @ret = my_map {some_function($_)} 1 .. 10; 

The reason sub ($$) {...} and similar prototypes are discouraged is because 9 times out of 10 the author means "I want two arguments" and not "I want two arguments each with a scalar context overlaid on the site call. " The first statement is better written:

 use Carp; sub needs2 { @_ == 2 or croak 'needs2 takes 2 arguments'; ... } 

which will then allow you to use the following call style as expected:

 my @array = (2, 4); needs2 @array; 

To summarize, sigil and function & prototypes are useful and powerful tools, but they should only be used when this functionality is required. Excessive use (or misuse as an argument) leads to inadvertent behavior and makes it difficult to track errors.

+15
source

There were mandatory and functional challenges in Perl 4, so you might have chosen this from the perl (1991) programming of Larry Wall and Randal L. Schwartz, like me, or something like that.

As for function prototyping, my hunch is less qualified. Perhaps you have manipulated languages โ€‹โ€‹where it makes sense and / or is required to declare argument lists, and since function prototypes in Perl look a bit like argument lists, did you start adding them?

Function

& is not recommended because it makes the code less readable and unnecessary (cases where a function is needed are rare and often better avoided).

Function prototypes are not argument lists, so most of the time they simply confuse your reader or lull you with a false sense of hardness, so you donโ€™t need to use them unless you know exactly why you are.

& was mandatory in Perl 4, so they were the best / necessary practice. I don't think there have ever been prototypes of functions.

+3
source

For style # 1 and before a subroutine is needed, only if you have a subroutine that has a name with a built-in name, and you need to eliminate which one you want to call so that the interpreter knows what is happening. Otherwise, this is equivalent to calling a subroutine without &.

In this case, I would say that its use is not recommended, since you should not name your routines with the same names as the built-in ones, and it is recommended that you use all your routines before calling them, for the sake of reading comprehension. In addition to this, if you define your routines before calling them, you can omit parentheses, for example, built-in ones. In addition, simply speaking visually, sticking to and before each subroutine unnecessarily clutters the file.

Regarding function prototypes, they were stuck in Perl after the fact, and actually don't do what they did. From an article on perl.com:

For the most part, prototypes have more problems than they are worth. Firstly, Perl does not check prototypes for methods, because for this it will be necessary to determine at compile time the class that will process this method. Since you can change @ISA at runtime, you see the problem. The main reason, however, is that prototypes are not very smart. If you specify sub foo ($$$), you cannot pass an array of three scalars to it (this is a problem with vec ()). Instead, you should say foo ($ x [0], $ x [1], $ x [2]), and this is just a pain.

In the end, it is best to comment on your code to indicate what you intend to execute the subroutine, and to check the parameters yourself. As the article says, this is really necessary for class methods, since they do not perform parameter checking.

For what it's worth, Perl 6 adds formal parameter lists to the following language:

 sub do_something(Str $thing, Int $other) { ... } 
+1
source

Source: https://habr.com/ru/post/1309913/


All Articles