Ambieditrous
When you screw up your .emacs file, there is something delightfully perverted in having to type
vim ~/.emacs
in order to set things straight... :-)
When you screw up your .emacs file, there is something delightfully perverted in having to type
vim ~/.emacs
in order to set things straight... :-)
Nobody was fooled: The language I decided on for 2009 is Clojure.
(This in spite of its name, which is positively horrible, in my opinion. YMMV. Anyway, now that that is out of the way...)
Besides Nu and F#, there were many other, lesser candidates, not all of them functional or Lisp-like (the list included Io, Prolog and Perl (!), for example). After I investigated the top three, I figured I had found the language I wanted, and decided not to look any further.
Nu looks like a Lisp, but I don't think it's actually very Lispy or functional, which was a bit of a drawback. The fact that it's tied to OS X doesn't really bother me, since Macs are all I have at the moment anyway.
F# is of course tied to .NET. There's Mono, but I didn't get the impression that it works all that well on OS X. Maybe that notion is wrong, but at that point I didn't want to spend too much time delving into each language.
Clojure, then, looked very impressive. Especially the videos are enlightening. While not perfect, the language nimbly sidesteps many of the problems that existing Lisps (like Common Lisp and Scheme) seem to have. (For example, with macros, data structures, sequences, lazy evaluation, nesting levels in let and cond, list destructuring, etc... but really there's too many to list here... watch the videos instead.)
It needs the JVM, but that runs pretty much everywhere nowadays (unlike .NET or Objective-C), and as a bonus it comes preinstalled on OS X. This has the tremendous benefit that programmers have access to the vast Java libraries. It's easy to integrate this, and you can use several styles to call Java code (e.g. a functional style, a more object-oriented style, etc).
As a result, a pragmatic Lisp + Java libraries equals crazy delicious. :-)
Or so I hope, anyway. I probably won't be able to use it much on my clamshell, since it takes 17 seconds to start up... but then again, it's a G3/466. :-) Fortunately I also have a more recent MacBook where starting the REPL only takes 1.7 seconds. ^_^' At the moment, I am trying to make Emacs behave well when editing Clojure code. (Autoindent doesn't seem to work, what's up with that?)
More later. It's time to inhale the manual now...
For 2009, I am going to study a new language again. (This doesn't mean that I will abandon Chicken/Scheme development completely, by the way.)
The major candidates on my list were Nu, F# and Clojure. Turns out that one of them impressed me much more than the others... So much so, that I don't want to wait until 2009. :-)
While y'all ponder which language this is, I'll go prepare a blog post in which I will explain my decision. ^_^
There is still hope for Apple then. :-) Maybe the pendulum is now going to swing back again... from bland and colorless toward colorful, like in the good old days. One can only hope...
I am looking for a new job.
I am an experienced software developer, specialized in Python, with extensive knowledge of modern database systems. I have developed and deployed several client-server applications, initiated numerous open source projects, and written a number of Python-related articles.
Over time, I've worked on several projects (both professional and personal) that deal with crawling the web and extracting data from web pages and other files, so this has become somewhat of a specialty of mine.
More information can be found in my resume (which also contains my contact info). I also wrote about many of my interests and programming projects in various weblogs (1, 2, 3, 4).
I'm in Florida, and interested in either local jobs or telecommuting (which I have been doing in my last two jobs), especially Python-related. I am willing to consider relocating if necessary.
Today I finally decided to upgrade to Mac OS X Leopard. I know, I'm late to the party as usual, but in this case I wanted to wait until most of the wrinkles were ironed out.
My first impressions are... mixed.
I like the fact that I could upgrade from Tiger without much hassle. Everything still seems to work, including QuickSilver, Adium, Chicken, and Postgres. Most of my settings (like e.g. for Terminal) are preserved as well.
There were, however, a few changes that immediately stood out, and that I didn't like at all.
The new look of the dock is one of them. Fortunately, I knew this beforehand, and it's easily fixed.
I don't like the translucent menu bar either, but again, nothing a bit of poking around can't fix. :-)
X11 still doesn't work (I normally would not use this at all, except that there's a C64 emulator that depends on it). There are some articles that deal with this problem, I will have to look into that.
Something I haven't found a fix for (so far), and which bugs the hell out of me, is the new behavior of the little "view" icons in Finder windows. There are four of them now, and you can change a window's setting to use icon view, list view, columns, or Cover Flow. Great, except changing a view for one window means changing it *for all windows*.
In other words, let's say my default view is icons. I go to folder A, which has a lot of documents, so I want to change it to list view. I click on the icon, then open folder B. Surprise! It's in list view now too, and so are all other windows on your system.
Now, it's not completely impossible to change this and set views on a per-window basis, but it's so clumsy that you might as well forget it. In order to use icon view as the default, but use list view for folder A, I have to do the following:
This is pretty lame, IMHO... unless I'm misunderstanding things, it was *much* easier to do this in Tiger and its precursors. So far, from what I've read online, this indeed seems to be the new behavior: "Leopard also has new logic for views. Unless you've ticked the option to open in icon view, all windows will show whatever view you have just selected in whatever window. Like it or not, that's the way it is." [link]
(Strangely enough, other options like colored backgrounds, seem to be automatically on a per-window basis.)
More impressions will follow as I continue to work with the system. I haven't checked out the shiny new features yet (Time Machine, Spaces, etc). More about that later...
I did some long overdue Chicken hackery yesterday, and by accident I found out that Chicken's (or rather, SRFI-26's) cut/cute macros are not the same as Arc's [ ] syntax after all.
Scheme/Arc aficionados already knew this, of course, but to me it was news since I've never really used cut much. Here's a short explanation.
Scheme's cut produces an anonymous function that takes as many arguments as there are <> symbols at the "top level". E.g.
> (cut + 1 <>) #<procedure (? g3)> ; has one argument > (cut + 1 <> <>) #<procedure (? g4 g5)> ; has two arguments ; etc...
However, any <> that is found in a nested expression, is not considered as a parameter. Therefore:
;this works... > (map (cut + 1 <>) '(1 2 3)) (2 3 4) ; but this does not: > (map (cut + 1 (* 2 <>)) '(1 2 3)) Error: bad argument count - received 1 but expected 0: #<procedure (?)>
By contrast, Arc's [ ] syntax produces an anonymous function that expects one and only one argument, which is represented by a single underscore. As a result, it's simultaneously more and less limited than cut:
arc> (map [+ 1 _] '(1 2 3)) (2 3 4) arc> (map [+ 1 (* 2 _)] '(1 2 3)) (3 5 7) ; no problem ; but two parameters doesn't work: arc> (map [cons _ _] '(1 2 3) '(4 5 6)) Error: "#<procedure>: expects 1 argument, given 2: 1 4"
Of course, for anonymous functions that are more complex than this, it's probably better to just use lambda... :-/ Or a named function.
This started out as a Chicken blog, where I would report my adventures with Chicken Scheme. But these days it's more like a Python blog again. (Which isn't too surprising, given my experience with the language, and the fact that I use it for work and most of my personal projects.)
Heck, it has even been added to Planet Python again, which wouldn't have been the case if I wrote about Scheme all the time.
But really, I want to learn more about Scheme as well, *and* be able to use it in a pragmatic way. I just need a bit of focus. Right now I'm wondering what to look at next. Maybe object systems?
People new (and not so new) to Python are often confused by the fact that the language uses functions in some situations, but methods in others. I see this come up a lot these days. The most recent example is this comment:
Say you have a list, how is a beginning supposed to follow/comprehend the bigger picture when faced with code like this:
mylist = [1,3,2] print len( mylist ) print sorted( mylist ) print mylist.sort() print mylist.reverse() print mylist[0]Honestly, what is going on here? Why different syntaxes for slightly different ideas?
This gives many people the feeling that OO in Python was added later, or "bolted on", as Taw puts it.
I figure the reasons for the discrepancy are like this:
In 1991, when Python was first released, *pure* object-oriented languages were rare. Sure, there was Smalltalk, but it was fairly obscure. Other languages that called themselves object-oriented, like C++ and ObjectPascal, were actually hybrids; objects were indeed "bolted on" to an existing language.
In this light, it makes sense that Python 0.9.1 did the same. It had built-in types, and user-defined objects. Some of the types, like lists and dictionaries, had methods, possibly because were mutable and therefore contained "state". Other types, like numbers, strings and tuples, did not have methods (and were therefore not "perceived" as objects, even though behind the scenes they were). (In fact, back in the early 90s, the idea of calling a method on a number seemed like a really odd idea (if you were not a Smalltalker :-).)
As a result, in order to take the length of a string or a tuple, you needed a *function* (because you could not call a method on these types). While list and dict could easily have had such a method, for consistency's sake this was omitted; instead, the len() function was to be used on them too.
And so it still is. But the world has changed since then. OO has become much more mainstream, and the notion of using methods for everything is no longer odd, but expected by many. I can understand why someone coming from Ruby (or maybe Java) would wonder why in some cases functions are required, where a method would seem more natural. It makes Python seem inconsistent, when initially the use of len() actually improved consistency.
This is something that *could* have been fixed in Python 3.0, but won't, as far as I understand it. I'm not sure if this is a missed opportunity, or that it will keep Python closer to its original spirit (i.e., a multi-paradigm language).
(Note: I am aware of the __len__ method of course, but honestly, who is really going to use that instead of len()? __len__ is a hook to make len() work, not an alternative for it.)