21 April 2010

What I Would Like in a Programming Language (Part 1)

Compiler Intrinsics

Intrinsic functions and properties are wonderful things. All the decent C family languages have intrinsic functions like sizeof and alignof, but sometimes you need support for more. While a language designer can try to think of every possible need and expose a good intrinsic for all potential future requirements, this is ultimately a losing battle for pretty obvious reasons. It would be really great if a user could extend the intrinsic properties of the compiler with their own domain-specific needs. I am imagining the compiler gets something like an extension sheet along with the source code so that these properties can be added to the system quite trivially. It would have make it so that people could extend the compiler without actually having to recompile the compiler -- it is the culture of extension that you really care about. Of course, I have no idea how the implementation would work, but it would be nice to have.

Ultimately, this could give a system like C++ type traits that do not feel like a complete hack. Of course, C++ type traits are extremely powerful, but frankly, they were never meant to do what they now do and, of course, just don't feel right. If concepts were not dropped from the C++0x standard, we could be about halfway to a cleaner solution; as it stands, we are stuck with using type traits.

To run completely away with the idea, something on the order of having a Lisp-like macro system where you have an extra program which spits out some abstract syntax tree from the input would be totally awesome. Okay, so this feature already exists in perfect form in Lisp, but I would love to see it in other languages as well.

Unit Testing


Haskell is a wonderful place to draw examples from. A framework like QuickCheck is just awesome. Because let's face it: Nobody likes writing unit tests. Now, I'm not saying that they are completely unnecessary, just that they are are pain in the ass to write. Say you have a function with the signature sqrt(x : real) : real.

If you wanted to write some unit tests for this function, you would pound away at some known values of various square roots. For brevity, I'll eliminate specifying some range of results that we consider "valid."

assert_equal(sqrt(4), 2)
assert_equal(sqrt(100), 10)
assert_equal(sqrt(2), 1.4142135)

Okay, that's halfway decent and pretty clear what I mean. But let's face it: out of the limited representational power of a real (whatever that may be), I am testing a very pathetic subset of all the possibilities. There might be negative values that somehow work or positive ones that do not - which is especially probable for very small or very large numbers. What would be nice is something with a signature like this:

sqrt(x : real @AcceptableRange(0 .. INFINITY))
: real @ResultCheck(r => (r * r) == x)

So the syntax is not completely readable, but the idea is that we are attaching some annotations to the parameter and the result of the function. These can be processed by whoever might need them, similar to the use of .NET attributes and Java annotations. However, I have stretched the allowable syntax to whatever you want -- in this case, a ranged primitive and a lambda function. The possibilities are endless! Compliers for the language doing static checking could find failures before they happen and IDEs could assist people with their problems.

Better yet, we could use...

Static Type Checking

I am a huge believer in static type checking. From the example above, things like just having a type modifier called unsigned makes exceptional conditions of the sqrt function impossible, which is really nice, since this is what you actually mean. Potential errors due to negative numbers are eliminated at compile time, because you simply cannot compile when there is a chance for an error. Compiler-enforced consistent behavior is an awesome thing.

User-Definable Primitive-looking Types

Let's say you are writing a math function that has the signature rotate(thing : Shape, angle : Real). This function rotates the Shape called thing by angle radians. Oh, you could not tell that I use radians by the method signature? That's a problem...

If we were doing some C++, we might have lines like:
typedef float Radians;
typedef float Degrees;

So the signature would look like: void rotate(Shape* thing, Radians angle). Now the method signature tells you which kind of unit you are using. Of course, the problem here is obvious: since Radians and Degrees are actually the same type, we are free to convert between the two and the compiler will not actually care that there is a difference (because, as far as it is concerned, there is not a difference).

So how can you make the compiler care? In C++, this is notoriously difficult (although possible). Once again, let us pretend that there is something perfect out there for me that looks like this:
type Radians is real range 0 .. 2 * PI
type Degrees is real range 0 .. 360

And then one could specify that there exists a scalar conversion between the two units:
conversion Radians <=> Degrees is implicit direct

That looks a little funny, but stay with me for a second. The <=> token means that the conversion is two-way. After that, I added some words just to show that my dream is really powerful. implicit means that there is an implicit conversion (as opposed to an explicit one) - the compiler is allowed to freely convert the units between each other (assuming it follows the rules of conversion). Then, direct is just a way to specify that there are no fancy conversion rules: the compiler just figures out that 180/PI is a good conversion factor for the number specified.

var angle = 180 degrees
rotate(thing, angle)

This is kind of along the lines of Ada with a little bit of extra conversion logic. A convenient system like this would be great for certain NASA contractors.

I've decided to split this incredibly long post up...

15 April 2010

Implications of Apple's iPhone Lockdown

If you have been living under a rock this week and have not heard about Apple's wonderful new iPhone Developer License Agreement, here is the part that is bothering people:

3.3.1--Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

I am not exactly a businessman, but this does seem like a rather bad move on Apple's part. Apple seems to lack an official stance of the matter, but the response of Steve Jobs to John Gruber's blog is the closest I have seen. I think the John summarized Apple's reasoning in the 4th paragraph (emphasis mine):

So what Apple does not want is for some other company to establish a de facto standard software platform on top of Cocoa Touch. Not Adobe’s Flash. Not .NET (through MonoTouch). If that were to happen, there's no lock-in advantage.

