The Perl guy in Python land: The joys of abstraction
From AJS.COM
- Part of the The Perl guy in Python land series of articles.
Abstraction is, of course, the primary function of any programming language. In the end, all that really matters to the computer is which machine instruction to execute next, but we use programming languages to abstract away those low-level details and present us with something that's both easier to use and much more compact. Perl was one of the initial wave of very abstract programming languages that attempted to preserve the C-style syntax. After it, other languages such as PHP, Python, and JavaScript continued to push down this road of using the C-style approach while expanding the abstraction. In some areas, Python has really taken this ball and run with it, and this can be one of Python's greatest strengths. For this reason, most of this article is praise for Python's abstraction, not really a comparison or migration history.
Typing
Python's typing is a slippery thing. In one sense, there is no typing at all, but in another sense, there are quite a few different types. int, str, object, callable, ... all of these are really more type annotations than they are types, but python uses them in both ways. What is novel is Python's interchangeability. You can attempt to "call" any variable:
x()
If x happens to have a value which is callable, then this is a function call. If not, then an error is raised. Here's a more complex example:
def somefunc(a,b,c): print a+b+c x=somefunc x(1,2,3)
x is just a variable like any other, but it contains a reference to the function, somefunc and that allows the use of function-call semantics. Essentially defining a function with def just defines a variable and places a function reference in that variable. Unlike Perl, there's nothing inherently special about function names. They're not in their own namespace, and can be treated just like any other variable. For comparison, let's look at the equivalent Perl:
sub somefunc {
my($a,$b,$c) = @_;
print $a+$b+$c, "\n";
}
$x=\&somefunc;
$x->(1,2,3);
Notice that the variable $x is just a variable and would never conflict with or be invoked in the same way as a function called x
Functions
When it comes to abstraction, I suppose I really need to touch on Perl's greatest weakness: the lack of formal subroutine parameters. In the above example, somefunc takes three arguments, but the parser cannot know this. Instead, the function itself manipulates the stack (@_) and stores the first three values in localized variables. In the Python example, the parameters are simply defined as part of the declaration of somefunc and that tells the parser how many arguments to expect. The parser can then issue errors when the wrong number of arguments is passed, something Perl programmers must do for themselves.
