On Thu, 26 Nov 2015 12:23 pm, BartC wrote: > On 26/11/2015 00:31, Steven D'Aprano wrote:
>> In 2015, it's hard to think of any non-obsolete, non-toy language which >> doesn't treat functions as first-class values, including creating them on >> the fly. Fortran and C perhaps. > > It's funny then that the vast majority of top-level function definitions > I see in Python (and import and class statements too) are decidedly > static. I can't be held responsible for what code you see. It is probably true that many, maybe even a majority, of top-level functions, and methods, are static. So what? That's not the point. The point is that *more than that is possible*, so when you need the power, you have it. Any time you see a function decorator: @decorate def function(arg): ... you're probably seeing a dynamically-generated function. The typical decorator idiom looks like this: def decorate(function): @functools.wraps(function) def inner(arg): do stuff call the original function return the result return inner Lo and behold, the simple @decorate idiom usually hides a function created on the fly. (That would be the inner function, which is called a closure.) Any time you see a function factory, chances are good that it involves dynamic generation of function objects. Any time you see lambda, you are definitely seeing the dynamic generation of function objects. If you do any sort of programming involving callbacks (for example, some GUI toolkits, like Tkinter, make extensive use of callbacks) you probably will use lambda a lot. The equivalent to lambda, code blocks, is even more powerful in Ruby, and Ruby programmers use code blocks *a lot*. So much so that I know at least one Ruby programmer who considers Python almost unusably primitive and crippled because it lacks code blocks. You really should read Paul Graham's essay, "Beating the Averages", and understand the Blub Paradox. (It's not really a paradox.) It might open your eyes. [quote] As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub. [end quote] http://www.paulgraham.com/avg.html We're all Blub programmers. But some of us are aware that we're Blub programmers, and when we see "weird languages" with "hairy stuff", we don't immediately dismiss the possibility that maybe that stuff is powerful and useful, just because we've never found a use for it. > The names are declared, but the names are rarely bound to anything else. > Functions are just called the same boring way they are in C. > > /They might as well be static definitions/. Sure. And that's probably true for, oh, I don't know, I'll be generous, and say that 95% of Python functions in use are of a straight-forward pseudo-static form, using no dynamic features. But it's the other 5% -- one in twenty -- that *shine*. They're the ones that do things that you can't do in Pascal or C except with the greatest of difficulty. Back when I was an undergrad at uni, I did a course on computational mathematics. At the time, Pascal was the language of choice at my uni, and when it came to solving ODEs (Ordinary Differential Equations) we used a package of Pascal programs to do so. Because Pascal doesn't have first-class functions, you couldn't pass a function as an argument to another function. So the ODE solvers used a hard-coded function as the equation to be solved. So if you wanted to solve a particular equation, you had to *edit the source code of the program*, modifying that hard-coded function to match your equation, then re-compile, and then run the code. You couldn't just type in the equation you wanted to solve and run the code. Of course Pascal is Turing Complete, and the solver could have been written to work that way. It just would have been much, much, much harder. Something that in a language like Python you can do almost without thinking: function(another_function, x, y, z) would have required hundreds, perhaps thousands or tens of thousands of lines to do in standard Pascal. You would have had to build up all this infrastructure for dealing with functions that Python gives you for free. There's a lot to like about Pascal, but gosh it sure is lacking in power. C at least has function pointers, which is a step up from Pascal, but still pretty weak and feeble. If functions are first class values in Python, Ruby, Lisp and others, they're second class values in C and third class in Pascal. -- Steven -- https://mail.python.org/mailman/listinfo/python-list