Welcome to phong.org, the home of all things Phong. Actually, it's only home to some things Phong. There are other Phongs out there, and some of them aren't even me. How foolish of them! Anyhow, I occasionally post egotistical rants here. Do not be alarmed if they don't make sense or I don't know what I'm talking about. I also have some other pages that I occasionally do something with. They're in that menu thing floating over there.
2006-07-14:
The GTK+ file dialog is probably the worst user inteface disaster in the history of the universe.
2006-06-05:
Typing again. Not keyboard typing. Variable typing. I keep seeing people who can't keep different kinds of typing straight, and I think it's damaging their brains. So I'm posting this as a quick clarification. Not that anyone but me reads it. I do get the sort of satisfaction you get when you write an angry letter but never send it.
Strong typing - Variables/names may only be of one type. Types aren't converted or coerced mysteriously behind your back. If you need types converted, you must do it explicitly. You usually can't interpret a value as a wrong type. Strongly typed is roughly the opposite of weakly typed. A typical example would be Java. Python and Ruby are also strongly typed contrary to what you may hear.
Weak typing - Values may be automatically coerced on your behalf or behind your back. Often you are allowed to very simply interpret variables as the wrong type. Examples would include Perl or PHP, where numbers will get converted to and from strings as needed. Also, Perl will silently (usually) let you interpret references as strings, which is almost never what you want. C is also weakly typed, as is C++ insofar as it is backwards compatable with C ("real" C++ code is more-or-less strongly typed). If you don't believe me, take note of the abuses C can make of pointers and casting. (C has a good excuse, in that it is the language for doing low-level bit twaddling, etc.)
Static typing - Variables/names may only refer to a
single type. If x is an int at the start of a function, it can't
just start pointing to a float later on. Parameters to functions/methods are
required to be a specific type. Usually, collections (lists, arrays, hashes,
sets, bags, etc.) can only contain values of a single type.
Dynamic typing - Variables/names may be rebound to values of different types. Functions/methods don't generally enforce specific types of their parameters (at least, not at the language level - the code might do some sort of type checking if it has a compelling reason). Collections can usually contain values of mixed type. Popular examples would be PHP, Perl, Ruby, Python, Javascript and Lisp.
Manifest typing - Types of variables must be explicitly declared. This is not quite the same as static typing, but they almost always go together. It is possible to have a statically typed language where almost all of the types are determined by type inference. Rpython sounds like it's sorta like this. Java, C, C++, C#, VB and most traditional languages are manifestly typed.
Of course, none of these are black and white. Even very strongly typed
langauges have some small degree of weak typing built in. Most automatically
promote integer types to floating point when necessary. A non-manifestly typed
language might let you declare some variables as an optimization (e.g. Pyrex for
Python) or may require a declaration to specify scope (global in
Python, var in javascript).
Philip Greenspun famously observed that "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp." My corrolary would be that "any sufficiently complicated statically typed language will include a horrible, inconvenient feature intended to provide some of the benefits of dynamic typing." Examples would be things like templates, generics or abominations like VB's variant types. I suspect that many static typing advocates have developed their opinions on dynamic typing from having to endure these features, or from their experience with weak typing.
It could also be argued that dynamically typed languages all eventually include a feature or language variant that implements some part of static typing (e.g., Pyrex). It appears that uses of this for anything other than performance is very rare. This would seem to indicate that staic typing is mostly just a performance optimization. Since "premature optimization is the root of all evil," I'd conclude that enforcing static typing on a language-wide basis is bad.
I think the dynamic vs. static typing debate is eventually going to go in the direction of the garbage collection vs. manual memory management debate. Sure, manual memory management can be faster or more efficient, but it's just not worth it. Why not let the language handle it for you? The performance disadvantages of dynamic typing are gradually shrinking while simultaneously becoming less important as computers get faster. Eventually, static typing should be seen as unnecessary tedium for most problems.
2006-02-20:
I've recently started playing nethack, and have added a page for it here.
2005-10-09:
CSS sucks. It's not just that browser support for CSS is poor or uneven. CSS itself sucks. Sure, it's not helped by the fact that no browsers support the standards, and that IE doesn't even come close, but the standards themselves are deeply flawed.
Decoupling content from presentation
This is why we're supposed to be using CSS instead of deprecated
presentation tags or <table> layout. But it doesn't do the
job. It doesn't come close. Sure, it works great for setting your fonts and
colors and crap, but if you want to get your layout right, you still almost
always have to tweak your HTML. The order and nesting of your
<div>s and stuff matters too much. Often, layout elements
must be expressed in reverse order of what logic would dictate. Sometimes you
have to wrap things in extra tags (that are meaningless to the structure of
your content) just to get certain layout effects to work. Sometimes you really
can get exactly the layout you want with just CSS, but it's so complicated and
time consuming that you would have been better off just going with a lame
<table> layout in the first place.
Being able to change the layout by just changing the CSS is a fantasy.
Images are one of many issues that force presentational information into your HTML. Except for backgrounds, images can't be specified in any useful way in CSS. They have to be in the HTML. Some images are part of the content, so that's fine, but some are truly only part of the visual presentation. It's not as if you can eliminate these sorts if images completely - web sites NEED eye candy. If you think they don't, please explain your reasoning to my customers.
You'd still have a lot of these kinds of problems even if the the major browsers were all perfectly standards compliant because CSS just isn't powerful enough.
CSS Box model
Find a coffee cup. Put it in your refrigerator. Now, how big is your refrigerator? If you ask the W3C, they'll say that the refrigerator is the size of a coffee cup. If you ask a person who is not crazy, they will tell you the size of your fridge. Maybe some people will measure the inside, and some would measure the outside, and some might give you the cubic volume, but you'll never see somebody claim that a fridge is the size of whatever is inside it.
For years and years, web browsers measured your fridge the sane way. The size of a box was the size of the box, including padding and borders. But then CSS came along and took the sanity away. Why? There's no advantage to it. All it did was introduce yet another compatability issue that didn't have to be there. If they had just left it alone, all the legacy browsers would have already been compliant. Now you have to rely on hacks to make non-compliant broswers use the new, stupid box model, or hacks to make compliant broswers use the sane, "quirky" box model.
In spite of the fact that box-sizing: border-box; works, and is
part of CSS 3, the W3C CSS validator rejects it. It also rejects
-moz-box-sizing: border-box;, even though it follows the standard
that browser-specific extensions should start with a hyphen.
Columns are too hard
In the future, CSS will have real columns. Yeah, about the time that SVG and MNG files have broad support. Columns were half the reason why people used tables for layout in the first place. Sure, it's POSSIBLE to do column layout with pure CSS positioning, but it's complicated, counterintuitive and fraught with peril. Getting it to work consistently across browsers is too hard. Much harder than just throwing a table at the problem. If you're trying to get CSS to replace the "old way" of doing things, shouldn't you make the new way EASIER than the old way?
Lots of other things are too hard
Why is it so hard to center a box (e.g. table that isn't the full width of
the screen)? I know, it doesn't help that margin: auto isn't
supported consistently, but shouldn't there be some sort of thing that says
"center this thing"?
No standards for font sizes
It's damn hard to get fonts to render consistently across browsers and still
be accessable (e.g. allowing users to tell their browser to make the text
bigger and having it actually work). The standards are not specific enough.
How big should small or x-large be? How big should
1em be by default? How should browsers behave if the user chooses
a larger font size because their eyes aren't so great? How big should
<h3> be (relative to the base font size) by default?
In general, there are no standard defaults, so you have to set a lot more things explicitly than you should.
No way to embed fonts
Why? Web developers are tied to a very small subset of useable fonts because they can't distribute fonts with their web pages. Is it really that complicated? Fonts are embedded in PDF files just fine.
It's not like embedding fonts in CSS is going to usher in an era of rampant font piracy. There are lots of completely free fonts and browsers can easily honor the "don't copy me" flag. Besides, if somebody wants to illegally distribute fonts or pirated software on their web page, it's not like anything prevents them from doing that now. Should we prevent people from embedding text or images in their web pages because it could be a copyright violation?
Sure, fonts can be big, and maybe users don't want to download them. But the same is true of images - web browsers just give users an option to not include them.
No help with forms
CSS and newer versions of HTML/XHTML haven't done anything to help forms. Forms have sucked for a long, long time, and they continue to suck. Maybe we'll get XFORMS some day... But we've known that forms suck for a long time, couldn't we have a fix for them yet? Please?
Not expressive enough
CSS doesn't have any way to set and reuse values. I'm not looking for anything complicated here, just something to keep me from repeating myself repeating myself. The most common case is colors. Let's say I want to use the same shade of yellow for a background on one element, a border on some other element and the text color somewhere else. I have to mention it by RGB triplet in three places. Sometimes more. If I decide I want to change that color, I have to change it everywhere. It would be nice if I could set some variable at the top of the CSS file and then refer to that variable throughout.
The only solution is to have the CSS file generated on the server side by some script or mini-templating language. This either slows things down, because it has to be generated for each request, or you have to have the hassle of "recompiling" the CSS file any time you make a change. None of the solutions are any good
Developing on the web still sucks
It's always sucked. It will always suck. Somehow, the web has become THE place for the future of application development. I just wish it didn't suck.
2005-09-06:
I've always hated Comcast. Not the simple, casual "I hate it when the corner of my grilled-cheese sandwich gets soggy from the stupid pickle they always give you" sort of hate. I mean a real, visceral loathing. Today was the last straw. I'm too angry and too tired to tell the story again. Suffice it to say, my new life goal (I previously had no specific life goal) is the complete and utter destruction of Comcast. I want to be clear on my meaning. I am not a violent person, and will neither advocate nor engage in violence. However, I will not be satisfied with anything less than the dissolution of the entire corporation.
Sadly, they will still be taking my money every month. While I can learn to live without cable TV -- and I most assuredly will -- I cannot realistically live with high-speed internet access. It is my livelihood. There are no other cable providers in my area, nor can I get DSL, nor satellite (not that satellite would be acceptable for my application.) Allegedly in a capitalist society we are able to vote with our dollar. I have been disenfranchised.
When one ponders the complete and utter destruction of a giant corporation -- a company that can buy Disney can safely be described as giant -- it is easy to become discouraged. Where do you start? It is especially difficult for a person who intends to behave ethically. I do not yet know the answer, but I will take some first steps. I will write a letter to my congresspeople. And when I say "my congresspeople", I mean, all 435 members of the United States house of representatives, all 100 members of the United States Senate, all 40 members of the Florida state senate, and all 120 members of the Florida house. I will write a total of 695 personalized, hand-written (if it doesn't kill me) letters, 1-2 pages each. Considering that I will not be watching TV anymore, 2-4 letters per day is a realistic goal without a significant over-investment in my time. That nine months or so gives Comcast a chance to milk me for a few hundred more dollars and gives me plenty of time to come up with a better plan.
2005-09-05:
Numbers are simple, universal, immutable things. 1, 2, 3... An arithmetic progression of ever increasing magnitude. Two is still two even when it's a pair, a couple, dos, zwei or ni. Seven was greater than five before time began and will be still when we're gone. One thousand is twenty times larger than fifty. That's not something we invented. It's just something we noticed.
Somehow, human beings invert this mechanistic regime. One is so much bigger than ten or twenty or one thousand. Big numbers like 161, or 10,000 are meaningless. One is sticky and rigid and harsh. One is a nameless corpse floating in a flooded street. One is a mother trapped in her attic, screaming and dying. One is a tearful call on a borrowed phone just to say "I'm OK." You can't multiply that by thousands. It stops making sense. You become numb.
2005-09-04:
After ages with no updates, I decided to redo my layout a bit. I can't claim pure original inspiration on this one. I got the transparency trick from Eric Meyer's complexspiral demo, though I have a more primitive version of a similar idea on my Pansi page. I also got the color palette from colourlovers.com. The image is all mine though, from my OpenGL thingy. I'm still working out some of the kinks (it doesn't yet have all the tweaks the old layout had), and I'll have some work ahead of me to make it work with substandard browsers like IE. This project is pretty fucking exciting.
Also, I've moved to Florida. DtMM has the pictures.
2004-06-23:
I was playing around with The Rasterbator and produced a wall-sized poster, but wanted a few features that it didn't have. One evening, when I had too much coffee, I decided to write a clone in Python. It took about three hours to get 95% of the functionality I wanted. I used the excellent Reportlab and Python Imaging libraries.
It could use some cleaning up, but it really works quite well considering how little time I've spent on it. The most time consuming part was adding the command line parameter support (instead of hard coded variables at the top of the script), which I didn't get around to until about a week after writing the prototype.
Anyhow, I decided to give it a page of its own and share it with anyone interested. Feel free to download The Masterbizor.
2004-06-04:
This is, of course, the title of the second track on the Aphex Twin single Windowlicker. Try as I may, no amount of googling will reveal its meaning (if it has any). If you happen to know, I would like to know...
2004-04-28:
My Go progress has been pretty nice. I ended up making 9 kyu before my birthday. I really wish I had gotten back into it sooner - it's been a pleasant and challenging diversion. I recommend everyone give it a try - it only takes a few minutes to learn the rules (which are simpler than virtually any other board game). Those coming from a Chess background should find it espescially interesting and may be quite surprised at its depth.
...
Do you ever get the feeling, when you're talking to someone, that they're using an entirely different language with mostly the same words? The syntax is not quite the same, and some of the words seem to have different meanings... In fact, the ideas they're communicating seem to come from some sort of incomprehensable alien thought process with rules of logic incompatible with our own. It's as if they had a strange system of math where familiar things like the associative law of multiplication do not apply.
I feel that way more and more each day...
2004-03-26:
I won't be surprised if I make 11k by April Fool's and 10k by my Birthday.
Python has foo.strip()
Not the string.strip() function in the string module - I'm
talking about the method you can call on any string object. Ok, that seems
pretty trivial, but it's a bit deeper than that. If I had a nickle for every
time I've reinvented that wheel in Perl, I'd have an unholy assload of nickles.
It's always
($foo = <FH>) =~ s/(^\s+|\s+$)/g;.
Sure, I could be a good guy and load something from Text:: that
does that, or write just one function that I include from everywhere, but that
seems pretty damn stupid for one little line like that. I'd much rather
foo = fh.readline().strip().
There are dozens of things like this. Python has decided to go ahead and include them in the language in a clean, readable way. In Perl, they're usually pretty easy, but they're rarely clean. Since there's no simple, cannonical solution, everyone's idiom for doing little things like that is different, making others' code that much less readable. In other languages it gets worse - really common tasks like that are sometimes downright difficult.
To be fair, I can't get rid of Perl. Shorthand like
perl -p '$_ = "wget $1\n" if /href="(.+?\.jpg)"/i'
is just too irresistable for
those throwaway parsers that I write every day.
2004-03-15:
No time to update lately, but my Go is progressing. I made 12k today on KGS only a couple weeks after making 13k. I should easily make 11k by tax day or my birthday.
It occurs to me that vengence is always the wrong reason to engage in any activity.
2004-02-18:
It's weird when you look at your web site stats and learn that you're the third result for a google search for "pork rinds benefits".
It's been a while since I've said a cool thing about Python. Today is another that wasn't on the original list of 50.
Almost everything is hashable
You can use just about anything for a dictionary key, and it works. This includes non-stringy things like objects, classes, funtions, types, etc. Here's a little interpreter for a useless mini-language. It uses funcions as dictionary keys to define classes of commands in the mini-language based on the type of parameter they accept.
#!/usr/bin/python import sys, time, math, operator checker_commands = { int: ('fibonacci', 'factorial'), float: ('sub', 'add', 'mul', 'div', 'sqrt', 'log'), str: ('print', 'reverse', 'concat'), time.strptime: ('schedule', 'alarm'), } checkers = dict([ (cmd, chk) for chk, cmds in checker_commands.iteritems() for cmd in cmds ]) def fibonacci(value): if value < 1: raise ValueError last1, last2 = 1, 1 while value > 2: last1, last2 = last1 + last2, last1 value -= 1 return last1 def factorial(value): if value < 0: raise ValueError return reduce(operator.mul, range(1, value+1)) # Define more functions here command_functions = { 'fibonacci': fibonacci, 'factorial': factorial, 'sqrt': math.sqrt, 'print': lambda x: x, # etc. etc. etc. } def handle_command(command, parameter): if not command_functions.has_key(command): raise Exception("Unknown command '%s'." % command) if checkers.has_key(command): parameter = checkers[command](parameter) print command_functions[command](parameter) while 1: line = sys.stdin.readline() if line == '': break; command, parameter = line.strip().split(" ", 1) handle_command(command, parameter)
2004-02-16:
"Hi, I'm Mr. Soandsuch and I'd like to talk to you today about my bizarrely vague business proposal. I have this idea for a project. It's not so much an idea; it's more a notion. A fuzzy notion. A hope that someday I'll have an idea. Anyhow, I'll talk business-speak at you for a while until our synergy reaches critical mass and magically precipitates into money.
"You see, it's this really complex project, an endless black hole of despair. I actually think it's quite simple because my brain resembles a moist bar of soap. I understand that it will be difficult for you to estimate the cost of implementing something this nebulously defined, but that's OK, because I won't be paying you. Instead, you can have a few shares of stock in my new company. It's worth the cost of a pack of cigarettes, but I'm sure you'll agree that owning a fraction of that is better than owning nothing at all! When I close my eyes, I can see our customers lining up to pay for our new product/service. Perhaps you should be paying me for this opportunity!"
2004-02-06:
I was thinking that it's pretty easy in my mind to make a list of my top 5 videogames of all time.
- Doom I/II
- Star Control II
- Grand Theft Auto 3
- Super Mario Bros. 3
- The Sims
I consider Doom II to basically be an expansion of Doom I (a very good expansion) because it's basically the same game/engine/controls with some new enemies, levels and weapons. So I think it's fair to count them as one game/experience. It's difficult for me to put SCII second, but it's DOOM we're talking about here. I could almost put Mario 64 in place of SMB3, but not quite. The Sims is the only member of this list I'm at all unsure about. How much did I play one implemenation or another of Tetris (the import Tetris Battle Gaiden being the best ever), or some other puzzle game like Dr. Mario? How can I, in good conscience, omit the Mario Kart, Metroid or Zelda series? These games all caused me to lose plenty of sleep, but I can say that about Blaster Master, Dragon Warrior or Ninja Gaiden. Fine games all, but could they even make my Top 10? What about something fucking brilliant like Ikaruga that I've only ever played for short periods? Maybe it's not such an easy list after all.
2004-02-04:
2004-02-03:
Something's been bothering me ever since the Superbowl half-time show (typically an insidious bore), and I think I finally figured out what it is. It's not seeing a bare breast on television. I'm all for that. I'm a pro-boob guy. Maybe not Janet Jackson's boob; she's like 50 or something on top of looking very much like her brother. I just don't think there's that much hot there to get excited about. Was it done intentionally? I don't think I care. I honestly don't think anybody's ever been harmed by seeing a tit for 2 seconds.
The thing that bothers me is, if it was intentional, it was basically simulated sexual assault. It was portrayal of a guy forcefully ripping clothes off a woman who didn't seem particularly amenable to the idea. Sure, if it was staged, then she must have agreed beforehand, and they were "involved" before, and yada, yada, yada. Whatever. The point is, it was meant to look like sexual assault. That's not funny. That's not sexy. That's not even smut (and I'm pro-smut). It's degrading, it's violent and it's hateful.
I'm sure I'm overreacting. Maybe it really was a "wardrobe malfunction". Maybe Mr. Timberlake was supposed to rip off some other, less revealing part of her costume. Maybe I'm just taking a sophomoric prank too seriously. Still, has MTV produced anything of substantive value in the last 10 years? There's been some sleaze, a lot of swearing, bizarre and inconsistent censorship policies and an occasional forgettable video for a bland popular song. That's about it. Beavis and Butthead were high-brow sophistication compared to the jetsam they've shat out recently.
Pop stars and actresses like Janet Jackson, Brittany Spears or the cast of Charlie's Angels claim to be role models for young women. OK, I get it, women should be able to express their sexuality, be comfortable with their bodies, etc. That's fine and good, but didn't we figure that out 30 years ago? The sexual revolution happened before I was born; it's old news. I doubt that any of the cretins who haven't caught up yet will be turned around by the likes of Ms. Spears. Shouldn't we be aiming a tad higher than "skank" on the suffrage-o-meter? Uber-slut might be the pinnacle of achievement in those occupations but it's a pretty dubious career path for most normal people.
If you manage to look beyond the boob tube, there actually is a bevy of genuine, positive female role models. Sadly, far too many pass into history unknown or forgotten by the masses. How many know the achievements of Rosalind Franklin? Her pioneering work in molecular biology were pivotal in unraveling the structure of DNA. Just cracking into the chauvinistic, male-dominated field of science during the 40's and 50's was an accomplishment in itself. She broke new and important scientific ground in spite of a disapproving father and sexist, fractious colleagues. The discovery of the double-helix led to a 1962 Nobel prize shared by James Watson, Francis Crick and Maurice Wilkins. Tragically, Franklin could not share in the award, having died of ovarian cancer four years earlier at only 37 years of age. Her contributions to the discovery were as great as any of her male peers.
It's maddening to see so much time devoted to the lives of every simpering moron in Hollywood and every lecherous politician in Washington. Wouldn't it be wiser to remember the lives and accomplishments of the thinkers, teachers, scientists, inventors, writers, explorers and social reformers that reinvent the world with each generation?
2004-02-01:
Well, the holidays are behind us and everyone has shifted back into their old routines. Some are more shifty than others of course. During lunch the day after Christmas I had the pleasure of listening to some blow-hard demonstrate what sort of people many Americans really are.
The conversation started with some discussion of the earthquake in Iran. He found the disaster marginally interesting, laughing about the "crappy mud huts" that were to blame for the catastrophic loss of life. This was not shocking; most Americans don't typically get too worked up over dead people in other countries. Certainly, we all remember 09/11/2001, but how many of us remember 01/26/2001? "Gujarat? Is that one o' them terrorists things?"
He went on to complain about his trip to the Bahamas. In particular, he found the people who live and work there to be uniquely intolerable. He droned on about how he had to walk through "straw markets" dodging the locals trying to peddle their wares. He blathered on about having to avoid the "bohemians" (sic) offering to braid his hair with their filthy fingers. His coworkers laughed along as he so skillfully mocked the accents and illiteracy of the "natives." Yep, those money-grubbing savages will do anything for a Yankee tourist's buck.
He took special offense at having to haggle over the cost of a ride back to the boat. Once he'd finally bullied them down to a price commensurate with the disrepair of the taxi, they'd "act polite", but still gave him the "evil eye." Worse, they'd want to pick up other passengers and collect more fares! Surely, five bucks ought to get non-stop limousine service, a spit-shine and a smile. That driver ought to be grateful for the opportunity to do business with a rich, overweight American.
As he continued his story, laughing about how he was nearly arrested for attempting to strangle the driver in a drunken rage, I thought he should be grateful that he can provide food for his family. I thought he should be grateful that he can afford a nice house in Bloomfield Hills. I thought he should be grateful to be so pampered on a vacation to an exotic destination with such "interesting" people. I thought he ought to spend just a few moments, just one day removed from Christmas, to thank his lucky fucking stars that he's never had to endure the sort of abject poverty that he took so much delight in mocking.
Is it any wonder the world hates us?
2003-12-18:
I've made a small bugfix release of my Python auto-initializer. It now no longer blows up on the bizzare case of using a default value on the "self" parameter (or whatever else you named it). To be honest, I'm surprised that's even legal. I can grok how it works, I just don't know why somebody would want to do it. I guess you could then call an object method as an unbound function without giving it the otherwise required parameter. The only reason I found it is because I inadvertantly omitted "self" from a parameter list
2003-12-15:
It would be cool to switch to a 28 hour day.
2003-12-03:
So, I've finally managed to get back into Go, and I've made a little web page for it. There's just some links and filler there at the moment, but I'll flesh it out eventually. Go rulez
pyGame, SDL interface for Python:
SDL is cool, ergo, pyGame is cool.
Pyrex:
You can write C modules very easily with a very Python syntax.
Everything is a dictionary:
Python, of course, has hash tables as a built in data type (called dictionaries). Any useful language has hash tables as a built in data type with their own syntax and whatnot. What qualifies as a useful language? One with hash tables as a built in type with their own syntax of course!
In Python though, lots of things are dictionaries that you don't expect, like classes, objects and modules. You don't neccesarily use them that way, but that's the way they are implemented, and it makes things very flexible.
Sequences:
Python's sequence types (strings, lists, tuples, dictonaries) are nice.
Every language has them, that's true, but there's so much nice stuff built into
Python for working with them, and the semantics are simple and consistent.
Like Perl, there are things like map and slices, and there's also
some other cool things like list comprehensions (lifted from Haskell
apparently.)
2003-12-01:
I hope everyone had a pleasant Thanksgiving. I myself did serious damage to the domestic turkey population of this country.
I should avoid reading the web in the middle of the night. You can stumble across some pretty scary stuff.
Doing so much with so little:
It never requires much code to do anything in Python. The clean, terse syntax is part of that. The plethora of standard and third-party modules doesn't hurt either. Thanks to SilverCity, for example, I'll probably be syntax highlighting my code examples:
#!/usr/bin/python import sys from SilverCity.Python import PythonHTMLGenerator PythonHTMLGenerator.preformat = lambda self, text: self.escape(text.expandtabs(4)) intext = sys.stdin.read().strip("\r\n") sys.stdout.write('<pre class="python">') PythonHTMLGenerator().generate_html(sys.stdout, intext) print '</pre>'
That's 90% of the behavior I want with just a handful of code. It took less time than writing this update. Adding, e.g. language detection or vim modeline detection (for tabstop size) would be almost trivial. This docutils syntax highlighting recipe which I found on Python Daily is what gave me the inkling to do it.
Of course, it's no accident that Python code is short and sweet and I'm certainly not the only one who's noticed:
- Steve Ferg - Java vs. Python, a Side-by-Side comparison
- A study comparing statically typed languages and scripting languages
2003-11-26:
This reason wasn't on my original list of 50, but since I came up with an interesting use recently, I thought I'd mention it.
Metaclasses:
Yep, you can modify the types of your types. Or, the class of your classes, if you prefer. It can let you do some brain exploding things, or some things that are just kinda handy.
The thing I did with them was save myself some future typing. I was inspired by this Wiki discussion about initializers and eventually came up with something that I think is pretty slick. Instead of this:
class Thing(object): def __init__(self, color, length, width, height, weight): self.color = color self.width = width self.height = height self.mass = weight*0.45359237 # convert pounds to kilograms # do more stuff
I can just do this:
class Thing(Selfish): def __init__(self, _color, _length, _width, _height, weight): self.mass = weight*0.45359237 # convert pounds to kilograms # do more stuff
The metaclass spots the parameters starting with "_" and automatically creates an __init__ function for the class that initializes them for me. The function is generated at the time the class is created (not class instances), so there's only a tiny, one-time performance impact. Never again will I write the parameter list in triplicate!
Of course, the metaclass can easily be modified to automatically generate all sorts of other functionality that is boring to code over and over again. Feel free to download and share the code; let me know what you think: selfish.py
2003-11-17:
Today's "thing that makes Python cool" is a big one, so I'm only doing the one.
Python is dynamically typed:
I was going to put up a big argument here about why dynamic typing (and dynamic languages in general) are better than statically typed languages. It's quite a popular holy war though, and a well visited argument, so I'm only going to hit a few points and list a few links to some good material on the subject.
The typical argument in favor of static typing assumes that the compile time checks it provides are of great benefit (i.e. the same robustness is not easily achieved in a dynamic language) and that the cost of static typing is negligible. I would argue that both of those assertions are false.
The only reliable way to know that a program is correct is to use plenty of test cases that run the software through its spectrum of behaviors. Static typing adherents would argue that the compile time checks of a static language would have to be replaced by additional "type" unit tests in a dynamic language. Anyone making that argument cannot possibly have used a dynamically typed language for any period of time. It is obvious to dynamic typing fans is that such additional checks are not required at all. The test suite in a dynamic language is virtually identical. If your unit-tests thoroughly check your program's behavior (a requirement in either environment), and the behavior is correct, the type usage can't possibly be wrong (even if it appears so from a statically typed perspective.) In my experience, most type errors occur because of static typing - in a dynamic language, they're not errors at all!
On the other hand, the costs of using a statically typed language are much higher than the just the red tape of type declarations. The loss in flexibility cannot be understated. Writing abstract, reusable code in a dynamic language is much less difficult (see links below.)
I'd say that most static typing fans are the prisoners in Plato's allegory of the cave. They don't understand, and even fear the flexibility of dynamic typing because many of them haven't worked with something like Python; or at least, not long enough to really see the benefits. Even many who have worked with a dynamic language had a bad experience because they stuck to their static mindset and didn't take full advantage of the flexibility offered. In a way, I suppose that's true of many programming concepts. It's hard for a beginning programmer to see the advantage of even simple concepts like arrays and recursion until they've used them. After they've been coding for a while, they'll wonder how they did anything without them!
Programming in general is moving towards having the language do more for you. Zero terminated character arrays are replaced by real string types. Memory allocation via malloc/free is replaced by garbage collection. Hand tuned assembly is replaced by more powerful compilers. Likewise, I think dynamic typing is going to eventually replace static typing in many domains, and I think it's a bigger win than almost anyone realizes.
Here are some articles in favor of dynamic types:
- Bruce Eckel - Strong Typing vs. Strong Testing
- David Buck - Domino Changes with Static Typing - Why static typing breaks encapsulation in OO programming
- Robert C. Martin - Are Dynamic Languages Going to Replace Static Languages?
- Cincom Smalltalk Wiki - What about Static Typing? - links to a couple interesting arguments
- Oliver Steele - Test vs. Type - A good explanation of the kinds of typing
- Anatol Fomenko - Why Dynamic Typing?
This
article presents an interesting counter-point. While they admit that
static typing in languages like Java or C++ sucks, they argue that a better
static typing system (e.g. with inferred types) is a good thing. I would agree
with most of what they're saying (I am not familiar enough with the languages
they mention to know if they can really provide the amount of flexibility that
dynamic languages offer), but I'll disagree with his Artist and
Gunslinger example. I've never had that kind of problem in
practice, and I think it's probably very rare in general. I also have to take
issue with his assertion that a list of mixed types is not useful. I use them
all the time (a mix of different types of numbers, different kinds of
"printable" objects, a mix of callables and NoneTypes, a mix of
lists and non lists, etc.):
2003-11-11:
Maddox has updated his page. He also found Matrix Revolutions to be less than stellar.
I suppose I really shouldn't be surprised, but rock, paper scissors turns out to be an international organized sport, and the strategies are more sophisticated than I ever imagined. Naturally, there is a computer RoShamBo competition with surprisingly strong players. The description of Iocaine Powder, one of the stronger computer players, explains how they work.
It occurs to me that __init__() functions in Python could be
made cooler. There's this WiKi page discussing
solutions in Ruby and Python, but it would be neat if a slight extension
were made to the language (though it might not be generally possible):
# We can do this: def __init__(self, foo, bar, baz="bob"): self.foo = foo self.bar = bar self.baz = baz self.do_stuff() # This is better, but still lists things three times: def __init__(self, foo, bar, baz="bob"): self.foo, self.bar, self.baz = foo, bar, baz self.do_stuff() # It would be cool if we could do this: def __init__(self, self.foo, self.bar, self.baz="bob"): self.do_stuff()
Continuing the series I started earlier, here are a few more reasons why Python rules.
Syntactic whitespace isn't evil:
I'm still suffering from significant cognitive dissonance over this anti-feature. I should be hating it, but I somehow like it. It's the thing that kept me from learning Python all these years. I guess that most of the time, it's a Good Thingtm.
Pleasant OO model:
Many popular languages make it a real pain to write object oriented code, making it frustrating to get anything done the "right way" (though in fairness I am not yet very familiar with Smalltalk or Ruby, which my understanding have very similar models to Python). Writing good OO C++ code is damn annoying. Perl's OO mechanisms are less than elegant. Java is overly burdened with all kinds of fiddly crap.
On the other hand, Python keeps it simple. Writing reusable OO code requires hardly any more effort than hacking out the quick-and-dirty solution. I never find myself wasting time buried in minutia.
In spite of its simplicity, Python offers advanced OO features such as multiple inheritance and meta-classes. The language is flexible enough to make it reasonably simple to write reusable extensions such as multiple dispatch.
wxPython is quite decent:
GUI toolkits suck heavily, as a rule. However, wxPython sucks significantly less. For one thing, it uses your platform's native widgets, whatever those may be (if possible.) Being that it is a Python interface to wxWindows, it's also pretty easy to write solid, flexible cross-platform GUIs.
2003-11-05:
I saw Matrix Revolutions at an IMAX theater and have to say that it sucked. I would recommend not seeing it. There are a couple of cool scenes in it (nothing as good as the better scenes from the previous two), but overall it was quite painful to watch.
2003-11-03:
Let's see if I can get mathML working... It's kinda a pain that you have to get your web server to serve the correct content type. Many times you don't have any control over that at all. I thought that was meta tags were supposed to be for. Anyhow, this is the formula used to compute the "pval" in an ABX test. Note: if you have IE, Microsoft has deemed you not worthy of MathML support.