I was having a discussion with a friend of mine not too long ago debating the merits of dynamic languages. My friend believes that type-safety is a top priority and that a language that does not do compile-time (or for an interpreted language, parse-time I suppose) type checking is a disaster waiting to happen.
This is completely correct. Unless you're doing something trivial like a script to resize/rotate the pictures from your digital camera, a dynamically-typed language will have problems when the app gets more complex. For example, suppose while refactoring you want to change the parameter list of a function for some reason. Maybe some parameter is no longer needed, who knows. In a statically typed language, this is not a huge issue because the compiler will pick up all the places that the function is called and tell you if there are problems. Not so in a dynamically typed language, instead you have to actually execute the code. If your program is highly interactive, this will lead to problems because you will manually have to execute each version and catch the error at run-time. And if you forget to check something? Well, your users will find it.
Here is where the standard response comes in from dynamic-typing enthusiasts: testing suites. All non-trivial programs should have testing suites, regardless of the language. No programming language, even Haskell with its crazy type system, will save you from the requirement of clarifying your ideas - at least you better hope so, or you're out of a job. A type-checker can tell you if the types you are throwing around make sense, but they don't check whether the code is working the way it is supposed to. For example, one time I wrote a 3D vector class in C++. I made a typo in the cross product function and put a - instead of a +. Passed the type check just fine, but when the shading on objects was looking horribly fucked up, I had absolutely no idea what was going on. This kind of bug can be easily avoided by a simple unit test.
A good unit testing suite will help a lot, and catch many of the errors that would normally be caught by a compiler (like type-errors or spelling mistakes) while at the same time verifying the behaviour of your code.
Unfortunately, the type-safety depends on the quality of your unit tests. It is prone to human error. It is this fact that I believe a program written in a dynamically-typed language can never be as type-safe as one in a statically-typed one.
You could work around this by checking the types of the arguments at the start of every function. However this is paranoid. If you're doing this, why don't you just switch to a statically-typed language which will do this automatically, more quickly, and with less work for you?
So we come to a trade-off. Many programmers discover quite quickly that a dynamically-typed language will let you get code out the door much more quickly than with a statically-typed one. I've been mucking around with a gaming library in Python (I'll post about this another time) and I'm finding it is much easier to get simple stuff done than I ever did with C++. In fact it is so simple that there is no need for adding scripting languages on top, or config files, or all that. I can just write the stuff in Python. I've had similar experiences with Ruby.
But to get these benefits, you must accept the fact that you will not be having 100% type-safety. There may have to write more tests than you would have.
Is it worth it? Sacrificing type-safety for faster development times? Well, it depends. In fact, you may not always have faster development times. I believe that there is a threshold at some point where a dynamically-typed language will have slower development times than a statically-typed one. This threshold is dependent on many factors - how good the design is, how good the programmers are, how many programmers there are, how big the project is, how quickly requirements change, etc.
Finally one last thing to note is that statically-typed languages are easier to optimize for speed than dynamically-typed languages. In a statically-typed language, the compiler knows without a doubt the type of a variable, and can sometimes drop the type information from the resulting machine/byte code. The compiler knows at compile-time whether an object has a certain method or not, so there is no need to check at run-time, or even keep track of what methods an object really has. A lot of this is why C and C++ are still faster than well, anything else (of course there are other factors, like how most dynamically-typed languages these days are interpreted).
Apr 28, 2009
Apr 26, 2009
Adventures in Python
Although over the last few years I've dabbled in Python a little, I've never really sat down and made an actual program with it. I made a little web app for Google's app engine some time ago, however I don't really consider it a lot of coding and hardly enough experience to say that I really know the language.
I have the same problem that most Ruby people seem to have: we really see no reason to learn Python. There is not really any objective benefit that it gives. Both Ruby and Python offer faster development times compared to languages like C++ or Java (although it would be interesting to see which of the two languages would be faster, I don't really know). They're both interpreted (and therefore, slow and memory-intensive). They both have good-sized followings and plenty of free software available for them. So I don't really know any good reason to switch between the two - I know many Python people say the same about Ruby.
For the record, the thing I'm making now is a little game. You can check it out here if you like, it is a little Diablo-style game where you go around stabbing monsters. Hopefully it will evolve into something cooler at some point, but for now it is pretty limited.
Anyway I'll give my first impressions of the language, from the perspective of someone who has lots of experience with other Perl-derived languages (namely Ruby and PHP). Keep in mind that this is all subjective and you are more than welcome to disagree - although I think most of the people who read this blog are Ruby people anyway so I doubt too many feelings will be hurt by this one.
Things I like so far:
One thing I've really learned here is that I haven't really done much with Ruby besides web apps, which in terms of complexity really aren't that deep - I don't know if "deep" is the right word here, but it seems like that when you write a web app there are fewer levels of moving parts than in an app like a game. I wonder what it would be like if I rewrote this app in Ruby, if it would have taken as long to make and if it would be more maintainable or not - probably yes since I actually know Ruby a lot better, but maybe not.
I have the same problem that most Ruby people seem to have: we really see no reason to learn Python. There is not really any objective benefit that it gives. Both Ruby and Python offer faster development times compared to languages like C++ or Java (although it would be interesting to see which of the two languages would be faster, I don't really know). They're both interpreted (and therefore, slow and memory-intensive). They both have good-sized followings and plenty of free software available for them. So I don't really know any good reason to switch between the two - I know many Python people say the same about Ruby.
For the record, the thing I'm making now is a little game. You can check it out here if you like, it is a little Diablo-style game where you go around stabbing monsters. Hopefully it will evolve into something cooler at some point, but for now it is pretty limited.
Anyway I'll give my first impressions of the language, from the perspective of someone who has lots of experience with other Perl-derived languages (namely Ruby and PHP). Keep in mind that this is all subjective and you are more than welcome to disagree - although I think most of the people who read this blog are Ruby people anyway so I doubt too many feelings will be hurt by this one.
Things I like so far:
- Whitespace - I love it. At first I felt as though my code were naked without end keywords or closing brackets, however after a while it becomes enjoyable. I find it makes the code much more clean, and you don't have to worry about whether you have too many or too few ends, just make the indentation work (which I would have done anyway). I do tend to forget to put the colon at the end, but that's probably just because I'm still new to the game.
- Modularity - At it was a little annoying to have to import the modules in every single file that use it or to have to specify "from ... import ...", but in the long run it is a better way to go in that it helps break down coupling between files. I'm thinking I should take this back to Ruby and design things in this way.
- List Comprehensions - they're nice and precise and do things that in Ruby you'd have to use zips, maps and selects for (unless of course my Ruby-fu is not amazing and there are similar things in Ruby that I don't know about, which is likely).
- Object-Orientation - it feels a little...clunky. I have to put self everywhere. While it isn't a real complaint, it is a bit annoying and does clutter things up a fair bit. I find Ruby's sigil notation to be cleaner. Also one of the things from PHP that I really hated was having to declare something as global, it is here too. Don't like it.
static vs. class methods? Not sure why. It also seems like I have to jump through hoops to create these things. - Naming conventions: __ clutters up the screen, I feel like I'm writing C again: typedef struct _name { ...
I finddef+()
oroperator+()
to be much more readable. But then again, it's what I'm used to.
Finally, certain things like lists not having a length() method and instead you call the global method len() seems to be a little inconsistent to me. Same goes for various things like map, filter, etc. - It's very imperative - This may not be a bad thing. Some people like this kind of programming, they say it's old school. Feels like real programming again instead of plugging libraries/gems into one another and suddenly having an application.
For me, I've gotten used to using functional-esque programming with Ruby and to a lesser extent Javascript with jQuery, so coming to Python seems like I'm more limited in how I can express what I want to write. But whatever.
One thing I've really learned here is that I haven't really done much with Ruby besides web apps, which in terms of complexity really aren't that deep - I don't know if "deep" is the right word here, but it seems like that when you write a web app there are fewer levels of moving parts than in an app like a game. I wonder what it would be like if I rewrote this app in Ruby, if it would have taken as long to make and if it would be more maintainable or not - probably yes since I actually know Ruby a lot better, but maybe not.
Apr 25, 2009
pygame
In my latest project I've been messing around with pygame, which is a Python wrapper and extension for the SDL media library. It is great because it adds all sorts of object-oriented stuff on top of the original SDL functionality, without really sacrificing anything (at least as far as I've noticed).
You may wonder why I chose Python for writing a game over C or C++. Well to be honest, it was mainly just to learn Python, and Python just so happened to have this gaming library available. However the more I use it, I think it might actually be a viable strategy for simpler games. If something somewhere is going too slow or using too much memory, you can always just write a part in C++ using Boost.Python and import it in - I'll be honest, I haven't tried Boost.Python so I don't know if it is as seamless as they claim, there could be more on this later.
Python offers much faster development time over C++, I noticed this right away. I can add things very easily that weren't originally in the plan. If I have a bunch of classes with similar functionality, I can quickly refactor them to inherit from a base class which provides the shared functionality - while I can probably do this in C++ too, I'd have to go through the code everywhere and use references/pointers to base class objects instead of the original - bit of a pain.
You may also now wonder why I didn't write it in Ruby. Well, like I said, wanted to learn Python. At this point, I still want to learn Python - I haven't been turned off it yet like I was with Haskell or Scala either (not sure why I was turned off of these, maybe because I'm too dumb or entrenched in my ways to really grasp their more advanced concepts). Also, Ruby is nice and all, but it's what I use at work. I'm happy about that, I'd rather be doing Ruby than PHP or Java, but I'd like a little bit of change when I go home and do my own coding. Choosing another language helps satisfy that desire for change.
You may wonder why I chose Python for writing a game over C or C++. Well to be honest, it was mainly just to learn Python, and Python just so happened to have this gaming library available. However the more I use it, I think it might actually be a viable strategy for simpler games. If something somewhere is going too slow or using too much memory, you can always just write a part in C++ using Boost.Python and import it in - I'll be honest, I haven't tried Boost.Python so I don't know if it is as seamless as they claim, there could be more on this later.
Python offers much faster development time over C++, I noticed this right away. I can add things very easily that weren't originally in the plan. If I have a bunch of classes with similar functionality, I can quickly refactor them to inherit from a base class which provides the shared functionality - while I can probably do this in C++ too, I'd have to go through the code everywhere and use references/pointers to base class objects instead of the original - bit of a pain.
You may also now wonder why I didn't write it in Ruby. Well, like I said, wanted to learn Python. At this point, I still want to learn Python - I haven't been turned off it yet like I was with Haskell or Scala either (not sure why I was turned off of these, maybe because I'm too dumb or entrenched in my ways to really grasp their more advanced concepts). Also, Ruby is nice and all, but it's what I use at work. I'm happy about that, I'd rather be doing Ruby than PHP or Java, but I'd like a little bit of change when I go home and do my own coding. Choosing another language helps satisfy that desire for change.
Apr 24, 2009
My Problems with Twitter
While many people claim that Twitter ate their blog, I can't really say it has eaten mine - while I have been much more quiet lately than 6 months ago, I think it more due to lack of enthusiasm/inspiration/commitment than anything else. I have several reasons why I'm not a huge fan of Twitter for "microblogging", at least compared to a lot of the other people who are on it. Don't get me wrong, it is great for small little things, but I don't think it is a great substitute for an actual blog.
Why I don't like it:
Why I don't like it:
- Lack of expressiveness - while some people could say that Twitter makes them more efficient in saying what they want to say, I think shortening your message to 140 characters really limits what you can say. A lot of the time I have stuff to say that is too short to make into a real blog entry, but I'd like to talk about in more depth than a simple tweet (perhaps I should lower my minimum blog entry length, but for some reason I don't like to write really short ones. Not sure why).
- The Chaos - It is completely chaotic. I forget to check Twitter every day. In fact, sometimes a week goes by. What happens when I finally do remember to check is I sign on and there's absolutely no way I can see what people have said except for in the last few hours. Fortunately the good response to this was to just stop following a whole bunch of people who just spammed out tweets like there's no tomorrow, so now my timeline shows probably a day or two worth of tweets - though still no good if I haven't checked it in a week. In fact, just today I found out that several weeks ago someone sent me a "message" - not a real direct message mind you, but an @robbrit message - with a link to a cool book and I just got it today because I was messing around the Twitter Search API. If you're reading this, thanks! It is definitely interesting!
- Level of Satisfaction - This somewhat relates to my first point, but is a bit different. I find that tweeting does not give the level of satisfaction as a good blog entry (I find it odd that I'm saying this, since I tend to tweet more than I blog these days) mainly because with a blog entry I sit down and write something that people may actually care about. While shouting out random things to my followers on Twitter may be temporarily gratifying (just got to work! sitting in my chair now!), there is a deeper feeling of satisfaction when you receive a comment on a year-old article saying how you helped someone out so much, or when someone links you on Reddit because they like what you've written - although there is an awful lot of negative attention from sites like those that really bugs me, but I suppose it is unavoidable on the Internet.
Apr 23, 2009
Jaunty and RMagick
If you're doing Ruby development under the Jaunty and you're using RMagick, make sure that after you upgrade to reinstall the libmagickwand-dev package, and then reinstall the RMagick gem:
UPDATE(Apr. 27, 2010): The latest version of RMagick does not work with the most recent version of Imagemagick in the Ubuntu repository. To install the version of RMagick that does work, you need to use version 2.11:
sudo apt-get install libmagickwand-devI can imagine there may be issues with other languages too, it seems like Jaunty replaces/upgrades some ImageMagick libraries, so you'll have to patch it up after you upgrade.
sudo gem uninstall rmagick
sudo gem install rmagick --no-ri --no-rdoc
UPDATE(Apr. 27, 2010): The latest version of RMagick does not work with the most recent version of Imagemagick in the Ubuntu repository. To install the version of RMagick that does work, you need to use version 2.11:
sudo gem install rmagick --no-ri --no-rdoc --version=2.11
Apr 15, 2009
Installing Steam in Ubuntu
If you're like me and you enjoy video games, one thing you'll miss about Linux is the supreme lack of games for Linux (the only reason I still have a Windows partition is for games). Of course, there are a few good open-source games out there, and some games work beautifully under wine.
Turns out, so does Steam. The fonts are a little messed up, and if you run in a virtual desktop like I usually do (Compiz Fusion has issues with full-screen apps and I'm too lazy to turn it off) then the system tray is a little annoying, but whatever.
To install:
1) Download Steam from steampowered.com.
2) (UPDATE 12/12/2009: Installing wine is a bit tricky in Ubuntu 9.10, see my post for installation instructions.) Install Wine, if you don't have it installed. After it is installed or if you haven't run it before, run it real quick in a terminal (Applications->Accessories->Terminal) by typing "wine" and pressing Enter. This creates the wine folder where your settings go, it's important.
3) Put it in a Wine folder. If you don't have a wine folder, create a folder on your desktop called Wine and then run this command in a terminal :
4) Follow the Steam installation instructions. Usually this means you have to click Next a bunch of times.
There, you should now have Steam installed. Keep in mind that not all games work in Wine. You'll have to try different ones (that's what I'm going to do) and see what works and what doesn't, I'll try to post on here if I have to jump through a few hoops to get certain games working properly.
Turns out, so does Steam. The fonts are a little messed up, and if you run in a virtual desktop like I usually do (Compiz Fusion has issues with full-screen apps and I'm too lazy to turn it off) then the system tray is a little annoying, but whatever.
To install:
1) Download Steam from steampowered.com.
2) (UPDATE 12/12/2009: Installing wine is a bit tricky in Ubuntu 9.10, see my post for installation instructions.) Install Wine, if you don't have it installed. After it is installed or if you haven't run it before, run it real quick in a terminal (Applications->Accessories->Terminal) by typing "wine" and pressing Enter. This creates the wine folder where your settings go, it's important.
3) Put it in a Wine folder. If you don't have a wine folder, create a folder on your desktop called Wine and then run this command in a terminal :
ln -s ~/.wine/dosdevices/z: ~/Desktop/WinePut the Steam installer in that folder, open the folder and run the installer. It should work fine. If double-clicking it doesn't work you, right click on the file and go to "Open with Other Application". Click on "Use a custom command" and in the box that appears type msiexec. Then press Open.
4) Follow the Steam installation instructions. Usually this means you have to click Next a bunch of times.
There, you should now have Steam installed. Keep in mind that not all games work in Wine. You'll have to try different ones (that's what I'm going to do) and see what works and what doesn't, I'll try to post on here if I have to jump through a few hoops to get certain games working properly.
Apr 14, 2009
Accents in Vim
I've been working with localization for work lately, and I've had to put a lot of accents in for French. This is not a huge deal since I have this thing on my desktop PC (forgot what it is called) that lets you put RSuper+accent+key to type an accent (RSuper being the right Windows key) - so RSuper+'+e gives you é.
However on my laptop I don't have this set up and having forgotten what it is called, I can't look it up. Never fear though, Vim has a shortcut key for accents. While in insert mode (or in any mode where you can type a character to be outputted, like after pressing 'r') hit Ctrl+k, the letter to accent and then the accent. So to type a é you hit Ctrl+k, then e, then '. Nice and easy! However for some reason they don't do others as easily, è is e then !, and some others are weird like that too. Oh well.
However on my laptop I don't have this set up and having forgotten what it is called, I can't look it up. Never fear though, Vim has a shortcut key for accents. While in insert mode (or in any mode where you can type a character to be outputted, like after pressing 'r') hit Ctrl+k, the letter to accent and then the accent. So to type a é you hit Ctrl+k, then e, then '. Nice and easy! However for some reason they don't do others as easily, è is e then !, and some others are weird like that too. Oh well.
Apr 13, 2009
Hungarian Notation in Ruby?
Way back when I was first learning to program, I was quickly introduced to the Win32 C API, which uses a lot of Hungarian notation on the variable names. This got really annoying really quickly, especially back then when there was a difference between a "long pointer" and a "short pointer", you'd get stuff like "g_lpasz_..." which means "long pointer to an array of zero-terminated strings, which happens to be a global variable". It can get nastier.
Eventually I dropped this, because in C/C++ you explicitly declare the type of a variable anyway, and the IDE that I used at the time (Visual Studio) would display the type anyway. It was both redundant and slightly verbose, so it didn't really come as a surprise that when I came to Java in university and saw that it did not use this notation that maybe it was worth ditching (it's one of the few things that Java ditched from C++ that I actually agreed with). So now I don't use it when I'm programming C++.
Most of the time these days, I'm not programming in C++. While I still like the language - probably because I haven't found a language that does what it does well better, namely execution speed with OOP/generics - most of the projects I seem to do are better suited to Ruby - there are probably better languages to use for some of the things I do (OORegress would probably be better off in Scala since it does number crunching) but whatever.
As my apps and web apps get more complex however, I'm thinking some sort of very basic type system would be in order. Since in Ruby you can never be really certain what type a variable is (I've been bitten in the ass in Rails by Hash vs. HashWithIndifferentAccess), having some sort of hint to other programmers what type the variable should be would be quite helpful. Just a thought.
Like most things, it is best to use it sparingly. If your Hungarian notation portion has more than say 5 characters in it, it's getting a little long. Plus since in Ruby a parameter may have more than one expected type - in Rails, ActiveRecord::Base#find can take an integer or a symbol for the first parameter - and lists can be heterogeneous there are situations where the system may not be comprehensive enough for what you need. However for 90% of the times, I think it would be an improvement.
Eventually I dropped this, because in C/C++ you explicitly declare the type of a variable anyway, and the IDE that I used at the time (Visual Studio) would display the type anyway. It was both redundant and slightly verbose, so it didn't really come as a surprise that when I came to Java in university and saw that it did not use this notation that maybe it was worth ditching (it's one of the few things that Java ditched from C++ that I actually agreed with). So now I don't use it when I'm programming C++.
Most of the time these days, I'm not programming in C++. While I still like the language - probably because I haven't found a language that does what it does well better, namely execution speed with OOP/generics - most of the projects I seem to do are better suited to Ruby - there are probably better languages to use for some of the things I do (OORegress would probably be better off in Scala since it does number crunching) but whatever.
As my apps and web apps get more complex however, I'm thinking some sort of very basic type system would be in order. Since in Ruby you can never be really certain what type a variable is (I've been bitten in the ass in Rails by Hash vs. HashWithIndifferentAccess), having some sort of hint to other programmers what type the variable should be would be quite helpful. Just a thought.
Like most things, it is best to use it sparingly. If your Hungarian notation portion has more than say 5 characters in it, it's getting a little long. Plus since in Ruby a parameter may have more than one expected type - in Rails, ActiveRecord::Base#find can take an integer or a symbol for the first parameter - and lists can be heterogeneous there are situations where the system may not be comprehensive enough for what you need. However for 90% of the times, I think it would be an improvement.
Subscribe to:
Posts (Atom)