Efectos Especiales
Ramblings, rants, musings, ideas and observations. Topics include (but are not limited to): programming (especially Python), books, games (especially CCGs and board games), astrology, design, writing, painting, etc.#828 (old comments) Septic shock
I'm currently working through the Programming Ruby book, second edition. I'm not even halfway, but I thought I'd write down some of my impressions of the Ruby language. (I've done so before, by the way, so this isn't really a first impression.)
Ruby is not a difficult language to learn, especially not if you are already familiar with dynamic languages. However, I found it less easy than expected, because of the differences in philosophy between Ruby and Python.
While it should not be taken too seriously, the Zen of Python does a good job of explaining the design principles that make up "the Python Way". Unsurprisingly, "the Ruby Way" turns some of these ideas on their heads, especially:
- Explicit is better than implicit.
- Special cases aren't special enough to break the rules.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one-- and preferably only one --obvious way to do it.
This is probably why some of the example code and Ruby constructs just make me cringe. They took several hits from the Perl pipe, and it shows. I'm not saying this is a bad thing. This is not a Ruby-bashing post. (Nor is it a Python-bashing post, by the way. :-) I'm just saying that I'm having a hard time with the difference in philosophies.
Let's start with Ruby's strengths. Its object model is powerful and elegant, and arguably cleaner than Python's (at least since 2.2). You can implement accessors, class methods, mixins, operators, etc with ease. Metaprogramming is easy, understandable (as far as metaprogramming goes) and reusable. On top of that, Ruby has some really powerful constructs, like code blocks, class_eval
, and the ability to extend existing classes and instances on the fly. It's also consistent: everything is done with objects and method calls.
(Yes, you can do most of these things in Python too. I'm not saying that Python is less powerful in these areas, but it's easier to do the above in Ruby, and it doesn't feel "tacked on" like e.g. Python's class methods.)
That said, Ruby does have its problems. While the aforementioned features may be clean, there are also areas where the language feels definitely messy, at least from a Pythonic point of view.
Ruby likes to cut corners. A lot. If you are so inclined, there are many, many ways to shave off those extra characters or lines. For starters, you can often omit the return
keyword, self
, or method call parentheses and commas. TMTOWTDI is also popular; there are many ways to do or write the same thing, sometimes gratuitous, sometimes with subtle differences (e.g. {}
vs do..end
and and
/or
vs &&
/||
). Like Perl, Ruby has unless
in addition to plain old if
, and both of these are allowed as statement modifiers as well (e.g. do_something if x==y
). Last but not least, there's a whole slew of non-intuitive $-variables, like $!
for the current exception, $.
for the current line number in a file being read, etc.
So in these respects, I think it's messier than Python. (YMMV, of course.) Problem is, it's not that these features aren't useful. To the contrary, they are extremely useful. If it was cleaner in these respects, I might actually consider switching. But as it is, after a session of Ruby programming, I just feel like I've been digging in the dirt, in spite of the clean OO system. Ruby seems to care more about clever hacks than Python does, and less about readability. Like I said, this is more of a philosophical difference than anything else. Over time, I've come to like the Python Way, though, and this is a bit of a culture shock for me.
I'm sure I'll have more to say about this later, considering that I'm currently using Ruby for one of my projects... which will be revealed in due time, if it survives.
#827 (old comments) Porn Star or Pop Star?
One of those silly Flash games. It's remarkably difficult to tell the two apart (which isn't much of a surprise, really). Or, in the game's own words: "It's not as easy as it looks, but it is as slutty as it looks."
#826 (old comments) Why Wax does not have a toolbar
If you look into a recent Wax distribution (e.g. 0.3.19), you might notice a file toolbar.py
in the tools
directory. This is a mistake. That file should not be there.
I put it there a while ago when I still assumed that it would make a good addition to Wax. I did not check it in into CVS; however, it was mistakenly included in the zip file distribution, unfortunately.
So, initially I considered adding a toolbar to Wax, based on wx.ToolBar
. After all, a toolbar is a handy thing to have, right? But as it turns out, wx.ToolBar
does not integrate well with Wax. It may be a great addition to wxPython... an easy way to add a toolbar with buttons and associated events, and possibly other controls too (checkboxes, dropdowns, etc). And it doesn't require a sizer.
In Wax, however, it's just as easy, or maybe even easier, to grab a Panel
, and add buttons or whatever to it in the usual way. When I was trying to add wx.ToolBar
, I realized that I was trying to add a similar (but not entirely the same) way of adding controls and events to a panel. Why have two incompatible ways of doing this? It's not like wx.ToolBar
offers many benefits over the traditional approach. IMHO, the Panel
approach is more flexible and more standard.
It's also a pain to write a wrapper for wx.ToolBar
. The wxPython approach (AddTool
creating the button for you, events based on IDs, etc) is very un-Wax-y, and in order to fix it I had to write a ToolBarItem
object, which has problems of its own. And all this to emulate constructs that are already present in Wax. So eventually I decided that it just wasn't worth it.
So. There will be no toolbar in Wax, at least not based on wx.ToolBar
. And please don't use the toolbar.py
that accidentally made it into the archive. Thanks.
#825 (old comments) What's in a name?
As a test, I tried to enter "nowak" in Factbites. The resulting page has a whole bunch of stuff, mostly about famous Nowaks (or at least those who have accomplished more than just writing a few crummy programs ). I'm in the list too, although not with my first name. It appears that the search engine takes random (probably not, but random-looking) sentences from web pages.
The link to the Wikipedia entry for Nowak caught my eye. It also has a list with "famous Nowaks", which does *not* include me... I would have to work a little harder to be on there, next to scientists, writers, politicians, etc. (Of course, I *could* just edit the page... )
I did not know that Nowak was the most popular surname in Poland. I actually do know some Polish people with that name, but in my case, my ancestors were from Czechoslovakia, as I mentioned a few posts ago. Of course, it's possible that *their* ancestors were Polish. Then again, Czech names often have the ending vowel + k, so it's hard to tell, and the page has no data on the popularity of the name in the Czech Republic or Slovakia.
Then this page says: "Last Name Meaning & Related Resources for the Surname NOWAK [...] Definition: New guy in town, from the root now, meaning new. The Nowak surname was occasionally bestowed on one who converted to Christianity (a new man). The Nowak surname is among the most common in Poland and is also very common in other Slavic countries, especially the Czech Republic (where it is spelled NOVAK). Surname Origin: Polish, Czech."
Hmm, I never know what the name meant, or that it had a meaning at all. It does seem kind of obvious, with a root now- or nov-.
#824 (old comments) Factbites
(Via Keith): Factbites. A search engine that's "different".
"What do you get if you cross a search engine with an encyclopedia? Factbites - a new way to search the web. Other search engines spew out meaningless site-names and mangled phrases. Factbites offers you real, meaningful sentences that are right on topic."
Interesting concept. A few quick tests...
- Searching for "python" gives a large number of meaningful results. Books, articles, the Python home page (but also references to Monty Python).
- "python programming" also has a number of relevant results, although it starts with a Wikipedia entry, and the python.org homepage is listed somewhere in the middle.
- "python pitfalls" does not find my article. I'm not saying it should, but it's unclear whether the engine does not know the article, or considers it irrelevant, or that this is simply something that it's not optimized for.
More later, maybe. It's interesting, but it doesn't look like it's going to replace Google anytime soon, not in my toolbox.
#823 (old comments) Hook and bait
Does the following Ruby code have a Python equivalent? If so, what is it?
class MyClass def MyClass.method_added(name) puts "Adding Method #{name}" end def new_method # Yada yada yada end end # produces output: # Adding Method new_method
(As seen here. It's part of the presentation 10 Things Every Java Programmer Should Know About Ruby. Read it, even if you're not a Java programmer.)
Needless to say, the method_added
class method catches the creation of a method in its class, and reports on it. Apparently it works immediately, for methods defined in the same class
block.
The following Python code looks like it might do the same, but doesn't:
class Meta(type): def __setattr__(cls, name, value): print "Setting:", cls, name, value type.__setattr__(cls, name, value) class Foo(object): __metaclass__ = Meta # this is not caught by Meta.__setattr__: def bar(self, x): pass # this is caught, though: Foo.magic = 42
I don't know all that much about metaclasses, so maybe there's a way to do this. Right now, I don't see how, though. Feel free to enlighten me.
(And yes, one could probably write a decorator that registers the method... but that is not really the same.)
[Update] Several people pointed out that the way Python reads a class definition is different from Ruby. In Python, the whole class is read in as a whole, before the __setattr__
has a chance to kick in. (Apparently this is different in Ruby.) Most of the method_added
behavior can be emulated by a combination of __init__
(going over the class's methods) and __setattr__
(to handle methods that are added after the class has been defined). See the comments for more.
#822 (old comments) The incredible disappearing language
According to De Telegraaf, most Dutch are not concerned about the future of their language. About 8 out of 10 people expect that the Dutch language will survive and will not be replaced by English. More here.
I'm not sure. What many people (especially those in the Randstad) may not realize, is that for quite a few people in the Netherlands Dutch is actually the second language. And I don't mean immigrants. For many people, their local dialect is actually their first language; ABN (the "official" version of Dutch) is the second.
Many of these dialects are not just "Dutch with a few different words thrown in", and would actually be considered languages if they had had any formal status. I personally know quite a few people who prefer to speak dialect, because it's easier to them; they speak "ABN Dutch" to those who don't know the dialect. But they don't really *like* the Dutch language all that much... to them it's the language of Holland. [1] Which is basically what it is; ABN is largely the dialect of Holland (or started out that way).
At some point, English (or another language) might fill the role that ABN has now. That is, large groups of people will continue to speak their local dialects, and use English to communicate with those who don't speak it (the rest of the world, literally). As communicating with non-Dutch people becomes more and more common, there will be less reason to learn Dutch. This probably won't cause Dutch to die out anytime soon, but I believe it will eventually become less and less important. I even expect that at some point it will be restricted to the Randstad. But that might still take a century or so...
(Of course, I might be overly pessimistic... my expectations might be biased by my own experiences. I am from Limburg, and people there might have different ideas about languages and dialect than the rest of the Netherlands. Then again, I have reason to believe that speakers of dialect in many other provinces feel the same way.)
(I don't speak any dialect myself, by the way... so in my case, Dutch really *is* my first language, which is not all that common in Limburg. As such, I am less of "a Limburger" than my peers were.)
[1] Foreigners often refer to the Netherlands as "Holland", but strictly speaking this is not correct. Holland is actually a small (though important) part of the country.
#821 (old comments) Foreshadowing
I just looked through some old posts, and found this one, from Feb 2003. The little class described here is the grandfather of Wax. ^_^
In other news, I added Wax 0.3.19 to the Cheese Shop (direct link). It's really very runny, sir.
Now to figure out how to lay an egg...
#820 (old comments) Timetwister
wxPython has its own date/time routines, wrapped into wx.DateTime
. Trying to use it without reading the fine manual may lead to surprising results.
>>> import wx >>> d = wx.DateTime() >>> d.Set(24, 12, 2005) <wx.DateTime: "09/24/05 00:00:00" at _38f3a901_p_wxDateTime>
?! Let's take a look at the docstring:
>>> print d.Set.__doc__ Set(self, int day, int month=Inv_Month, int year=Inv_Year, int hour=0, int minute=0, int second=0, int millisec=0) -> DateTime
Some more poking around reveals what is going on... sort of:
>>> d.Set(1,1,2005) <wx.DateTime: "02/01/05 00:00:00" at _38f3a901_p_wxDateTime> >>> d.Set(2,1,2005) <wx.DateTime: "02/02/05 00:00:00" at _38f3a901_p_wxDateTime> >>> d.Set(3,1,2005) <wx.DateTime: "02/03/05 00:00:00" at _38f3a901_p_wxDateTime> >>> d.Set(1,2,2005) <wx.DateTime: "03/01/05 00:00:00" at _38f3a901_p_wxDateTime> >>> d.GetMonth() 2
It turns out that in the C++ code, the second parameter month
is actually an enum. This would not be so bad, since integer values can still be used (at least in wxPython), but the problem is that it starts at zero. So January is 0, February is 1, etc. A remarkably bad decision, that makes the Set
method very non-intuitive to use. Sure, you can easily work around it, but if the day and the year are exactly what they seem, why use a brain-damaged enum for the month?
Anyway. Wax will not use wx.DateTime directly. In fact, Wax users don't need to know it exists at all. Not just because of the way it handles months, but also because Python already has a date type in the datetime
module. No need to add another type to the mix. So the forthcoming DatePicker
control will have a SetValue
method that supports datetime.date
types, but also 3-tuples (year, month, day), and maybe more. All of these will use January=1, etc.
(Another issue I ran into was that wx.DatePickerCtrl
does not seem to have a GetRange
method, although the wxWidgets reference manual claims it does. Hmm.)
Design and content © 2004 Electric Shock / Hans Nowak