tag:blogger.com,1999:blog-204257122024-03-08T22:15:32.667+01:00Constantly ChangingAttila Szegedihttp://www.blogger.com/profile/11586966395114113526noreply@blogger.comBlogger150125tag:blogger.com,1999:blog-20425712.post-89794182254374724502010-09-09T17:17:00.004+02:002010-10-16T00:10:16.825+02:00Running YourKit UI remotelyI got into a somewhat unique situation few weeks ago: I had a JVM heap dump 16GB in size that I had to analyze using a memory profiler. It was obviously hopeless to analyze it on my laptop which only has 4GB of RAM. Fortunately, I was given access to a computer half the world away that had 64GB of RAM. What I did was I moved my YourKit profiler instance onto that machine and tried to run it using X.11 tunneled through SSH.<div><br /></div><div>The good news is: it works.</div><div><br /></div><div>The bad news is: it needs tweaking to work.</div><div><br /></div><div>First thing I run into was that the GUI was hideously slow. I would click on a button in the profiler, and feedback would take several minutes. I'm not joking. Several <b><i>minutes</i></b>. Googling revealed a Sun Bug Database item <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4488401">"Antialiasing/Compositing is slow on remote display"</a>. It suggests that to run GUI Java apps over X.11, one should add</div><div><br /></div><div><span class="Apple-style-span" style="font-family:'lucida grande';">-Dsun.java2d.pmoffscreen=false</span></div><div><br /></div><div>as a JVM startup flag. I added it to profiler's yjp.sh launch script, and Holy Moly, it became <i>much better</i>. Granted, it was now rendering screens progressively from top to bottom, but it did it in matter of <i>seconds</i>, not minutes. It now felt like something out of 1999 instead of 1993. Further Googling for various combinations of "X.11" and "slow" and "ssh" turned out sites that suggested it's possible to make x.11 over a bit faster, by telling SSH to use Arcfour or Blowfish ciphers instead of AES, as well as to compress the traffic:</div><div><br /></div><div><div><span class="Apple-style-span" style="font-family:'lucida grande';">ssh <span class="Apple-style-span" style="color:#FF0000;">-c arcfour,blowfish-cbc -C</span> -X <i>host</i></span></div></div><div><span class="Apple-style-span" style="font-family:'lucida grande';"><br /></span></div><div>This led to further improvements; the progressive rendering got faster by another factor of two. That's as good as it gets. Now it feels like something out of circa 2001. I can work with that.</div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com1tag:blogger.com,1999:blog-20425712.post-19924195001313136072010-06-28T17:41:00.002+02:002010-06-28T17:47:15.022+02:00I work for Twitter now<div>I work for Twitter now.</div><div><br /></div><div><i>"Why?"</i></div><div><br /></div><div>Twitter is an amazing company that provides an amazing service to the humankind. I see it as a fundamental new modus of communication that's quickly becoming part of the global human culture. Whether the earthquake in Haiti or the post-election uprising in Iran, Twitter has proven to be a reliable and prompt medium for getting the latest news on what's happening in the world, directly from the people most involved in the events. (While simultaneously still allowing you to to tell your friends what you had for breakfast, of course.) I appreciate its singular focus on doing one thing right, and that it managed to remain simple to use. Twitter is experiencing a 16% month-over-month (that's exponential!) traffic increase, and I'm very excited at the prospect of throwing my weight behind making it able to cope with this welcome challenge. The company is chock full of extremely bright people that I will no doubt be a delight to work with, and maybe some of their awesome will rub on to me too...</div><div><br /></div><div>I want to change the world for the better and make a positive influence on people's lives. Often, the most significant changes are the ones people don't even notice, because they make Things Work As They Are Supposed To. How big a change? I have no idea yet, but it could be vital. If it makes the difference between a smooth operation and a Fail Whale for someone caught in the next civil unrest who's using a momentarily available internet connection to let his family know he's okay, it can mean the world to them.</div><div><br /></div><div>I appreciate Twitter's open-source fostering culture. Today, the barrier to entry for influencing lots of people's lives is actually pretty low. It's called Open Source Software, and it's easy to participate and create serious value. I count that for every hour I spent on my OSS projects, I saved in thousands of man hours to my users, a number that will keep growing until the last of my code goes out of use (will be a while...). The value leverage is just insane. I just never figured out how to make it pay the bills, so I can't devote myself 100% to it. Twitter plays great in the OSS ecosystem, so I hope that I'll be able to create value in two streams: improving Twitter through the OSS it relies on, and as a consequence, improving the said OSS.</div><div><br /></div><div><i>"So are you moving to Bay Area?"</i></div><div><br /></div><div>Yes. We're working on my visa, and once that's approved (hopefully around October), I'll move with my wife and children to San Francisco to join the company in person. Until then, I'm working remotely from home in Hungary. I'm absolutely thrilled at the prospect of living there, and I'm very much looking forward to this new adventure.</div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com6tag:blogger.com,1999:blog-20425712.post-49551843212019576782010-02-22T15:00:00.000+01:002010-02-22T15:01:03.118+01:00Windows Live nightmareLast week I purchased a copy of Gears of War - it cost me some 12 bucks in local currency, one of the benefits of only buying 2-3 year old games. Yup, I'm the guy from <a href="http://xkcd.com/606/">this comic</a>. So it happened that this weekend I decided to play a bit with it, so went to install it on a Sunday afternoon.<div><br />As installs go, it was uneventful, and I got to launching the game.</div><div><br /></div><div>First snag, it tells me that it needs to install an "AMD Processor Update" otherwise it will crash during gameplay. Okay, let it install it. Reboot machine. Restart the game. I can play now, right?</div><div><br /></div><div>Wrong.</div><div><br /></div><div>It again tells me it needs to install the same update. Uh-oh. Okay, give it another try. Reboot machine. Restart the game.</div><div><br /></div><div>I get to the main screen. Fine. I can play the game now, right?</div><div><br /></div><div>Wrong.</div><div><br /></div><div>I attempt to start the campaign, and it tells me that unless I have a Windows Live profile, <i>I won't be able to save games</i>!</div><div><br /></div><div>Excuse me?!</div><div><br /></div><div>*Pause*</div><div><br /></div><div>Oh well, let's create a Windows Live account, I can live with that. It opens a browser, I fill out few forms, and off we go. I can play the game now, right?</div><div><br /></div><div>Wrong.</div><div><br /></div><div>Next it tells me that now it needs to update the local Windows Live client binaries. It tells me that <i>I can choose to not update now, but I won't be able to play the game until I do</i>. Yeah, that's great choice, indeed, how very thoughtful of them to give me options.</div><div><br /></div><div>We're now at about one hour mark from the moment I inserted the install DVD. But once it got updated, I can finally log in and play the game, right?</div><div><br /></div><div>Wrong.</div><div><br /></div><div>It now tells me that Windows Live is "not supported in my region." How splendid! If I live in Hungary, I'm not allowed to save my bloody games, is that what you are telling me? Apparently, yes.</div><div><br /></div><div>Another hour of googling and forum reading ensues. I end up on some dead links at sites named xbox.com and gamesforwindows.com and the likes where I can supposedly change my region but in reality I can't. I end up on a site where finally I can do it (I think it's some long domain name with words "windows" and "account" and "services" in it in some order). I lie that I'm in UK. It seems to accept it. So, I can now play the game, right?</div><div><br /></div><div>Wrong.</div><div><br /></div><div>They still claim I'm in "unsupported region". Turns out, they're protecting against such smartypants as I am, naive people who believed that Internet is global and makes it irrelevant where do you sit physically. Nope. No matter what you change your location to, the initial location when you created your account <i>sticks with you</i>. At one forum, a user tells me that if I were to create a different account now (forget the one I already have, it's tainted forever he tells me), and initially log in through some obscure UK site, and supply plausibly looking UK address and phone number then I could... sheesh.</div><div><br /></div><div>I give up, play Bioshock for 15 minutes (all I had left of my evening), go to sleep, cursing my actions that led me to being exposed to a Microsoft technology again.</div><div><br /></div><div>Next morning, more forum trawling. Turns out that you can create a "local" or "offline" profile, and that it lets you save the game locally. Hey, that's all I really ever wanted! So, how do I do it? Because, sure enough, I didn't see this anywhere on the UI when they were gently pushing me in the direction of creating a Live account.</div><div><br /></div><div>Turns out, you need to click some kind of a "Learn More" button during the account creation process, and the <i>help document</i> will contain a link (only if you scroll to the bottom of the page) that will open a dialog to create a local account. At least it didn't say "Beware of the tiger" on the door...</div><div><br /></div><div>So, let me get this straight: some Microsoft genius, in an attempt to drive as many users as possible into signing up for their Live service thoroughly hid the offline account creation, even if this will cause genuine grief for a subset of those users that are in an "unsupported region".</div><div><br /></div><div>To use an analogy (it'll be a car analogy, of course), it's as if you'd have a four-lane highway, and all traffic signs point you to drive there to reach your destination, and of course you do, but after a bit of a drive, there's suddenly a blockade on the road, and since the license plates on your car are from an "unsupported region", you aren't allowed to drive further, and the grumpy officers won't tell you how you're supposed to get to your destination, only that they have specific instructions to not let pass the lower castes such as you are. So you drive back, and eventually find some secret vagabond scratchings on a wall (that'd be the forum posts) that point you to an otherwise unmarked dirt path through a forest, that will let you eventually reach your destination.</div><div><br /></div><div>In the end, I have my local profile, so I can play the game now, right?</div><div><br /></div><div>Right. Except I feel like I've been kicked in teeth by the whole experience so far, so it'll be some time before I'll have any desire to go back to this. Honestly, yesterday evening I was an inch from ritually burning the DVD. And I know that next time I hear that a game requires Windows Live in any capacity, that'll be a good sign for me to steer clear of it.</div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-24757716042896313882009-11-16T08:12:00.001+01:002009-11-16T08:12:30.409+01:00November momentOh, the sudden urgency in the people’s steps in the street as the raindrops start hitting the pavement. I don’t have an umbrella, so I’m drawing close to the buildings on the way home for some little shelter their walls and balconies can provide. I thought these buildings familiar, but either because I’m passing so close to them, or because of the rain, they smell different. It’s surprising, but pleasant and triggers some previously deeply buried childhood memories.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-57546411066575703482009-09-08T09:19:00.004+02:002009-09-08T17:21:40.161+02:00Review of the Commodore 64 emulator for the iPhone<em><b><span style="color:#FF0000;">UPDATE</span></b>: Apple yanked the app because of the BASIC interpreter hole, and the developers <a href="http://www.manomio.com/index.php/blog/important_update">have plugged it and resubmitted the app</a>. Way to go, Apple. I mean, what harm could that BASIC interpreter do? It has no means of loading external code - no access to local filesystem of the underlying OS, no network connectivity, nothing. Are they afraid I'll manually type-in a program from a listing published in a magazine or something? I got tons more </em>sense of childlike wonder<em> from toying with the interpreter than I could ever from playing Jack Attack and Dragon's Den combined! Sheesh... On to the original review:</em><br /><br />Against better judgment, I ended up taking my iPhone with me to the bathtub yesterday evening. I needed to check something really urgent, like the IMDB rating of "Watchmen" or similar (just finished the book). You know, stuff that you risk water damage to your high-tech gadget. I ended up browsing my RSS feeds instead though and spotted news about <a href="http://daringfireball.net/linked/2009/09/07/c64-emulator">Commodore 64 emulator being approved by Apple and available on the App Store</a>.<br />Now, you need to know that the first home computer I've ever been exposed to was a Commodore 64, at around age of eleven. I've got an enormous amount of emotional attachment to it, being enthusiast hacker for it as a kid. So, I was sitting there in my bathtub thinking, "this would be nice to get" and then realized "wait a minute, I can get it; right here, right now."<br />Let's pause for a moment to think about it folks, just how big enabler Internet is in our lives. I mean, there I was, purchasing a Commodore 64 simulator from my bathtub, and a minute later, I launched it and started toying around with the UI.<br /><br />That's where disappointment started to set in.<br /><br />Oh, don't get me wrong. Developers of this application (and the excellent <a href="http://frodo.cebix.net/">open source Frodo C64 simulator</a> they based it on) deserve every praise possible. I've used Frodo several years earlier, and it is painstakingly precise reproduction of a Commodore 64, up to the point of hardware side effects. The iPhone application is tasteful, snappy, responsive, and the UI is okay.<br />I do actually have one gripe with the UI, though. See, Commodore 64 horizontal resolution is 320 pixels, exactly the same as that of the iPhone. Since the developers added a graphic around it resembling the venerable Commodore 1701 monitor, the mask obscures some of the pixels at the edge. This is very annoying actually, since lots of games display important information around the top and bottom edges. These machines back then emitted an image that had two distinct areas named "border" and "paper". Border was the outermost part of the image and had a single attribute: color. Paper was a smaller rectangle within the border where the image was actually displayed. The purpose of the "border" was specifically to act as a disposable margin that could be clipped to size by your monitor (in many cases, a TV screen) so that you don't lose paper pixels. The developers of the iPhone emulator thus improved aesthetics at expense of functionality.<br /><br />But that's not what I'm disappointed with.<br /><br />Honestly, I could be disappointed by the initial selection of games; they're all ancient simplistic titles even by Commodore 64 standards, old 1983 titles where developers still didn't know how to utilize the platform to its potential. There will be more games available later, so I'm not too worried about that. (I hope they will release Elite...)<br /><br />That's not what I'm disappointed with.<br /><br />What I'm disappointed with is the lack of the Commodore 64 essence, as I experienced it. That essence, ladies and gentlemen, is <em>hacking</em>. Even as a kid, I disliked it when people were using the machine exclusively as a game console. As a bit of personal history, let me tell you that my family was not exactly wealthy when I was a kid, and that too is an understatement. After I became interested in computers (following a series of articles in a monthly magazine for school kids), I would write my little programs (initially BASIC, later 6510 machine code) in a notebook, then annoying one of the three people in our village who had a machine to give me a bit of a time to try them out. I saw the potential for creating my own stuff in these machines, and couldn't imagine why would someone, who is fortunate enough to actually be able to afford one, use it only to play games on it. I disliked people who didn't see beyond gaming (I'm not saying it was justified and think the same today, I was an eleven year old kid then, remember?).<br /><br />Commodore 64 was an utterly open platform. Even from BASIC, you could <a href="http://ready64.org/articoli/_files/043_pokesc64.txt">POKE</a> around with it (for those not in the know, "POKE" is a basic command for directly setting contents of a memory location). Even before I would have a Commodore 64 of my own (which I had to wait all the way until 1989 to be able to afford one; cool kids were playing with Amigas by then) I would have a <a href="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/commodore_za_sva_vremena.png">book</a> that contained a description of the BASIC, of the contents of both BASIC and System ROM (complete with all system calls and memory locations it used for settings, buffers, and so on), of all peripheral chips (VIC, SID, CIA1, CIA2 etc.), their mapped memory locations and how to program them, a complete reference of 6510 machine code, and finally, complete hardware schematics for the machine. If you had this book, you could do anything with the machine. <em>Anything</em>. And believe me, I did a lot. Won't go into details now as I'm well into get-off-my-lawn territory here.<br /><br />That's why I'm disappointed that I won't be able to do a lot with this one, except play old games on my phone. I don't imagine that under Apple's regime I would ever be able to fire up <a href="http://turbo.style64.org/index.php?cid=about">Turbo Assembler</a> and write some rasters, if you know what I mean. And that's what makes me sad.<br /><br />Apple even only approved the emulator once the developer has disabled the BASIC, so it's not even the familiar C64 screen that welcomes you on startup. It looks like this instead:<br /><br /><img src="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/IMG_0429.PNG" /><br /><br />However, turns out there's a workaround; the BASIC ain't disabled, it's just hidden. If you go to "Advanced" and turn on "Always show full keyboard", then launch a game, go to "EXTRA" keys, and tap "RESET", you end up with the familiar screen:<br /><br /><img src="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/IMG_0430.PNG" /><br /><br />(Mind you, the problem with monitor mask clipping the edge pixels is particularly articulated in this picture - you don't really see the first character in the line!) I had a bit more fun with it though now that I had a command line. For starters, let's see if there's something on the "floppy disk":<br /><br /><img src="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/IMG_0424.PNG" /><br /><br />Sure there is! Looks like a floppy for "Dragon's Den" (one of the games included with the app). Interestingly, it does not matter what game I started before resetting the emulator: the "floppy" in device 8 was always that of "Dragon's Den". I didn't find other numbered devices containing other games "floppies" either. For now. However, here's a kicker. (Or an easter egg if it's intentional, although I don't think it is.) If you load the program from the floppy and run it manually:<br /><br /><img src="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/IMG_0425.PNG" /><br /><br />OMG, YOU GET AN INTRO!:<br /><br /><img src="http://dl.getdropbox.com/u/362958/misc_web_images/c64iphone/IMG_0427.PNG" /><br /><br />That's correct ladies and gentlemen - the developers seem to had trouble locating a genuine copy of the game, so they bundled one that was distributed by a cracker group. Back in the day it was customary for people who cracked games for, erm, "unofficial distribution" to prepend a small program to it called "intro" which was a colorful, blinking screen with greetings to fellow members of the trade and good chiptunes. They also usually led to menus for enabling cheats and sometimes on-screen instructions for the game in case the player didn't have the original game manual at hand. <em>Like, if you're playing on an iPhone, right?</em> (Honestly, if that wasn't there I would have never figured out this particular game on my own. So the intro actually added value for me. Also, the fact someone had this game in cracked form but not in uncracked form strongly suggests that if it weren't for crackers, we wouldn't have this game today. Just sayin'.)<br /><br />Needless to say, the intro isn't there if you launch the game from the iPhone app menu.<br /><br />Verdict? Nice easter egg with the intro, folks. Beautiful, polished iPhone application. Potential for more game titles to come. But if you were more than a game player on Commodore 64, don't hold your breath. You'll likely never be able to upload any of your your own old time C64 creations on the device to show it off. For that, you'll still need an emulator on your desktop OS.<br /><br />I hope at least they'll release Elite, though. That'd be awesome.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-46182953182593402752009-03-17T14:16:00.004+01:002009-03-17T18:06:03.945+01:00Relativity of simultaneityA problem with staying in a profession for long years is that there's less and less things that can truly excite or surprise you as the time passes. That's why I was particularly delighted to experience a moment of sudden enlightenment while listening to Rich Hickey talk about "Persistent Data Structures and Managed References" last thursday at QCon in London. The title of the talk might not sound exciting, but I have to tell you, if this were the only talk I attended, it alone would have been worth attending. I don't say this often. <a href="http://qconlondon.com/london-2009/file?path=/qcon-london-2009/slides/RichHickey_PersistentDataStructuresAndManagedReferences.pdf">Slides are here</a>, although you're missing out Rich's incredibly good verbal presenting style if you just read them, obviously.<br /><br />Rich's view (with which I have to agree; in the time I knew Rich, I have yet to hear the first thing from him I'd disagree with, whether it be concurrency, memory models, or ideas for what to do in San Francisco if you only have a single day to explore it); so, Rich's view is that the idea of variables in traditional programming languages is broken, because they are based on a single thread of control at a time. This used to be true in single-threaded programs, and even to a degree for multi-threaded programs running on single-CPU systems.<br /><br />He argues that we need well defined time models for state changes in our concurrent computational systems. A lack of a time model fails to capture the situation where two observers (threads, CPUs) can observe two events (changes of state) in different order.<br /><br />Then it suddenly hit me! I learned this stuff in school! Relative timelines, observers... Rich is talking about <i>relativity of simultaneity</i>!<br /><br />(Which is one of the simpler conseqeunces of Einstein's special theory of relativity.)<br /><br />Wait a moment. Finding such a surprising parallel analogy between physical world surrounding us and our digital computational systems seems at first unlikely, but thinking more of it, it makes perfect sense. For event timelines to appear differently to different observers, we only need two prerequisites: truly parallel processing, and finite speed of change propagation. Both are true for the real world (quite massively parallel, and the changes propagate at at most the speed of light), and for digital computational systems (parallel already at two CPU cores, with changes occurring in CPU registers and needing time to propagate downstream the hardware memory model to be observable by other CPUs).<br /><br />One of the wonderful things about Rich is that he's able to express these notions very clearly. It is all really obvious when you think about it, and I couldn't even say I <a href="http://constc.blogspot.com/2006/06/accomodating-for-everyday-parallel.html">wasn't aware of it for at least three years now</a>, it's just that before hearing this talk, I always had a very slight hope that someday, someone (infinitely wiser than me) will somehow be able to, you know, solve this. <i>Eliminate</i> this <i>problem</i>. The thing I realize now is that it's <i>inherent</i>. You can no sooner eliminate relativity of simultaneity and the rest of consequences it brings to the table from our computational systems than you could cancel its effects in the physical world.<br /><br />Rich does the only sane thing to do with a problem you can't eliminate - he embraces it. His programming language, <a href="http://www.clojure.org">Clojure</a>, is an attempt at being the easiest way to write correct concurrent programs. Emphasis on all of "easy to write", "concurrent", and "correct". I learned about Clojure sometime last year when it came up at the jvm-languages mailing list. I read up the documentation on the website, and came away thoroughly impressed. Then I met Rich and saw a 30-minute Clojure presentation last year at the JVM language summit, saw the 60-minute version of the same talk now at QCon, and I'm still impressed. Clojure embraces the problem of concurrent state modifications by encapsulating the state into "references" - the only mutable data types in Clojure, which all point to immutable values. The references can change in time though to point to new values, and the big idea here is that each reference has defined concurrency semantics for how and when change occurs.<br /><br />Now, there's likely a huge number of temporal semantics of how can some entity's state change. Clojure identifies several usual semantic categories though, and provides them for ease of use. We have synchronous coordinated (Clojure has a STM for that), synchronous uncoordinated, asynchronous uncoordinated, as well as isolated (thread local). I think you can build whatever you need using those.<br /><br />Anyhow, during Rich's talk I had a moment of enlightenment. Not because I heard something entirely new, but because the pieces of the jigsaw puzzle finally fell into place and revealed a picture. The picture does away with a false hope I had, which is good as it is a clear and definite answer to a question, and having accepted it it is at least clear to me what's the direction forward. During the rest of the day, I was telling pretty much everyone I met and their dog about how I was shown the inherent manifestation of relativity in finite-speed concurrent systems. (Joe Armstrong was just smirking at it, probably thinking "you wet-behind-the-ears kids, this should've been obvious to you for decades", and then we proceeded making fun of all n-phase commit protocols, for any finite value of n).<br /><br />On multicore systems, there's no longer absolute time. Every core runs on its own relative time and there's no definite sequencing of events. It's time we build this assumption into our code, and not use tools and methodologies that are ignorant of this fact. And as Rich would point it out, writing your code in Clojure is a good way towards the goal.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com6tag:blogger.com,1999:blog-20425712.post-4170791815857190902009-01-30T16:25:00.003+01:002009-01-30T16:47:38.073+01:00Speaking at QConJust a heads up that I'll be speaking at <a href="http://qconlondon.com/london-2009">QCon in London</a> this March, about using <a href="http://qconlondon.com/london-2009/presentation/JavaScript+in+the+Enterprise">JavaScript in the enterprise</a>. Looking forward to meet you all there.<br /><br /><img align="center" src="http://dl.getdropbox.com/u/362958/misc_web_images/Speaking_Qcon_London_01.jpg"/>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com2tag:blogger.com,1999:blog-20425712.post-45024996460771967252008-12-03T11:48:00.005+01:002008-12-03T12:17:48.025+01:00IP telephony on iPhoneI spend quite a lot of time on calling my colleagues in US or UK (I am in Hungary), which can result in quite exorbitant phone bills. I tried to fix this lately by looking for IP telephony solutions for iPhone - I often have conference calls lasting upward of half an hour, and up to even two hours, so I don't want to be confined to my desk or any other physical location. I will often walk up and down in the apartment, subconsciously tracing patterns of the carpets with my feet (it's funny when I consciously realize I'm doing it), staring out of various windows at the sky, sometimes sprawling on a sofa and so forth. (Hey, working from home has its perks!). So, I need mobility within the apartment, hence I still want to use the phone.<br /><br />Now, Skype would be the obvious choice - for a flat fee of 10.29 EUR/month I can get <a href="http://www.skype.com/intl/en/allfeatures/subscriptions">unlimited calls</a> to both US and UK numbers. Major hurdle is that Skype ships no client for the iPhone. <a href="http://www.fring.com">Fring</a> actually does the job, it is a multiprotocol chat/voice client for iPhone (and some other phones) that supports Skype accounts too. Voice quality is not particularly good, but it's within tolerable. Fring however lacks an essential (for me) feature - it does not provide a DTMF keypad. I always dial into the company conference center, and must be able to punch in the conference number I wish to join. Fring can't do it. I can still use it to call direct extensions, but the bulk of my calls is through the conference system, and it's a no-go. I asked Fring support, and all they told me was:<blockquote>Currently, it is not available to dial DTMF sounds on fring, this should be implemented in future versions.</blockquote> For the record, Skype desktop client does have a DTMF keypad.<br /><br />Next choice is <a href="http://www.truphone.com">TruPhone</a>. They offer a client for iPhone (and also a bunch of other makers' devices). TruPhone operates their own call service, much like Skype does, and while there's no flat-fee subscription model, their 0.06 USD/minute plan is sure quite attractive (heck, even calling numbers within my cell provider's network, T-Mobile Hungary, is more expensive than that!). The voice quality is very good, even better than cellphone (one coworker remarked after I first used it to dial in to a conference that I sounded much clearer than I usually do). The client app also has a muting button and a DTMF keypad, the first useful, the second essential for conferencing. It would all be rosy, if only the client weren't extremely buggy. Sometime, with iPhone OS 2.1, the UI would slow down (you could see it animate scrolls pixel by pixel) and it'll then claim there's not enough memory. iPhone OS 2.2 seem to have fixed that, but now it instead often complains that it can't find "Wi-Fi coverage" (even though the iPhone itself clearly sees the network). The aforementioned DTMF keypad has the tendency to not react to touch, or conversely, to get jammed as if I touched the key but didn't lift my finger, sending a prolonged shrieking "beeeeep" of that particular number key tone through the earphones into my skull, full volume. (The iPhone built-in phone app nicely tones down the DTMF beeps on my end of the line, so I still have an audio feedback that I'm typing them, but don't hear them full-volume). Regardless, the "low memory" and "unable to find wi-fi" are the most critical problems - even turning the phone off and on again doesn't always help it with its wi-fi disorientation syndrome (and mind you, I should never be forced to power cycle my phone just to use an app!).<br /><br />So, it's a mixed bag. I'd use Fring if it had a DTMF keypad because of a flat-rate unlimited calls provided by Skype. The second best right now is TruPhone, which provides very good voice quality and otherwise pleasant service with low pay-as-you-go rates, but their iPhone client is bordering on unusable because of all the bugs. I'll be eagerly awaiting app updates to both.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com4tag:blogger.com,1999:blog-20425712.post-83275503326083754732008-11-18T23:26:00.004+01:002008-11-19T11:39:36.070+01:00World of GooI found a fantastic game. It's named <a href="http://www.worldofgoo.com/">World of Goo</a>. Here's a <a href="http://www.dailymotion.com/video/x2y52j_world-of-goo-gameplay-trailer_tech">trailer</a>. And here's the <a href="http://en.wikipedia.org/wiki/World_of_Goo">Wikipedia entry</a>. Check those ratings - 9/10, 9.5/10, 10/10, 93%, 96%.<br /><br />It's hard to summarize what's right about this game. Most everything is.<br /><br />Let me start with few obscure details that might appeal specifically to a computer geek like me.<br /><br />First, this game runs on Windows, on Nintendo Wii, and on <i>Mac OS X</i>. Linux version comes soon. And guess what, the Mac OS X version is not a lame "Win32 API linked with Wine" kind of port. Proof that it isn't is that Wine-linked Win32 API using Mac software only runs on Intel CPUs. Not so this game. It runs on Macs with PowerPC CPUs (either a G4 or a G5). It's pretty much a native version on Mac OS X. It runs crisply on my iMac G5. I asked the developers in e-mail about their development methodology, and the developer Ron Carmel was kind to reply. (The whole company seems to be just two guys, working from wi-fi equipped coffee houses in San Francisco. They have years of experience working for big name game companies, though.) Anyway, Ron's response was:<br /><blockquote>at some point, when we realized we're going to go multi-platform (wii/pc at the time) we simply abstracted away anything and everything platform dependent from the code. this meant graphics, sound, input handling, window creation, threading, that sort of thing. the game only deals with a set of abstract classs that it gets from a singleton "environment" class. those classes provide a set of services (like graphics, sound, etc) and we have different implementations of those classes for windows, mac, wii, and soon linux.</blockquote><br />I can't say just how much I respect people who take this approach. It's one of hallmarks of professionalism in my book. More often than not, even much more complex software systems <i>can</i> (and should) be developed to be really multiplatform. At least on unices, it is fairly common to maintain software as CPU-agnostic (and often OS-specifics-agnostic) source code with small CPU&OS adapters. These guys however didn't only do it across different unices, which are all closely related OSes. They did it across Windows, Mac OS X, and whatever is the OS of the Wii. That's 3 operating systems, and likely 3 different CPUs too (Intel, PPC, and whatever the Wii CPU is, although AFAIK, it's also some PPC variant). Consider how most large software houses can't be bothered to do this - they just target Windows primarily, even though they'd have lots of internal benefits if they cleaned up their source code to be multiplatform.<br /><br />Second obscure detail, the game has no DRM. None. These guys were smart enough to realize it'd be a waste of resources to bother with it. Another big tip o'the hat to them.<br /><br />What this game <i>does have</i> though is: captive, immersive, innovative gameplay based on building structures out of gooey balls that bind to each other, and leveraging mechanics in a very realistic physics simulation (on various levels, you'll need to use tension, elastics, gravity, wind, flotation, and so on). It's tremendous fun. Immersion is further helped by the fact that there's no UI aside from the mouse pointer - all interaction with the game world is by directly dragging and dropping the otherwise aimlessly wandering goo balls with the mouse.<br /><br />There's lot of humor and cuteness baked in. You can get emotionally attached to little goo balls as you could to those lemmings back in the day. <br /><br />And then there's the beautiful visual art (that at times reminds me of Tim Burton movies, particulary The Corpse Bride), and music that perfectly matches it to create the immersive atmosphere. There are overarching motives and hints of a backstory that are intriguing on their own.<br /><br />It's ideal for a casual gamer who needs to blow of steam for an hour after a hard day's work. My son is playing it every evening. My daughter is playing it every evening. I am playing it every evening. You can play it too in minutes - there's a downloadable demo with the full first chapter of the game (the full game has four chapters and an "epilogue").Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com2tag:blogger.com,1999:blog-20425712.post-84995301862535308492008-10-22T22:41:00.003+02:002008-10-22T23:39:54.172+02:00FreeCC, the modern JavaCCIf you ever needed to write a parser, you hopefully didn't do it by hand but rather used a parser generator. The two predominant parser generators in Java are <a href="http://www.antlr.org/">ANTLR</a> and <a href="https://javacc.dev.java.net/">JavaCC</a>. JavaCC project however suffers from paralysis for too many years now. The original developers aren't present for too many years now, and the current set of active committers didn't make any significant improvements for years. My FreeMarker colleague Jon Revusky has recently taken interest in it (FreeMarker having used JavaCC in the last six years, when Jon ditched the hand-written parser of the 1.x versions). Since his improvements to the JavaCC codebase weren't accepted by mainstream (largely dormant) JavaCC project, he did the only correct move: he forked it.<br/><br />Enter <a href="http://code.google.com/p/freecc/">FreeCC</a>.<br/><br />FreeCC is backwards compatible on source level with JavaCC - it can generate parsers from existing JavaCC sources, and the parsers behave identically (since it's a continuation of the original codebase with different name, it's not too surprising, but doing the work under fresh name, it doesn't hurt to emphasize), FreeCC, however has some modern new amenities, such as:<br /><ul><br /><li>typesafe collections in its own code, instead of Java 1.1 Vector and Hashtable</li><br /><li>instead of hardcoded prints in the source code, the parsers are generated using editable templates (can you say "multiple target languages support?")</li><br /><li>other long overdue source code sanitization</li><br /><li>generated parsers don't rely on static singletons anymore</li><br /></ul><br />These are all nice and dandy; code reworks in particular improve the project's long term maintainability by making its comprehension more easy for newly joining developers (in this regard, FreeCC is much more welcoming than JavaCC for a newbie hacker). These however don't really give you much of an advantage when you're writing your grammars. The following ones do, and they're the real kickers:<br /><ul><br /><li>code injection feature eliminates (or at least strongly reduces) the need for manual post-editing of files</li><br /><li>grammar include feature, which allow smaller grammar files to be reused in larger ones (with JavaCC, you had to copy-paste), as well as allow you to organize larger grammars into separate smaller files.</li><br /></ul><br />These features are also the sign of what kind of features are still to come: features that provide you with modern conveniences a programmer in a need of a parser generator would wish to have. These two new features above help you create maintainable grammar sources, and they are just the start. If you adopt these features however, there's no going back. Since JavaCC doesn't have these features, your grammar files will no longer be compatible with JavaCC, only with FreeCC. But you'll hardly want to go back. FreeCC has taken this particular parser generator codebase much further in its few months of existence than the JavaCC project did in years, and is gaining traction. Given the fact that FreeCC is a continuation of the current JavaCC codebase (which didn't really progress further since the fork), it is really risk-free to try it out for your next project (or even in current project!) instead of JavaCC. You can also expect that the developer will be more open to your feature requests, as Jon has a good track record of listening to community wishes in FreeMarker.<br/><br />FreeCC is <i>the</i> JavaCC you'd want to use in 21st century.<br/><br />At FreeMarker project, we've already switched to FreeCC; FreeMarker 2.4.0 and 2.3.15 will both have a parser built using FreeCC. Since Jon also works on FreeMarker, he's truly eating his own dog food. (Actually, there's even more to that. Since FreeCC in turn uses FreeMarker as the templating system for its output, he's eating his own dog food doubly! This seemingly creates a circular dependency between FreeMarker and FreeCC, except that luckily all that was needed was a FreeMarker JAR with parser built still using JavaCC to bootstrap the process initially; the projects are self-sufficient since and don't need JavaCC anymore.)Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com1tag:blogger.com,1999:blog-20425712.post-20633634464827878242008-10-08T10:31:00.003+02:002008-10-08T12:44:05.185+02:00HTML encapsulated JSONContinuing the early morning post on having an XSL-like solution for JSON, where your webapp only outputs JSON files, and has attached stylesheet(s) that the browsers can use to display it as a nicely formatted HTML it intended for human audience. All solutions I outlined there needed an active change to existing technologies: custom HTTP header, or extension to JSON, but in any case they would need explicit support from browsers. <div><br /></div><div>In other words, they would never get widely adopted. </div><div><br /></div><div>But then, just as I went to sleep, it hit me that there's a solution that operates completely within the currently existing technologies. I'll call this solution "HTML encapsulated JSON". The premise is that you create a simple HTML page that has the JSON payload in its body, and has script elements that pull in the JSON-to-DOM transforming script. Something like this:</div><div><pre><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /> <head><br /> <font color="red"><script src="/carlist-json-to-html.js" type="text/javascript" /></font><br /> <link rel="stylesheet" type="text/css" href="carlist.css" /><br /> </head><br /> <body><br /> <pre> <br /> { "cars": [<br /> { "color": "red",<br /> "make": "Ford",<br /> "model": "Mustang",<br /> "year": 1986,<br /> "price": { <br /> "amount": 250,<br /> "currency": "USD"<br /> }<br /> },<br /> { "color": "yellow",<br /> "make": "Mazda",<br /> "model": "6",<br /> "type": "GT",<br /> "year": 2002,<br /> "price": { <br /> "amount": 14000,<br /> "currency": "USD"<br /> }<br /> }<br /> ],<br /> "dealer": {<br /> "name": "Honest Joe",<br /> "address": {<br /> "street": "123 7th Avenue",<br /> "city": "Dustfield"<br /> },<br /> "phone": "1-456-789789"<br /> }<br /> }<br /> </pre><br /> </body><br /></html></pre></div><br /><div>As you can see, the JSON is put into html/body/pre (using "pre" to be fully DTD conformant). A machine client should be able to easily parse it out from there. Granted, it'll need to use both an XML parser and then a JSON parser, but that shouldn't be too big deal.</div><div>But the best part is definitely that you can very easily transform this into a nicely formatted HTML, by including a script (emphasized in red) to build a DOM from the JSON extracted from the body. Actually, you can just generate a fairly naked HTML, and then use a separate CSS stylesheet (as shown above) to format the HTML for presentation! And it's all standards compliant, and works with any modern browser!</div><div>Next, I'll try to come up with typical code for a JavaScript code template that would be used for a JSON-to-DOM conversion.</div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com1tag:blogger.com,1999:blog-20425712.post-55614780430348586082008-10-08T04:49:00.008+02:002008-10-08T05:28:04.182+02:00CSS for JSONThe back-in-the-day promise of XSL stylesheets was that you could output an XML document from a HTTP request, and have it processed as-is by a machine recipient, or transformed into a pretty HTML for human viewing automatically. <div><br /></div><div>Seeing how I (and probably many others) do prefer JSON to XML nowadays for my machine-to-machine communication, I'm thinking of an equivalent for JSON. In similar vein, XSL is almost entirely replaced by CSS today, and I keep thinking that we'd need an XSL or CSS equivalent for JSON.</div><div><br /></div><div>Actually, we probably don't even need a new language for describing the transform. JavaScript would probably do just fine - read the JSON, build the DOM.</div><div><br /></div><div>The other problem, assuming we already have the language for transforming JSON to pretty formatted HTML: how would you declare a transform in a JSON document?</div><div><br /></div><div>In XML, you can use a processing instruction. In HTML, you can use the <link> element. Now, unlike XML's processing instructions, or HTML's <link> element, JSON notoriously lacks any support for any out-of-band information that isn't the actual content. Heck, it doesn't even support comments!</div><div><br /></div><div>I can see three possible ways around it:</div><div><ol><li>Declare the transform in the transport header, i.e. just slap on an "X-JSON-Stylesheet" or similar header into the HTTP response. The obvious problem is that this ties the solution to the transport.</li><li>Add it to a conventional location into the JSON data itself. I.e. have the top-level object literal have a "__metadata__" object, and put this and similar other information into it. i.e.:<pre>{ "__metadata__": { "links": [{"url": "myStyleSheet.cssjs", "type": "stylesheet"}]} ... }</pre>The obvious problems are: a) the top-level value in a JSON document ain't necessarily an object (can be an array, or even a primitive value) b) some JSON based formats won't be happy about having extra elements with magic names inside of them.</li><li>Extend JSON to add a syntactic equivalent of XML processing instructions. Honestly, I prefer this approach. Just adding single-line comment support, and then having a special prefix for the "processing instruction" comment (i.e. using a question mark, to keep it similar with XML PE) would do, I think:<br /><pre>//?stylesheet myStyleSheet.cssjs<br />{ real payload goes here ... }</pre></li></ol><div>In any case, it is up to browser vendors to get the ball rolling on this - both the declaration mechanism, and the transform language.</div><br /><div>I think this would be a great technology to have, where I could just output JSON from my web applications, and have it both consumed by software, and presented in nicely human readable form in browsers.<br /></div></div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-67026850480637560272008-09-02T17:40:00.004+02:002008-09-02T22:11:45.268+02:00Package private access in Open Source codeI recently got in a same situation three times: someone wanted to use code I wrote in an Open Source project written in Java, and they couldn't, because the class/method in question had package private ("default") access, rendering it inaccessible outside of its package.<br /><br /><ul><li>First, Charlie Nutter needs access to package-private class BeanMetaobjectProtocol in Dynalang-MOP.<br /></li><li>Next, John Arkley <a href="https://sourceforge.net/forum/message.php?msg_id=5070128">needs access</a> to package-private class AllHttpScopesHashModel in FreeMarker to help <a href="http://jira.springframework.org/browse/SPR-4962">push it into Spring</a>.<br /></li><li>Finally, Steve Yegge needs access to the package-private constructor of Context class in Rhino.<br /></li></ul>Now, you know, when the same thing hits me three times in a row in short timeframe (incidentally, all three coming from people with high geek cred), that gets me thinking: <b>What good is package-private access in an Open Source project anyway?!</b><br /><br />It's a very valid question, really. Think about it: people can see the code - it's open. People want to use the code - it's normal. And when they want to, you frustrate them by declaratively preventing them from linking their code to your open source code. They can look, but they can't touch.<div><br /></div><div>That seems wrong.<br /><div><br />Of course, you could argue for package private access' validity. Here are some arguments you could come up with:<div><br /><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-weight: bold;">Package private helps implementation hiding on a package level!</span></span> Well, duh, it does. However, if a class/method is useful to another class you wrote and that lives in the same package, it might also be useful to some <span class="Apple-style-span" style="font-style: italic; ">poor outsider schmuck too</span>! It must already conform to quite rigorous coding standards, as it will be used by some other classes, ones you wrote in the same package, so it'd better maintain state invariants and so on. Does it really make a difference if it's another class of yours, or another class of another developer, living in another package? I say: it shouldn't. If you think the class is just an auxiliary, and it's just cluttering the JavaDoc, just move it to a *.support subpackage instead (Spring does that extensively).<br /><span class="Apple-style-span" style="font-style: italic; "><br /></span></div><div><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-weight: bold;">Package private helps you hide bits you don't want to be tied down by backwards compatibility!</span></span><span class="Apple-style-span" style="font-weight: bold;"> </span>This is really a corollary of the first one. I used to be big on this one (that's probably why I got asked to loosen up access restrictions in the first place - because I used to place them there in the first place). Common wisdom is that once people start using your publicly available API, you'd better not break it on the next release. By making lots of stuff public, you increase the surface area that needs to be kept backwards compatible, right? Right, sort of.</div><div><br /></div><div>Now, how about this instead: make it public anyway, just note in a JavaDoc entry (or even better, in an annotation, say @SubjectToChange) that there's no backwards compatibility guarantee on this method. If it's an annotation, people can even have an automated tool for checking for its use before they upgrade. Hell, you can even have a @BreaksCompatibility annotation! What it boils down to is: don't treat users of your library as children and decide what's good for them. Inform them that the API is volatile, but open it up, don't close it. It's not really closed anyway, as they can see the source. You're just erecting a glass wall in front of them; they can look but they can't touch. </div><div><br /></div><div>And they'll come to bug you about it anyway. </div><div><br /></div><div>My point of view right now is that it's better to provide a suggestive hint that an API is volatile in the documentation or annotation and let anyone use them at their own risk rather than build a non-negotiable restriction into the code (as in, can't negotiate it with a compiler; you can still definitely negotiate it with <span class="Apple-style-span" style="font-style: italic;">me</span>).</div><div><br /></div><div>Also, I'm not saying either that package private access is completely inadequate for Open Source libraries. I'll admit there might be valid use cases for it, but if there are, they're very few.</div><div><br /></div><div>Now, before you'd accuse me of being a "make everything public" proponent, let me say that this reasoning doesn't apply at all to private access, and only partially applies to protected access. Let's see why:</div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">Private access </span><span class="Apple-style-span" style="">is completely justified</span><span class="Apple-style-span" style="font-weight: bold;">.</span> Let me point out one clear distinction between packages and classes: classes and instances of classes can have<span class="Apple-style-span" style="font-style: italic;"> state</span>. Packages can<span class="Apple-style-span" style="font-style: italic;"> not</span>. That's pretty much what makes the difference. Through refactorings, you can end up with methods in a class that violate its state invariants. Other methods in the class can call these methods as steps to transform the object from one valid state to another valid state, but it might be invalid in the interim. You would never expose such a method publicly. Well, you shouldn't expose it even package-privately either; that'd be sloppy programming (see my above remark about package-privately accessible methods having to be just as rigorously coded as public ones). A class (and class instance) is a unit of state encapsulation, a package is not. Hence, classes need private access.</div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">Protected</span> methods remain usable by 3rd party code, as long as it has classes that extend your base class. It mightn't be too ideal a constraint (forcing subclassing in order to access functionality), and you might rather want to design your libraries to favor composition (has-a) over subclassing (is-a) architecture. But if you must have classes intended to be subclassed, and there's functionality that's only ever used/extended/implemented by a subclass, make it protected. Especially when you have abstract protected methods that act as poor Java programmer's mixins (are intended to be called by code in the base class). Sometimes you'll allow (or downright expect) such abstract methods to violate an invariant in the object's state temporarily, as it'll be called as a step in a more complex state transition implemented by an algorithm in the base class method. In these cases, protected access is justified. But in other cases though, you might still consider making some protected methods public.</div><div><br /></div><div>In conclusion: I'm currently fairly convinced that what package private access is good for is preventing your users from linking their code to useful bits of your code for purposes you didn't anticipate up front; it's often nothing more than an unnecessary garden wall.</div></div></div>Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com1tag:blogger.com,1999:blog-20425712.post-85520813112113113222008-07-24T14:52:00.004+02:002009-04-25T21:13:15.423+02:00Undeclared, Undefined, Null in JavaScriptSo, a coworker of mine run into a situation recently where they were testing for an expression in JavaScript as:<br /><br /><code>if(obj.prop != null && obj.prop.subprop > 0) ...</code><br /><br />This basically guards you against dereferencing "subprop" if "obj.prop" is itself undefined or null. They were running into a situation where the first predicate would pass, and the second would fail. However, "obj.prop" always printed "undefined". Turns out, it actually had the string "undefined" as its value.<br /><br />Ouch. <br /><br />Anyway, said coworker pointed me to a blog entry titled <a href="http://weblogs.asp.net/bleroy/archive/2005/02/15/Three-common-mistakes-in-JavaScript-_2F00_-EcmaScript.aspx">Three common mistakes in JavaScript / EcmaScript</a>. Said blog entry says:<blockquote>if (SomeObject != null) {<br /><br />Well, in JavaScript, which is a dynamic language, something that has not been assigned to is not null, it's undefined. Undefined is different from null. Why? Don't ask me. Well, anyways, you can use typeof to explicitly check for undefined, or use other more or less clean tricks, but the best way to deal with that is probably to just rely on the type-sloppiness of JavaScript and count on it to evaluate null and undefined as false in a boolean expression, like this:<br /><br />if (SomeObject) {<br /><br />It looks uglier, but it's more robust.</blockquote><br />I have to disagree. It's not more robust. It will also catch the cases of SomeObject having numeric value of 0, or string value of empty string. Because their boolean coercion is also <tt>false</tt>. To make matters worse, the original example, using <tt>SomeObject != null</tt> actually works and is in most cases actually the most appropriate!<br /><br />See, in JavaScript, null and undefined are <i>actually equal</i> according to the <tt>==</tt> and <tt>!=</tt> operator! (ECMA-262 standard, section 11.9.3 tells us so.) In vast majority of cases, you don't care about the difference at all, so using <tt>someExpr != null</tt> is good enough. <br /><br />If you really-truly must distinguish between undefined and null, you have some options. Curiously, while there is an actual built-in language literal for the null value (namely, <tt>null</tt>), the sole value of the Null type, there is no built-in language literal for undefined, the sole value of the Undefined type. The identifier "undefined" can be assigned to, so you can't write something simple as <tt>if(x === undefined)</tt>:<br /><br /><code>var undefined = "I'm defined now";<br />var x; // he's really undefined<br />print(x === undefined); // prints false</code><br /><br />Inconvenient, huh? So, how to test for undefined? Well, the common practice found in most books and tutorials on JavaScript seems to be using the JS built-in <tt>typeof()</tt> function, but I <i>really</i> don't like it, because this is implemented by way of a string comparison:<br /><br /><code>var x;<br />print(typeof(x) == "undefined");</code><br /><br />will actually print <tt>true</tt>. But as I said, I think it's ugly.<br /><br />My solution instead relies on the fact that undefined is equal to null, but is not strictly equal to null, therefore this expression also works:<br /><br /><code>var x;<br />print(x == null && x !== null);</code><br /><br />will also print <tt>true</tt>, and it involes only two simple comparisons.<br /><br />Which brings us to the question of what is the actual difference in JavaScript between an undeclared variable, a variable with undefined value, and a variable with null value. Let's see:<br /><br /><code>var x = {}; // empty object<br />var u; // declared, but undefined<br />var n = null; // declared, defined to be null<br /><br />function isUndefined(x) { return x == null && x !== null; }<br /><br />print(isUndefined(x.x)); // prints true - access to undefined property on an object yields undefined<br />print(isUndefined(u)); // prints true - declared, but undefined value<br />print(isUndefined(n)); // prints false - the value is null, not undefined<br />print(isUndefined(z)); // runtime error -- z is undeclared</code><br /><br />So, it's an error to dereference an undeclared variable, "z" in above example (it's okay to assign to it, which creates a new global variable). It is not an error to dereference a declared variable with undefined value, "u" in above example. Its value is the undefined value. Further, access to any undefined properties on objects also result in undefined value, duh. As for null, well, null is just a value like true, or false, or 4.66920166091; it's the single value of the type Null.<br /><br />Hope this clears up the whole topic of undefined/null values (and undeclared variables) somewhat.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com13tag:blogger.com,1999:blog-20425712.post-60072098361019036992008-06-07T14:07:00.004+02:002008-06-07T14:32:31.717+02:00Objective-JSo, here's some news: people at <a href="http://280slides.com/">280 Slides</a> created a web application that allows you to build presentations in your web browser. It does look very nice, people are comparing it to Apple's Keynote application. All in all, yet another webapp out there; what's the big deal, right?<br /><br />Well, the people who created 280 Slides were previously Apple employees. 280 Slides wasn't just written in JavaScript. No. These people created something called Objective-J, which is to JavaScript as Objective-C is to C. And then they implemented part of Apple's Cocoa application framework atop of it (named it Cappuccino), and finally implemented the application atop of it.<br /><br />Now that's quite amazing.<br /><br />Dion Almaer <a href="http://ajaxian.com/archives/an-interview-with-280-north-on-objective-j-and-cappuccino">writes</a> that<br /><blockquote>Objective-J is the language that takes JavaScript and makes it Objective (as Obj-C did to C). Lots of square brackets. When the browser gets served .j files, it preprocesses them on the fly. This means that you can do things like, use standard JavaScript in places.</blockquote><br />Interesting. Objective-J will eventually be open sourced at <a href="http://objective-j.org/">objective-j.org</a>, and I'll be quite curious to see what did they do. I suspect they have a transformer from Objective-J source code to plain JavaScript (presumably itself written in JS), and then the browser's JS runtime converts the source code to JS when it downloads it. But I might be wrong.<br /><br />Then there's the interesting issue that Objective-C improved C with OO features. But what did Objective-J improve? JavaScript is extremely object-oriented to begin with, so this sounds more as if they wanted to bring the actual Objective-C flavor of OO to JavaScript instead, because that's what they're comfortable doing. They need to drive nails into a different wall now, and they'd still prefer to do it with their old hammer!<br /><br />Don't get me wrong, I'm not making fun of them. Shaping one's tools in a new environment after ones you knew and loved in a previous environment is a valid activity if you percieve it as the path that allows you to be most productive. To build a new language atop of JS and then build an application framework atop of it, and then build a very usable and visually appealing application on top of it (very cross-browser compatible too) gets you a metric shitload of geek cred in my circles. It might turn out to be a catalyst for getting a lot of similarly nice future webapps out there. It might turn out to be the next big thing for JavaScript in browser.<br /><br />I'm eagerly waiting for content to start popping up at objective-j.org, although of course the <a href="http://280slides.com/Editor/1212807849/Frameworks/Objective-J/Objective-J.js">Objective-J.js</a> can be readily inspected.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com1tag:blogger.com,1999:blog-20425712.post-86912673685971229262008-06-05T11:06:00.004+02:002008-06-05T11:24:21.265+02:00So, WebKit JS used an AST walker before?Color me flabbergasted.<br /><br />WebKit recently announced a new JavaScript interpreter, named <a href="http://webkit.org/blog/189/announcing-squirrelfish/">SquirellFish</a>, claiming it is much faster than the previous interpreter in WebKit.<br /><br />That's good and all, but in the "Why it's fast" section of the linked article, they say:<br /><blockquote>Like the interpreters for many scripting languages, WebKit’s previous JavaScript interpreter was a simple syntax tree walker.</blockquote><br />It was? Oh my... They also say that:<br /><blockquote>SquirrelFish’s bytecode engine elegantly eliminates almost all of the overhead of a tree-walking interpreter. First, a bytecode stream exactly describes the operations needed to execute a program. Compiling to bytecode implicitly strips away irrelevant grammatical structure. Second, a bytecode dispatch is a single direct memory read, followed by a single indirect branch. Therefore, executing a bytecode instruction is much faster than visiting a syntax tree node. Third, with the syntax tree gone, the interpreter no longer needs to propagate execution state between syntax tree nodes.</blockquote><br />Why, yes, indeed!<br />For the record, <a href="http://www.mozilla.org/rhino">Rhino</a> has been doing this for ages - AST is compiled to internal "JS bytecode" format that strips away grammar, and then interprets it. This works like this since, well, around the turn of the millenium. (Actually, Rhino can even kick it another notch and can also optionally compile the JS bytecode to Java bytecode, eliminating the interpreter altogether. Which bytecode then the JVM JIT compiler can further compile to machine code at its own discretion.)<br /><br />Anyway, I digress. All I wanted to say is that I'm honestly amazed that a supposedly professional implementation of JavaScript (the one shipped in WebKit before SquirellFish came along, and by consequence, shipped in Apple's Safari browser) would use an AST walking interpreter. Yeah, I know, you'll say "most scripts run once on the page, so optimization is overkill", but with AJAX this is no longer true, and apparently, the WebKit team also thinks so.<br /><br />On the positive side, they're finally moving on to a better solution, and I congratulate them on the undoubtedly hard decision to finally take the leap toward a more modern execution architecture.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com5tag:blogger.com,1999:blog-20425712.post-54878208990402935622008-05-29T19:19:00.001+02:002008-05-29T19:21:08.781+02:00"Mixed Language Environments" interviewin case you're interested, the <a href="http://blip.tv/file/939549">video interview</a> where Kresten Krab Thorup interviewed Charlie Nutter, Erik Meijer, and myself about mixed language environments on virtual machines is now online. This was shot at the JAOO conference last September.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-45569089281843257562008-04-16T17:36:00.004+02:002008-04-16T17:45:40.549+02:00Interview about RhinoFloyd Marinescu interviewed me about Rhino at the <a href="http://www.jaoo.dk">JAOO</a> conference in Aarhus, Denmark last September. You can watch the interview <a href="http://www.infoq.com/interviews/szegedi-rhino">here</a>. Yes, I know I said "scratch to itch" :-)<br /><br />I actually stepped down from the Rhino maintainer role since this interview was shot, although I do remain with the project as a committer.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-19793674799583516222008-04-09T15:03:00.005+02:002008-07-07T10:14:46.514+02:00Airport Extreme disappoints<b>UPDATE:</b> Apparently, firmware upgrade 7.3.2 fixed the disk access problems. I'm now able to use a USB-attached disk to AEBS just fine. Skype also started working fine some time ago (even before the firmware upgrade). The speed issue (not being able to exceed 8 Mbit/sec on 802.11g with all-Apple equipment) unfortunately still remains.<br /><br />I got a brand new <a href="http://www.apple.com/airportextreme/">Airport Extreme Base Station</a> (AEBS) this Friday. (<a href="http://www.kodewerk.com/">Kirk</a> hauled it for me from Las Vegas to Hungary - Apple gear costs roughly twice as much here than it does in US.) <br /><br />I already own a 250GB external HDD, so I wanted to attach it to AEBS for either file sharing or, hopefully, wireless Time Machine backups.<br /><br />(Too bad Apple <a href="http://db.tidbits.com/article/9547">officially said</a> only three days later that they don't support Time Machine backups with AEBS. Meaning, if it works for you, you're lucky, but if it doesn't, you're on your own.)<br /><br />Anyway...<br /><br />My experience is that even when Time Machine is not involved, AEBS can't handle a USB drive <i>at all</i>. Just attaching the drive to the base station will cause it to come online much more slowly (needs several minutes after plugged in). Also, whenever I wanted to mount the drive through Finder on any of the Macs in the house and transfer a file to/from it, AEBS would become inaccessible in a minute or two, then spontaneously reboot. With no drive attached, it's stable as a rock.<br /><br />Of course, you could claim that the drive is at fault. Now, the same drive works perfectly when attached to either my MacBook Pro, or to my iMac G5, both running Mac OS X 10.5.2. It was formatted and partitioned (single partition, GUID scheme, HFS+ journalled filesystem) on the iMac G5. As in, freshly reformatted and repartitioned once again in a desperate attempt to make it work with AEBS. Run Disk Utility's "Repair Disk" on it too, just in case.<br /><br />Now, when the drive is attached to either Mac and shared from it, the other Mac can mount it wirelessly and even do Time Machine backups to it, without any problems. So, you know, the drive itself seems in order. But if I connect it to the AEBS, it kills the AEBS. AEBS firmware is also upgraded to latest, 7.3.1. I wanted to reduce the clutter on my desk by moving the HDD and its wires to the AEBS and am fairly frustrated with the inability to do so.<br /><br />I repeat: the symptoms have nothing to do with Time Machine. With Time Machine off, and trying to access the drive over AEBS as a vanilla networked volume, AEBS dies in a minute or so. I suspect a firmware bug.<br /><br />And then there's the speed. <br /><br />My MacBook Pro is a first-gen Core Duo, meaning it can only use 802.11g, and can't be upgraded to use 802.11n. Still, 802.11g is 54 MBit/sec, right? Well, the fastest data transfer rate I could achieve moving data to the AEBS-attached HDD (before it crapped out) was a bit over 8 MBit/sec. On a distance of few feet between the devices. Not happy. I can understand various protocol overheads would chip off the bandwidth but I can't understand getting 14% of advertised bandwidth. Not even if it were half-duplex. <br /><br />Okay, what about Ethernet access? I tried connecting over Ethernet to see whether the AEBS crashing problem is inherent to Wi-Fi, or is also present over Ethernet (result: it is present over Ethernet too). The MacBook Pro said the connection is 1000MBit/sec - fair enough, as both it and the AEBS are supposedly Gigabit Ethernet. Both devices use speed and duplex autoselect based on the cable actually plugged in. So, with 1000MBit/sec theoretical maximum speed, what effective throughput could I get? 72MBit/sec, tops. It ain't the HDD that's slow - it's a 7200RPM drive with USB 2.0, and when connected directly to the computer it is pretty much screaming fast.<br /><br />And then there are application compatibility problems.<br /><br />My wife Kriszti speaks quite a lot with her aunt over Skype, and with AEBS she experiences much more stalled audio/video over Skype. I actually subscribe to two broadband connections: a 4MBit cable and also a 1MBit ADSL as a backup. I moved the old router to the 1MBit ADSL (which previously wasn't available over wireless, being only a backup). When Kriszti had repeated Skype problems, I told her to switch to using the old wireless router, and lo and behold Skype works okay for her again, so her Mac tends to remain connected to the old router's wireless network (so our machines aren't on the same network, which is also a source of inconveniences). So: cable ISP with old router = Skype ok; cable ISP with AEBS = Skype not okay; ADSL ISP with old router = Skype okay. There's a pattern here, although in order to be able to claim with 100% certainity that it's a problem with AEBS, I'd also need to test Skype with AEBS connected to the ADSL line which I won't do now as it'd require too much uncabling/hauling/recabling.<br /><br />So, we have a base station that crashes when you try to use an USB HDD with it, with disappointing speed figures, and apparently also causes problems for Skype traffic. The only really good point is that contrary to the old taiwanese no-name router I replaced, it has a better range and implements WPA/WPA2 in a manner that Windows laptops can also understand; both of these don't really mean anything to me, but it certainly makes the nice girl next door (who we give free Internet access in exchange for occasionally babysitting our kids) lot happier.<br /><br />All in all, a disappointment.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com8tag:blogger.com,1999:blog-20425712.post-78597704251747600492008-03-21T11:33:00.004+01:002008-03-21T12:26:29.904+01:00Xstream with HibernatePeople have been asking in the comments to <a href="http://constc.blogspot.com/2007/05/xstream.html">my post on XStream</a> about how to properly integrate Hibernate with XStream, as there are few pieces of puzzle that don't necessarily fit together perfectly. I answered in the comments, but Blogger annoyingly doesn't allow a lot of formatting in comments, so I decided to write a separate follow-up post; here it goes.<br /><ul><li>First of all, I use Hibernate 2. I know, it's old, but it does the work and I won't fix it unless it is broken. I expect most of the advice will also apply to Hibernate 3.</li><br /><li>I'm aliasing all classes using <code>XStream.alias()</code>. Reason being that on the server side, some data model classes are actually subclassed for additional (although non-Hibernate) related functionality. You might or might not need this.</li><br /><li>This is however essential: We need to ensure that XStream will treat Hibernate lists, sets, and maps as Java lists, sets, and maps. I believe this is what helps avoid the infamous "com.thoughtworks.xstream.converters.ConversionException: Cannot handle CGLIB enhanced proxies with multiple callbacks..." problem. There are three things that need to be done:<ul><li>use <code>Xstream.addDefaultImplementation()</code> to tell XStream to treat all Hibernate-enhanced collection classes as plain Java collections:<pre>xstream.addDefaultImplementation(<br /> net.sf.hibernate.collection.List.class, java.util.List.class);<br />xstream.addDefaultImplementation(<br /> net.sf.hibernate.collection.Map.class, java.util.Map.class);<br />xstream.addDefaultImplementation(<br /> net.sf.hibernate.collection.Set.class, java.util.Set.class);</pre></li><br /><li>Finally, in order for XStream to actually handle these collections I needed to define and register some custom converters that are able to handle Hibernate collections as Java collections:<pre>Mapper mapper = xstream.getMapper();<br />xstream.registerConverter(new HibernateCollectionConverter(mapper));<br />xstream.registerConverter(new HibernateMapConverter(mapper));</pre>These custom converter classes are rather trivial, here are their definitions. All they really do is extend the XStream built-in collection and map converters, and declare their ability to handle Hibernate lists, sets, and maps:<pre>import net.sf.hibernate.collection.List;<br />import net.sf.hibernate.collection.Set;<br />import com.thoughtworks.xstream.converters.collections.CollectionConverter;<br />import com.thoughtworks.xstream.mapper.Mapper;<br /><br />class HibernateCollectionConverter extends CollectionConverter {<br /> HibernateCollectionConverter(Mapper mapper) {<br /> super(mapper);<br /> }<br /><br /> public boolean canConvert(Class type) {<br /> return super.canConvert(type) || type == List.class || type == Set.class; <br /> }<br />}</pre>and<pre>import net.sf.hibernate.collection.Map;<br />import com.thoughtworks.xstream.converters.collections.MapConverter;<br />import com.thoughtworks.xstream.mapper.Mapper;<br /><br />class HibernateMapConverter extends MapConverter {<br /><br /> HibernateMapConverter(Mapper mapper) {<br /> super(mapper);<br /> }<br /><br /> public boolean canConvert(Class type) {<br /> return super.canConvert(type) || type == Map.class; <br /> }<br />}</pre></li></ul></li></ul><br /><br />That's all I did and it eliminated all of my Hibernate+XStream problems - hope it will also help you.Attila Szegedihttp://www.blogger.com/profile/11586966395114113526noreply@blogger.com12tag:blogger.com,1999:blog-20425712.post-30089207562188411972008-03-20T13:50:00.003+01:002008-03-20T14:05:37.069+01:00Attributes and itemsSo, here I am trying to further my <a href="http://dynalang.sourceforge.net/">metaobject protocol library</a>. I'm now in the eat-my-own-dog-food phase of sorts, as - after having written a MOP for POJOs, I'm trying to write actual MOPs for some dynamic language implementations, most notably, Jython and JRuby. And pretty soon, I hit an obvious design problem (which is okay, really - this is still an exercise in exploring the right approach). Namely, lots of languages actually have two namespaces when it comes to accessing data belonging to an object. I'll refer to one of them as "attributes" (as that's what they're called in both Ruby and Python) and the other are "items", which are elements of some container object. All objects have attributes, but only some objects (containers) have items. Some languages don't make a distinction, most notably, JavaScript. In JavaScript, all objects are containers and they only have items (and an item can be a function, in which case it functions as a method on the object). Other languages (Ruby, Python) will distinguish between the two; the containers are arrays/lists and hashes/dictionaries/maps. As a matter of fact, it helps thinking of Java as having the distinction - JavaBeans properties are the attributes, and arrays, Maps, and Lists will have items.<br /><br />I'd like to think that most people's mental model of objects actually distinguishes the two.<br /><br />Now, to make matters a bit more complicated, in lots of languages the container API is actually just a syntactic sugar. Give an object a [] and a []= method, and it's a container in Ruby! Give it __getitem__, __setitem__, and few others, and it's a container in Python! Honestly, this is okay - as a byproduct of duck typing, one shouldn't expect to there be any sort of an explicit declaration, right?<br /><br />For ordered containers, most languages will also make it possible to manipulate subranges as well.<br /><br />Bottom line is, I feel this is a big deal to solve in interoperable manner, as the raison d'être of this library is to allow interoperability between programs written in different languages within a single JVM; I imagine in most cases the programs will pass complex data structures built out of lists and dictionaries to one another, so it feels... essential to get this right. It also feels like something that can rightfully belong in a generic MOP as most languages do have the concept of ordered sequences and associative arrays. Of course, I might also be wrong here; it is also an essential goal to not end up with a baroque specification that contains everything plus the kitchen sink.<br /><br />So, here am I wondering whether this is something that can be made sufficiently unified across the languages to the point that if a Ruby program is given a Python dictionary, and it calls []= on it, it actually ends up being translated into a __getitem__ call. The goal seems worthwhile, and is certainly possible but I'm not entirely sure how much of an effort will it take. There's only one way to find out though :-)Attila Szegedihttp://www.blogger.com/profile/11586966395114113526noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-75259656599706847232008-03-06T11:05:00.002+01:002008-03-06T11:07:45.474+01:00Running Half-Life 2 natively on Mac OS XI run Half-Life 2 natively on Mac OS X yesterday evening, in the same configuration I run it on Mac: 1280x1024 resolution, 8x anisotropic filtering, High Dynamic Range bloom rendering, all graphic settings set to "High". It run like charm. I'm impressed. Half-Life 2 was the only reason until today to keep a Windows XP partition on my Mac, and use Boot Camp. But it was inconvenient, the rebooting, even if I did it about once a week on a sunday afternoon for few hours of gameplay.<br /><br />The magic behind this is called CrossOver Gaming.<br /><br />Yesterday, I got an e-mail from Codeweavers where they announced <a href="http://www.codeweavers.com/beta/crossover/">CrossOver Gaming Beta</a>. For those unfamiliar, CrossOver is a <a href="http://www.winehq.org">Wine</a>-based Win32 API compatibility layer for Mac and Linux, allowing Windows application binaries to run natively under these operating systems on machines with x86 CPU architecture. I did test drive CrossOver earlier (that's why I was on their e-mail list), but it left me unexcited, not by its own fault, but really because I had no need for any Windows applications at the time.<br /><br />I was intrigued by the CrossOver Gaming product though, as it does answer a need I have, namely playing a game I own without needing a reboot (VMWare fusion doesn't run Half-Life 2). Or needing a Windows license. The difference between "regular" CrossOver and CrossOver Gaming is that Gaming will see more frequent releases, will be more bleeding edge, basically less conservative as to what goes into it and frequently updated to accommodate game compatibility problems. You won't necessarily want that from a software that you use to run, say, your Windows-only accounting package, but for games, this model makes perfect sense.<br /><br />Well, it works pretty much as advertised on the box. It knows of a bunch of "supported" applications, one of them being Steam (and all games available through it). It will install a surrogate HTML library (lacking Internet Explorer, right, there's no Microsoft-shipped mshtml.dll in the system) that allows Steam's built-in store browser to work, then download and install MSXML redistributables and Steam itself. Steam then launched, I logged into my account, downloaded Half-Life 2: Episode One, crossed fingers, and launched it.<br /><br />It runs just as it did under Windows, and I think I couldn't say anything more praiseworthy about this CrossOver product, even in its beta. I'm totally buying this when it comes out.<br /><br />I'll briefly mention that there is another player in this space, Transgaming, but unlike Codeweavers, they forked off Wine and aren't donating code back upstream to Wine, so if you need to choose, it seems as if supporting Codeweavers seems like a better option from the moral point of view, as Codeweavers do donate back to Wine. Also, Transgaming's Cedega product doesn't allow users running unaltered Windows games on Mac, only on Linux. They don't offer Cedega for Mac; they have Cider, but that's not a runtime but rather a library that developers need to link against to produce Mac-runnable versions of their games written against the Win32 API. So in reality, CrossOver is the only solution for running a Windows game natively under Mac OS X. Fortunately, it seems to be a good one.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com5tag:blogger.com,1999:blog-20425712.post-75148752092984391802008-03-04T17:20:00.003+01:002008-03-04T18:14:00.431+01:00While waiting for the fourth season...I avoid most forms of filmed science fiction, reason being that most attempts underachieve badly compared to written works. The quality of written sci-fi is rarely matched or even approximated by movies and TV series. Notable exceptions are few, and the finest filmed sci-fi for the last few years is without a doubt the reimagined Battlestar Galactica (Firefly would come in close second). The final, fourth season starts in April, and I can hardly wait for it to start. In the meantime, there's a great two part interview with the show's creators about <a href="http://www.concurringopinions.com/archives/2008/03/battlestar_gala_4.html">legal system, torture, and morality</a> (part one), as well as <a href="http://www.concurringopinions.com/archives/2008/03/battlestar_gala_5.html">economy and politics</a> (part two) in the series.<br /><br />If that weren't enough, here's a gorgeous <a href="http://www.flickr.com/photos/34527294@N00/2177726792/">Battlestar Galactica reinterpretation of Last Supper</a> on Flickr.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-89860234913708193562008-02-22T11:13:00.004+01:002008-02-22T11:22:44.439+01:00Microsoft Open SourceI was surprised to discover today that Microsoft has a hosting site for Open Source projects (analogous to, say, SourceForge.net or GNU Savannah): witness <a href="http://www.codeplex.com/">Codeplex</a>. To my further surprise, there's also an Open Source community site at Microsoft, named <a href="http://port25.technet.com/">Port 25</a>. I haven't got time to investigate either of them more deeply yet, but plan to do so in future. This is intriguing.<br /><br />(Found them both following Microsoft's <a href="http://www.microsoft.com/opensource/interop/default.mspx">Open Source Interoperability Initiative FAQ</a>.)<br /><br />Mind you, I was aware earlier that Microsoft has software released under OSI-approved licenses; there are more than few Microsoft-backed projects hosted on SourceForge.net (or did they move to Codeplex since? Hm...). What I was not aware of, and what I believe is a big deal is that Microsoft is now providing its own hosted infrastructure for Open Source project hosting and community discussion.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0tag:blogger.com,1999:blog-20425712.post-60226271421918621762008-02-21T22:05:00.003+01:002008-02-21T23:21:14.806+01:00Reap What You SowYou won't catch me writing about politics too often, but I need to express my view on the declaration of independence in Kosovo. Actually, I'll mostly bother you with some of my family history, but the two are, for better or worse, somewhat intertwined.<br /><br />As you might or might not know, I grew up on the territory of former Yugoslavia, in a small village in northeast Croatia, bordering on Serbia. My family lived in Croatia, but we had relatives in Serbia as well. My family's roots are from the Serbian Vojvodina province, which belonged to Hungary under name Vajdaság until it was annexed into the Serbian-Croatian-Slovenian Kingdom (forerunner of Yugoslavia) as part of the breakup operation of the Austro-Hungarian empire after World War I. (In a way, Serbia then gained a province in north not unlike to how these days it lost one in south.) As such, Vajdaság has a high (alas, dwindling) Hungarian population, and I come from this ethnicity.<br /><br />I never felt any drawback growing up a non-croatian in Croatia. Nobody in Croatia ever as much as made a remark about me being ethnic minority. Not so in Serbia. Whenever I visited my grandmother in Novi Sad (Serbia) during summer vacation, I experienced strange things. She'd hush me to not speak Hungarian on the street or on the bus. She did neither. The name plate on her door had her name spelt in Serbian (serbian "Jelisaveta" instead of hungarian "Erzsébet" for "Elizabeth"). It was clear you can get into trouble for being different. My whole experience of Serbia was - as far as I can remember - that people there are highly xenophobic and intolerant of their ethnic minorities.<br /><br />Then came 1991 and the breakup of Yugoslavia. The Croatian region I lived in was overrun by serbian paramilitary troops with full backing by Milosevic's serbian state army. They ruthlessly drove away or slaughtered nonserbian population from the territories they occupied. My family fled with one car trunk worth of belongings when these thugs were approaching. We lived next to an improvised Croatian police station, and we later learned we were targetted as "Croatian collaborators" by paramilitaries because we were on cordial terms with the police officers. They broke into our home on a night after they occupied the region. I have no doubts as to our fate if they found us there.<br /><br />Mind you, at the time police officers with handguns were the only armed force the just-born Croatian Republic could stack against the Serbian-controlled "People's Army of Yugoslavia", the biggest and most heavily armed force in Balkans in 1991. They had all the chance of a snowflake in hell to defend our homes against the occupators.<br /><br />While Serbia was significant territorial influence in the breakup of Yugoslavia, it clamped down even harder on its own ethnic minorities, trying to prevent further loss of grip on its remaining territories with the oppression in both Vajdaság and Kosovo growing year after year under Milosevic regime. It culminated when Serbia attempted to eradicate the Albanian minority (minority when viewed against overall population of Serbia, but a 95% majority in Kosovo) in 1999 using its military. This led to the well known NATO intervention when Serbia was bombed by US and its allies until its warlords lost the backing of the population and were overthrown in a revolution.<br /><br />But the damage has been done. The Serbian state consistently over several decades mistreated and oppressed its ethnic minorities. After what they experienced under Serbian regime for decades, ethnic Albanians of Kosovo wouldn't trust'em as far as they can throw'em. The Serbian state is reaping what they sow now. <br /><br />It's ironic, but I do actually believe that the recently elected Serbian government might actually be a modern european democratic government that would treat its minorities as a modern european democracy should. (Provided they don't <a href="http://en.wikipedia.org/wiki/Zoran_Đinđić_assassination">assassinate their prime minister <i>again</i></a> for being too European...)<br /><br />But it's simply too late.<br /><br />There was a huge demonstration this evening in Belgrade. There were atrocities. Embassies and banks were burned. The prime minister spoke to the crowd, fueling it, and the police didn't stop the hooligans. It's sad how they still lay the blame everyone for the situation except themselves, and their decades of hostile politics. I have no illusions this will change soon. I have no doubts that the long oppressed Albanian people of Kosovo are better off in an independent state. They finally will have the chance to bring prosperity to the long neglected region. The region will finally have a government that feels it belongs to the land. As far as I remember, Kosovo was always extremely poor. Serbians have strong emotional ties to the region because Kosovo is the historical site of birth of Serbian state and church, but aside from that, Serbia was a very lousy custodian of the region, not bothering developing it, or helping it develop, or even just not actively hindering any economic progress in it in recent history.<br /><br />My father packed his two children and wife into his car on 20th August of 1991, and pressed the pedal to the metal until we crossed the border to escape certain death from Serbian paramilitary thugs. Dad spent the rest of his life in exile. Even after our former Croatian homeland was liberated, the six years of Serbian rule set it back economically, infrastructurally, and most importantly socially for decades - it still didn't recover as most young people, including me, departed the region and didn't go back, decimating the society's renewal potential. There was simply no place to go back to, as that land was no more the same land we left. So Dad didn't return either although I know his heart ached for an alternate reality where all of this didn't happen, the peaceful continuation of days of old, something that is not ours to experience in our lifetimes, taken away from us by force by aggressive neighbors' selfish geopolitical interests. I wish Dad was still alive to witness how those same aggressive neighbors are now in pain too; while it doesn't cure our wounds, he would certainly find some poetic justice in it. <br /><br />Schadenfreude? Damn well yes, we're entitled to it.Attila Szegedihttp://www.blogger.com/profile/08179252447170860637noreply@blogger.com0