This is a read-only archive!

Redemption, sadly.

Today I rammed smack up against a brick wall in my C# endeavors. The problem at hand was something that seems pretty simple: Randomly shuffle an array. Anyone who knows Ruby knows that this is super easy. Here's one way:

arr.sort_by { rand }

How do you do this in C#? Search google for some tips and view the abject horror of a verbose and non-orthogonal weak language. Read if you dare. Find the shuffle routine in this labyrinth of code, and feel the pain. Have some more if you like. ...cringe. Then read this one. And then read on Wikipedia why this last solution is pretty much totally wrong. And why the Ruby one above is very much right.

So a lot of people wrote a lot of C# code, much of it ugly, to solve this problem, so what? You can find bad code in any language. My point is, to borrow a mantra from the world of Lisp, not all programming languages are created equal. Sure, all programming languages are equally powerful in the Turing-complete sense; you could write a Ruby interpreter in C# and solve the above problem that way. But there are things about some languages that make it much more difficult to solve some problems than it would be in other languages. Passing around blocks in Ruby makes it super easy to solve a problem like randomly shuffling an array. In C#, Java, etc. you'd at the very least have to make some kind of object that represents a sorting algorithm, some kind of method that takes and uses such an object, and you'd also have to worry about all the type compatibility between all of the above. Or I could use some kind of delegate method, which is C#'s version of function pointers, from what little I read. Both of those solutions are a lot more code than I really want to write to solve such a simple problem.

In Perl, to do this kind of thing, you'd take the array, map it into a hash of array-element / random-number pairs, sort by the random numbers, and then re-map it into an array. More verbose than Ruby, but better than nothing. C# has Hashtables and ArrayLists, so why not try it the longhand Perl way? That's what I ended up trying in C# at work. At this point, I ran up against all the lovely limitations of statically typed languages. First I made a hash and tried to get a list of its keys and store them in a native array. You can't do that, because Hashtable returns an ICollection object, not a plain old array, and you can't cast one into the other. C# apparently retains some of the ridiculous Array vs. ArrayList, primitive type vs. object type bullcrap that comes from the world of Java. What reason is there to have a subset of things that are completely incompatible with another subset of nearly identical things? What reason is there to have such a thing built into the very foundation of a language? Java has the excuse (maybe) that they started off with a bunch of crap, and had to try to fix their crap without breaking all the code everyone already wrote using the old crap. What's C#'s excuse for copying this horrendously unwieldy mess?

I eventually got everything sorted out, and it didn't take THAT long, but sure it wasn't pretty. And it was silly, unnecessary work. The solution ended up being 20 or so lines of code to do what Ruby does in 13 characters much more elegantly.

Problem number two today came when I tried to printf a string, and strftime a DateTime. Now, there are what seem to be pretty widely accepted standards on how a formt string for how a printf-style function should look. %d, %s, %f, and so on. Similarly lots of languages have a strftime function that uses pretty standard tags to represent month, day, year, hour, minute, second etc. There are some variations between languages, but the general idea is similar enough that you can pick it up very quickly. In many cases you can drop C strings into Perl or Ruby or whatever, and it'll work just the same.

Well, of course, Microsoft craps all over those pseduo-standards. In C# rather than something like "%0.8d", you get something that looks like "{0,8:#}". Same deal for strings to format dates and times; they look nothing like the strftime I'm familiar with.

Why? Why does MS have to do everything differently than everyone else in the world? The choice of format strings is totally arbitrary, so why not use what every freaking other language in the world uses? Is it to keep MS-only programmers mentally tied into MS-only languages so that anything non-MS looks alien to them? Are the MS-style format strings any more powerful than printf-style? Not that I can tell; the C# ones give you special tags for "currency" and to comma-separated numbers, but couldn't they have just added a "%$" and "%," to the MS version of printf or something? Read this trash. I spent way too much time today reading through this small encyclopedia of documentation on MS-style format strings just to re-learn something I already knew very well.

October 29, 2007 @ 1:48 PM PDT
Cateogory: Programming

4 Comments

numerodix
Quoth numerodix on October 29, 2007 @ 10:59 PM PDT

Oooh boy, you sure are putting me off c#, which I've been meaning to try.

I agree with your first point, though, once I've written list.each { something } once in my life, I never want to write another for loop again. Which made a recent java project for a school assignment so much more painful.

Brian
Quoth Brian on October 30, 2007 @ 6:43 PM PDT

There's some good in C# and Java. The tools built around the language and the standard libraries that come with them can make up for some of their deficiencies, if only by keeping you from having to write much code yourself.

Sad that the best thing you can say about C# is that its IDE lets you get away with having to write much of it by hand.

smarter than u
Quoth smarter than u on October 31, 2008 @ 4:10 AM PDT

List list = new List(new int[] { 1, 2, 3, 4, 5 }); Random rand = new Random(); list.Sort(delegate(int x, int y) { return rand.Next(-1, 1); });

Not that hard, newbie.

Brian
Quoth Brian on October 31, 2008 @ 4:24 AM PDT

That's better than all the solutions I linked to, thanks.

However you sound like a 12-year-old. (No offense if you really are 12.)