Thursday, September 19, 2013

Damn you, C# !

For some time now I have been working on a pet project: a domain specific language implemented as a set of C# types intended to support the creation of complex single-page web applications, generating everything including the HTML, CSS, and JavaScript.  I am more than a little pleased with the result and will be making it open source any day now.  [My motivation for this is that I've spent the last two years immersed in the web world, which is clearly a brilliant idea implemented by psychopaths and idiots -- I will rant in more detail on this topic at some later point.]

Speaking of points, back to the subject in hand.

My DSL is, in large part, based around a type Expr<T> denoting a JavaScript expression of type T.  To make life convenient, I have added implicit casts from string to Expr<string> (etc.) and overridden the standard operator set {+, -, *, /, %, ==, !=, <, <=, etc.}.  So far so good.  I can write expressions such as x + (y * z) in my DSL directly in C# where x, y, and z are Expr<int> or Expr<double>, and so forth.

There are two flies in the ointment.

Ointment fly number 1: you can't freely overload the indexing operator.

I would like to be able to write xs[i] to denote the JavaScript expression for the ith element of the array xs.  Tragically, I can't do this.  Here's what the implementation might look like if you could:

public static Expr<T>this[Expr<int>i] { get { return ...; } }

But, noooo, I can't do this because this has to be defined in the Expr<T> class and that means this has type Expr<T> rather than Expr<T[]>, which is what is required.  Instead I have to provide some awkward named function, Ith(xs, i) to do the job.  Ugh.

Damn you, C# !

Ointment fly number 2: you can't freely overload the << operator.

I would like to express assignments in my DSL as x := y or x <- y, but I can't do that because C# won't let you create new infix operators.  Hmm, well, I reckon << is hardly ever used, so maybe I could hijack x << y instead for assignment.  It has as slightly tainted C++ flavour, but it's the best thing on offer.

But, noooo, I can't do this because if I write

public static Act operator <<(Var<T>x, Expr<T>e) { ... }

I get a complaint from the C# compiler that not only is the first argument not of type Expr<T> (the hosting class), but the second argument is not a plain old int!  Great googly moogly, what were they thinking?  Even if I wanted to implement << as bitwise left shift in my little DSL, I couldn't because of the idiotic second constraint.  Instead I have to provide some awkward named function, Set(x, e) to do the job.  Ugh.

Damn you, C# !

Why would you expect any of this to work?

I just so happens I spent most of my life doing functional programming (I taught Haskell, I worked on the Mercury language team for a very long time).  In sane, modern languages (i.e., ones invented since ~1970 by people who actually passed a few hard exams -- OO, I am not talking about you) this sort of thing is done as a matter of course.



Ilya said...

Not because I don't believe you, but because I'm very interested in what this DSL looks like, can you publish just a snippet of what a basic example looks like in it? I'm curious to see what the syntax looks like...

Rafe said...

Hi Ilya! Great to hear from you. I've put up a new post in response to your question. I'd love to hear your feedback.