It is Apple's platform which they used to take over the "hip" smartphone market with elegant simplicity, solid design and good marketing. Somehow, despite the incredible lockdown on distribution (to the point where you can develop an application and just have it rejected), people are climbing over each other to develop exclusive applications for it. It seems like everyone and their dog is making an iPhone application and it is the de facto "easy mobile platform," despite the fact that other SDKs exist and look awesome.

John then goes on to say this:

Then Apple releases major new features to iPhone OS, and that other company’s toolkit is slow to adopt them. At that point, it’s the other company that controls when third-party apps can make use of these features.

How is that relevant? As an application developer, layers of abstraction are a good thing. In the simplest case, consider a library like SDL. It allows me to develop an application concurrently for Windows, Linux, OSX and whatever else SDL, despite the drastic differences in windowing systems and system libraries. For the majority of the graphics things I need, SDL provides a convenient way to develop it for all target platforms simultaneously. In the corner cases where I need functionality that SDL does not provide, I can work down to system-specific OpenGL calls. The mark of the good library is that it abstracts the most common functionality and lets you get more specific when you need to. If the abstraction layer does not provide the functionality you need it, make the system call yourself. If the abstraction layer does not allow you to do this, get a new library.

I can understand that Apple does not want a bad standard taking over their magical platform, but unlike a web standard, when you compile a language, assemble the generated code and run it on a processor, the processor is completely agnostic to what the original input language was. I'm willing to bet that when Adobe's software is transforming your ActionScript code to run on the iPhone, they are making the appropriate system calls. There is also a good chance that the code that Adobe emits automatically is more efficient than the average iPhone developer's. If application developers need some functionality provided by Apple's SDK but not yet wrapped in a high-level call, they can just make the SDK call. If the system does not allow this, it is time to get a new one.

All Apple is doing is locking down their system so that people have to use their tools to develop for them. While a great money-grabbing move: Does it help the customers? While John provides the common assertion that cross-platform apps are bad on Apple platforms, I would argue that has less to do with the fact that the application is cross-platform and more to do with developer time. Many Windows+OSX apps are worse on OSX because developers do not care enough about the OSX version (which is probably justified, considering the percentage of users of both systems). Besides, there are already systems which provide cross-platform support and I will site QML as just one of such systems. Ultimately, how well an application works on the systems is a property of how much time and effort a developer puts into it. And if a developer is tasked with making the same app for a web browser and the iPhone, then having to write common functionality once will give them more time to dedicate to the making the application feel right and will give consistency across platforms, both of which lead to an ultimately better user experience. And if the abstraction layer does not make it easier to develop, then it is time to get a new one.

Enter the Apple fanboys. Steve makes the case that Apple does not want to tie themselves to a single platform and seems to think that XCode is the only thing capable of cross-compilation or that Apple is somehow innovative in this regard. He also seems to think that the iPad's processor is not of ARM architecture and that, for some reason, Apple is artificially restricting people to running their apps on an emulator. If he is right, then Apple is epically stupid, since it is obvious they are not lacking in a compiler for whatever the A4 chip is. This is my favorite quote:

Apple is sowing the groundwork to make architecture changes seamless—developers will only need to flip a switch to give their apps blazing, native performance.

All debate about what the A4 is aside, it is ridiculous to think this argument is a legitimate justification for the programming language lockdown. If Apple's toolchain really does generate applications that are so superior to others that it outweighs the cost of having to develop two simultaneous apps, then people will just use their system. Apple would win on the merits of being better and would not need to lock down their system in the first place. Apple is no longer competing on the grounds of producing a better system; they are effectively saying that they do not wish to compete and are just locking Adobe out. Lack of competition ultimately hurts the customer.

But Adobe is not the only one Apple is screwing over with this policy - it raises legitimate concerns for abstractions like Qt-iPhone. They are probably safe, since Qt is mostly C++. However, some could argue that with uic and moc, that Qt code can no longer be considered "C++." Of more concern are tools like Unity 3D, whose front page boldly currently advertises "Unity iPhone 1.7, Now with iPad support." Sorry, guys! And what about the people who no longer wish to live in the world of imperative languages? Nope.

Its sad that the iPhone is what people will consider the spark that started the era of ubiquitous mobility, when that perception was nothing but an amazingly well-played marketing game.

UPDATE: The latest Unity mailing list letter contains this gem (emphasis mine):

As most folks already know, Apple introduced a new Terms of Service (ToS) with their iPhone OS 4 that has some Unity users concerned. While we don't yet have a definitive statement to share at this time, we have a healthy, ongoing dialogue with Apple and it seems clear that it's not their intention to block Unity and will continue our efforts to ensure compliance with the Terms.

I feel bad for the Unity developers, who will probably have to do a some amount of work to "insure compliance." What a pointless waste of energy. For more on this, check out David Helgason's blog. What surprises me is that Unity is in direct violation of the words of their terms of service. It is not really debatable — user applications simply are not written in "Objective-C, C, C++, or JavaScript."

This goes back to my emphasis: "...it seems clear that it's not their intention to block Unity..." So what is their intention? It is clear that Adobe is not getting this same treatment. Was Apple's only intention to block Adobe? That is astoundingly pathetic.