Posts filed under ‘python’
Blocks != Functional Programming
Joel Spolsky is one of my heroes. He has a vast amount of insightful articles that rank among the clearest and most relevant software writing today, and his blog gets more hits in a day than mine ever will. (Speaking of which, I hit 2000 visitors yesterday – around 10x more than I ever thought I’d get.) He’s a very smart cookie, and when he speaks, people listen. But last week, while browsing the top Reddit articles of all time, I was surprised to see his article Can Your Programming Language Do This? at #4. While it’s a good primer on Javascript abstraction, I don’t think it deserves as many points as it recieved. I spent the next few days thinking about why this article bothered me so much – Joel certainly didn’t say anything untrue, attack any favorite language of mine, or make some outlandish claim. But then I realized that Joel’s article fit together in a pattern of recent articles, all of which bothered me slightly.
Here’s what I realized: it seems that every language under the sun is being evangelized as an excellent functional programming language simply because it supports a few paradigms from FP.
Or, restated: Anonymous functions do not a functional language make.
The most egregious example of a pundit claiming a language is functional when it’s clearly not is Eric Kidd’s well-known Why Ruby is an acceptable Lisp. Kidd tells us explicitly that Ruby is a denser functional language than Lisp – and I’ll be the first one to admit that if I were to debate the “denser” part of that sentence, I wouldn’t know what I was talking about.
But Ruby is not functional – Wikipedia calls it a reflective, object-oriented programming language, and I agree with them. Yes, you can have block arguments to methods, continuations, generators, reflection, and metaprogramming – but it isn’t functional, for two reasons.
1. It’s hard to carry around functions as objects.
I really don’t know why Ruby hates parentheses so much – it’s probably part of its Perl heritage. In Ruby, you can call methods without sticking superfluous parentheses in there – take a look at this Python code:
" I'll write about Cocoa soon; disaster struck the app I was writing ".strip().lower().split()
Now take a look at the equivalent Ruby code:
" Apple's releasing a tool with XCode 3 which completely supersedes my Cocoa app - so I'm very depressed right now ".strip.downcase.split
Though you could put parentheses in front of strip, downcase, and split, Ruby will work just fine without them. Now, this feature makes for far fewer parentheses, thereby making code significantly more readable. But what if I want a previously-declared function as an argument? If I type in the name, Ruby will just evaluate the function. Sure, I could use the kludge that is Symbol.to_proc, but that’s ugly – and it wraps the function inside a Proc object, which has to be called with the call(*args) method. And that’s just ugly. In Python, all you need to do is type the function’s name to use it as an object, and append a pair of parentheses if you need to call it.
2. Variables are.
A purely functional language only has immutable variables. Ruby doesn’t. (Yes, I know LISP isn’t purely functional. But it adheres to so many other FP paradigms that we can overlook that.)
But I’m getting distracted, so I’ll cut the above point short.
Anyway, what I wanted to say was this – just because your pet language has support for anonymous functions/closures doesn’t make it a functional language. Sure, Python has lambda and list comprehensions (which are taken from Haskell, a purely functional language) – but it’s not functional, it’s object-oriented. Yes, Ruby has blocks (even if you do have to wrap them in Procs), but it’s not functional. Javascript may have support for anonymous functions, but its syntax can be traced back to Algol and the birth of imperative programming language. Hell, even Objective-C has blocks if you include the F-Script framework, and it’s the farthest thing from functional there is.
In conclusion, don’t say your language is a functional one just because you borrowed a few ideas from Lisp. If you want a real functional language, try OCaml, Haskell, ML, or Scheme. Calling imperative/OOP languages functional just makes the term meaningless.
How to Beat Rails
(Note: I really, really like Ruby and Rails. Anything disparaging that I say about either of them should be taken with several grains of salt. If I seem to be encouraging Pythoneers to crush Rails, it’s simply because I love both, and want all frameworks to be constantly innovating.)
Everybody with the slightest interest in web development has heard of Ruby on Rails. It thrust Ruby into the spotlight, created a hype machine that stubbornly refuses to go away, and made David Heinemeier Hansson a celebrity. I adore Rails – it’s by far the best web framework for simple CRUD apps. However, as a Python devotee, it hurt me deeply to see Ruby stealing the spotlight. As such, I embarked on a quest to find out why Rails is winning; I looked at Django, Turbogears, Pylons and web.py. After months of building the same simple CRUD app, I came to the following conclusion:
Python can beat Rails. It can grind it into a pulp in every way concievable – speed, elegance, coolness, extensiblity, organization, AJAXness, beauty, and flexibility. It can send Rails crying home to David while Guido basks in the Web 2.0 spotlight. But right now, Rails is thoroughly torching all of the Python web frameworks. The following is a list of recommendations that, if applied to a Python framework, could dislodge Rails from the position of King of the Web Frameworks.
Worse is Better: Python templating systems vs. Rails ERb
(Disclaimer: Python is my favorite programming language; however, I do criticize it in this article. Please redirect flames to /dev/null.)
I’ve been comparing web frameworks lately, developing a relatively simple CRUD database-backed application that can support a few bells and whistles. I’ve checked out Ruby on Rails (who hasn’t?) Django, and Turbogears in my search, and realized something as I was hacking together some templates in Kid:
Python, a far more restrictive and inflexible language – one that would seem, on the surface, to be worse for web application development than Ruby – is better for programmers, designers and security by nature of its inflexibility.
Let me explain what I mean. When designing ‘views’ – the web pages that users will see – that need to be updated with data from a given database, it is natural to break the Model-View-Controller paradigm and embed some controller logic into the application. After all, it’s so much less effort to embed
<% found_books = Book.find_all(“title = ?”, given_title) %>
into your .rhtml files then to go back into the controller file, change the return types, and make sure everything works correctly. However, Python is whitespace-sensitive, and therefore is much more difficult to embed into HTML. As such, you can’t write the mixture of Ruby and HTML that makes Rails so easy to use.
This is a good thing. I am a strong advocate of separating the model, view, and controller; by the very fact that I can’t write a combination of Python and HTML, I am forced to go back into the CherryPy/Django controller codebase and write a properly formed, secure, and elegant SQL query. Normally laxity wouldn’t bother me, but I believe that any large web application will grow into a hideous, Nylartothepic tangle if the MVC rules are not followed to the letter.
I still love Rails, but I love the templating systems in Python even more. Because Python is so restrictive, people had to write templating systems the Right Way – and that’s a good thing for everybody.
Adventures in Pythonic Encapsulation
Python has undergone a fair share of criticism for its lack of support for information hiding. Despite its being a solidly object-oriented language, Python has historically refused to support this facet of object-orientation. Other programming languages have implemented encapsulation in a variety of ways:
- All variables in Smalltalk, the canonical OO language, are private; in order to access them, the programmer must write explicit accessor and mutator methods for each variable.
- C++, Java, and C# rely on the
public,private, andprotectedkeywords in order to implement variable scoping and encapsulation. - Cocoa’s Objective-C code strongly encourages the programmer to use key-value coding for encapsulatory purposes.
- Ruby does ultra-sexy encapsulation through the
attr_accessorfunction(s).
However, Pythonistas like myself often assert that “we’re all consenting adults here.” While this attitude is refreshing in this day of slavish devotion to OOP principles, the Python community has realized that in order to avoid alienating newcomers, Python should perform some sort of encapsulatory behavior. This article intends to show the various ways in which Python supports encapsulation and/or information hiding.