Objective-C, Ruby and Python for Cocoa

I stayed out of the Cocoa language bridging discussion for a few days. I had some initial reactions, but I wanted to make sure they were legit and listen to what people had to say first. The biggest unnamed factor in all of this, I think, is Objective-C 2.0.

First, just a quick rewind. On the Hivelogic podcast, John Gruber talked to Dan Benjamin about the Ruby and Python bridges being bundled in Leopard. In essence, Gruber suggests that Cocoa programmers would prefer to use Ruby or Python if performance wasn't an issue. Here's the quote:

The reason people love Python and the reason people love Ruby is they love the syntax. [...] Even people who really, really love Objective-C and Cocoa, they love it because of what it lets them do. Most people don't really say "this is beautiful syntax."


That's true, but I think it's a little misleading. I think you'll find that most Cocoa programmers enjoy the Objective-C syntax, mainly because it's very simple and straightforward. In fact, it's much simpler than C++, but you don't hear about this as much because it's not newsworthy.

People talk about Ruby's syntax because it really stands out. Objective-C's standout feature is the fact that it's a dynamic language which is compiled. It can call into C and C++ while maintaining runtime class changes and message redirection.

Many of tedious aspects of Objective-C — memory management and accessor maintenance, for example — go away in Leopard if you want them to. These changes are, of course, designed to reduce code.

Gruber suggests that Ruby is a logical replacement for Objective-C in many cases because you can do so much in so few lines of code and it looks. But there's a subtle point there: Cocoa is not about the fewest possible lines of code, but rather making every line tell.

Some things that allow Ruby programs to be very short involve language cleverness or even basic terseness, some of which can be found in Perl and Python as well. This isn't always a good thing in Cocoa. The overriding goal for Cocoa is clarity and simplicity, and sometimes the most straightforward thing is not the shortest or the most clever. What's clever to you may be confusing to someone else reading your code.

Higher Level Abstractions

Gruber goes on to explain that he's not trying to put down Objective-C (which is clear when you hear it in context), but he thinks programmers will prefer to use Ruby or Python wherever performance is not a significant factor, because you have to write less code. Daniel Jalkut expands on this a bit:

...it's exactly what programmers have always done when they switched to a higher level language. 10 years ago a programmer would be more likely to "switch to assembly" for a much-needed performance boost. Has it come to this? Are we moving to a higher plane?


(Side note: I think this might unintentionally give some the impression that C and Objective-C are similar, which is only true to the extent that milk and milk chocolate are similar).

In a follow-up comment on Daring Fireball, Gruber adds this:

Back in the really old days, before Perl took off for web programming, people used to write CGIs using C. And then when Perl started getting popular, some C programmers said it wouldn’t work because Perl was slower than C. In the meantime, while the C curmudgeons were complaining, those who embraced Perl were building the Web.


In both of these cases, switching to the higher-level language made the code much easier to manage and didn't present any significant functional drawback. In other words, it wasn't just that you were further away from the processor, but that you actually ended up with better code in most cases.

That later case is particularly interesting because Perl was designed for text processing, which is what CGI programming was all about at the time. There was rarely a functional advantage to using a character buffer over a Perl string.

This isn't the same situation Cocoa finds itself in. Ruby isn't just a higher-level version of Objective-C. Both are dynamic languages with a high-level syntax, and each has evolved around their areas of specialty. For web apps, text processing is very important. For desktop apps, calling into existing C and C++ code is invaluable.

Variable typing can be very useful. AppKit and Foundation alone have hundreds of classes, and that doesn't even include everything in Application Services, Core Foundation, Core Image, an so on. With so many data types, it's not clear to me if you really want to optimize for the assumption of most things being strings or numbers.

In any case, typed variables in Objective-C are not a constraint imposed by the compiler. Although typed variables are generally necessary in C so that you can get proper data sizes, Objective-C uses them as hints to the programmer and the compiler. You can discard most of them if you really want to.

Stripped-Down Objective-C

Because Objective-C is a dynamic language, methods are bound at runtime. Classes, too, can be changed on the fly and messages can be redirected at will. This is how things like NSUndoManager, Core Data and Key-Value Observing are possible, and why Java never had a very easy time with any of this.

In addition to all of that, the typing of variables and return types is mostly optional. Here's an example:
- personProperties
{
   id person = self.person;
   person.firstName = @"Douglas";
   person.lastName  = @"Adams";
   person.favoriteColor = self.defaultColor;
   person.birthDate = self.defaultDate;

   return person.properties;
}


This is perfectly valid Objective-C 2.0 code — variables are only typed by choice. Up until Leopard, there was some extra noise in the syntax related to memory management and accessors, but with garbage collection and properties, all of that can vanish if you want it to.

Also, even as far back as Mac OS X 10.0 (and beyond) methods without return types are assumed to be id, as are method arguments without a type. So these two are equivalent:
-personWithTemplate:template;
-(id)personWithTemplate:(id)template;


This gives you room to return an NSNumber, an NSArray, an NSManagedObject, or practically anything else.

So why does no one do this? Because it's not about the fewest number of characters, it's about removing ambiguity. There are places where the id type is used by Cocoa, but it's where you legitimately want a generic type, such as valueForKey or delegates.

Writing Code is the Easy Part

If we take the previous stripped-down example and add some optional typing information, it looks a bit more like this:

- (NSSet *) personProperties
{
   PersonProxy * person = self.person;
   person.firstName = @"Douglas";
   person.lastName  = @"Adams";
   person.favoriteColor = self.defaultColor;
   person.birthDate = self.defaultDate;
  
   return person.properties;
}


This version takes slightly more time to type, but without the type information, I might assume personProperties returns a NSDictionary and person itself is a Person object. In this case, though, it's actually an PersonProxy class and the properties are contained in an NSSet.

I could figure all of this out by trial and error, and it's it's not that I'm worried about things breaking at runtime — it's that variable types help me understand the intent of the code. It's like a comment the compiler can use. Units tests can prevent logic errors, but they can't help me or the compiler read the code. Programmers do more reading of code than writing.
                            
Is it technically possible to build Cocoa projects without type information? Absolutely. That, combined with dynamic messages, foreach loops, properties with dot syntax, and garbage collection gets you within throwing distance of a scripting language, all while maintaining all of speed and compatibility benefits of Objective-C.

Headers files and variable typing are tools to help you navigate complex code bases. You can dispense with most of them in Objective-C if you really want to treat Cocoa as a scripting environment, but why throw away what is clearly useful metadata? You don't need to be a compiler or linker expert to use Objective-C.

Use the Tools You're Given

I'm thrilled that Cocoa is gaining built-in Ruby and Python support, particularly because it lowers the barrier to entry. I think it will mean we'll see a lot more people get involved in Cocoa.

I don't think it's going to mean a mass migration of existing Objective-C development to a scripting language, at least not anytime soon. Even if performance was not an issue, Objective-C simply offers too many advantages, not the least of which is that it's the language that Cocoa is built around. For example, look at this example of creating a timer in Objective-C:
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/60.0
                                         target: self
                                       selector: tick
                                       userInfo: nil
                                        repeats: YES];


Here's what it looks like in Ruby (from Tim Burks's excellent RubyCocoa site):              
@timer = OSX::NSTimer.scheduledTimerWithTimeInterval_\
target_selector_userInfo_repeats(\
1.0/60.0, self, :tick, nil, true)


(I'm not intentionally misformatting this. I'm not sure if it's convention to break these things up into multiple lines.)

Cocoa is designed for multiple named arguments at the language level, which is something Ruby does not currently support. Rails tackles this with named hashes, but that approach has its own challenges since applying that to Cocoa means you'd be changing the actual method names.

Cocoa and Objective-C are not independent tools that just happened to be dropped in the same bin, they're designed to work together. Separating the two is like installing Mac OS X on a Dell.

I'm also curious how the debugging process goes with gdb. It looks like Ruby objects can talk to gdb, but it seems things could get interesting when Ruby and Objective-C method talk back and forth.

Balance of Available Options

What this all comes down to is two points:

1. Mac application development revolves around Cocoa.
2. Cocoa revolves around Objective-C.

There are other possibilities on both points, some of them quite good, but it all comes back home to this. The Ruby language has some incredible features that Objective-C does not, and the opposite is also true. I recently helped port a PyObjC app with Quartz bindings to Objective-C. Admittedly, I'm not an expert in Cocoa bridging, but I do have some recent experience in this area, so it's not all just guessing.

If you look at the site archives, you can see I'm a big fan of Ruby and Rails in particular, but the the question isn't if the language itself has value, it's which language is the best fit for Cocoa.

As far as I can see, the scales are tipped in the direction of Objective-C for most moderate-size desktop Mac apps. It will not always be this way, but that's how it is today. The key is that Objective-C is tuned exactly for what a Cocoa app needs: compiled code, dynamic dispatch, simple language constucts, and easy call-in to C and C++.

This last point is important. In a Rails app, you can do practically everything you need to do from Ruby. For a desktop Mac app, Objective-C is often just the core. Large parts of the Mac OS X API — not to mention huge amounts of multi-platform code — is implemented in C. Being able to call that right inline is invaluable. As invaluable as having built-in regex support for web apps.

Despite all the progress that has been made, I think web and desktop development are still not all that similar — at least if you're building the sort of apps Mac users are used to. When you have multiple threads, persistent state, interprocess communication, graphic contexts, notifications, and so on, things look a bit different. The other big factor that a web app mostly sits between the server and the browser. A desktop app involves more direct interaction.

An Ongoing Evolution

Although a typeless scripting language is a proven good fit for the web, it doesn't necessarily carry over directly to a desktop environment like Cocoa and all of the related frameworks (many of which are not available from the bridge). It might carry over, but it has to re-prove itself. Maybe Ruby will change to better fit Cocoa, or vice-versa.

It is certainly possible to do a lot of the core interactions in Ruby or Python, but Apple specifically provides Objective-C because it helps all of this stuff fit together nicely. That's why it went the trouble of creating a new version of the language with a brand new runtime.

In fact, if there was no such thing as Objective-C 2.0, I think this would be a much different discussion. The advantages of garbage collection, properties and foreach loops are so significant that the lack of them might actually trump the speed and integration — but the new syntax and runtime tip the balance back in the favor of Objective-C, at least for the next several years.

Of course, I could be wrong about all of this. Maybe Ruby Cocoa or PyObjC will take off. For further reading, though, check out these Cocoa Dev Central tutorials:

Objective-C Style I
Objective-C Style II

Let me know what you think. Finally, it's worth noting that there are a few things about the Objective-C 2.0 runtime that aren't public knowledge yet, but do have an impact on this overall discussion.
Design Element
Objective-C, Ruby and Python for Cocoa
Posted Feb 19, 2007 — 47 comments below




 

Romain Guy — Feb 19, 07 3598

Excellent post Scott. I like Python and Java programming languages a lot, but I am equally fond of Objective-C. To me, Objective-C is the language to go for to write Cocoa, simply because there's already so much Objective-C code for Cocoa out there. That said, I wouldn't mind using something else if I had a good reason to.

Nevertheless, if you look at what happened with other languages/GUI toolkits you can see a trend. Most, if not all, GUI toolkits appear to be tied to a particular language. Even though bindings are available for other languages, there's always a, largely, dominant one. Most people are writing Swing in Java, most people are writing QT in C++, most people are writing WinForms in C#, and so on.

But I am glad we have the choice. Python and Ruby support for Cocoa is nice because there will be some programmers who will prefer to use those languages rather than Objective-C but I highly doubt this will be the case of all Cocoa developers, even if performance wasn't an issue (and I'm pretty sure it is already not an issue for many applications.)

Choice is good.

Scott Guelich — Feb 19, 07 3599

As a former Perl junkie, I definitely welcome the script language bindings. Here are a few reasons why I believe Ruby/Python development may be successful:

1. Ruby and Python do some things much faster and easier than Cocoa/Objective C. Things such as regular expressions, text processing, interacting with the shell, etc. As an example, you could easily port the Debian rename script (Perl) to Ruby with bindings, throw a slick GUI on it, and you have a powerful drag-n-drop batch renaming utility for Terminal-phobic users (like A Better Finder Rename, but in less than 100 lines of code).

2. Hopefully it'll encourage a bit more freeware in the Mac world, since scripting languages are inherently open source.

3. It's a lower barrier of entry for new/young developers. Because scripting languages are by default open source, it'll be easier for newbies to learn by tweaking existing freeware apps.

While I agree that Objective C makes more sense for many projects, I'll definitely use Ruby for tasks where it's a better fit.

p.s. The long Ruby line definitely looks odd to me. I'm a compulsive line-breaker/indenter/vertical aligner in scripting languages (which is why I never could use Python...), so I'd certainly reformat that.

Ryan Brown — Feb 19, 07 3600

Two things:

First, RubyCocoa has a new messaging syntax as part of the 1.0 preview. For information about it, check out What's New in RubyCocoa's 1.0 sneak preview. Here is a before and after with your example code:

Before:
@timer = OSX::NSTimer.scheduledTimerWithTimeInterval_\ target_selector_userInfo_repeats(\ 1.0/60.0, self, :tick, nil, true)

After:
OSX::NSTimer.objc_send(:scheduledTimerWithTimeInterval, 1.0/60.0, :target, self, selector, tick, :userInfo, nil, :repeats, YES);

Second, why are you (and all the other Mac bloggers) talking like these bridges are something new?

I'm thrilled that Cocoa is gaining built-in Ruby and Python support, particularly because it lowers the barrier to entry.

PyObjC and RubyCocoa have both been around for a long time. RubyCocoa has recently seen a lot of improvements (both in speed and features) because of the efforts of one Apple developer. These changes are significant, but not significant enough to say that Cocoa is now "gaining built-in Ruby support". You have been able to write Cocoa apps in Ruby or Python for years.

Daniel Jalkut — Feb 20, 07 3601

I agree that my post betrayed my own view that Objective C and C are largely identical. I mean, the fact that ObjC is essentially implemented as a C-library runtime on top of C contributes to this attitude.

Side note: I think this might unintentionally give some the impression that C and Objective-C are similar, which is only true to the extent that milk and milk chocolate are similar.

I think this statement would be much truer if you compared milk and chocolate milk. That is, Objective C is C with something added to it. Not a complex product of which C is merely an ingredient.

Scott Stevenson — Feb 20, 07 3602 Scotty the Leopard

@Ryan Brown: Here is a before and after with your example code
It's certainly more clear which argument goes with which value, but I don't think it's as readable as Objective-C's named parameters.

Second, why are you (and all the other Mac bloggers) talking like these bridges are something new
A lot of it started up because of John Gruber's interview, but the fact that they will be bundled with Leopard increases their visibility. A lot of people may have not known about them before.

Another thing I forgot to mention is the issue of interpreter versions. The PyObjC project I was working on had its own version of Python in the application package in. I'm not sure what the exact reason is for that, but I wonder if it will be negated by Leopard.

That document you linked to also has some interesting details about how to get access to C functions. Apparently a metadata file is generated for each framework which gets interpreted at runtime. It looks like they're tackling one built-in framework at a time, but I'm not sure how third party code is handled. This is all exciting stuff, though, even as a great tool in a larger toobox.

Also, this seems to have some, um, interesting implications:
class NSString def length 42 end end # Now, all NSString objects will have a length of 42

The plain text aspect of this is what strikes me. Developers who have an Objective-C app which allows RubyCocoa plug-ins to load (or even just RubyCocoa code in the bundle) might have something to think about here.

Scott Stevenson — Feb 20, 07 3603 Scotty the Leopard

@Daniel Jalkut: I think this statement would be much truer if you compared milk and chocolate milk. That is, Objective C is C with something added to it. Not a complex product of which C is merely an ingredient
I don't think that's as true as it once was, particularly if you consider the Objective-C 2.0 sessions from WWDC. There are some big changes in the runtime.

From an implementation (Apple) perspective, Objective-C rests on top of raw C, but from the developer-user's perspective, they're worlds apart. You can write plenty of Cocoa code without knowing what asprintf or wchar_t is. With that perspective in mind, I really do think the milk chocolate metaphor fits, but I realize that's just my view.

Daniel Jalkut — Feb 20, 07 3604

Heh, well I shouldn't argue too passionately about chocolate ... considering ... this is the Theocacao site :)

But chocolate milk is like milk in that you can do everything with it that you can do with milk, and more. You can't pour a candy bar.

Anyway I realize the metaphor debate is a bit beside the point. I think you're right that with the ObjC 2.0 enhancements, ObjC stakes out a bit more independence for itself.

Jesper — Feb 20, 07 3605

Good post. Definitely a good post.

Typing is important. Writing clean code is important. I never thought I'd say this, but having coded in C# 2.0 and used generics, it's clearly a good alternative to many duck typing techniques. (And also a reminder: yes, I know that doing id foo here and id bar there isn't duck typing - it's very loose standard typing.)

Just the ability to have an ad-hoc created, dynamically specified list type for containing, say, strings, is a good idea. Being able to pass in dictionaries and their own types, and being able to create a subclass and pass in a set type for that (like saying HTTPHeaderDict : Dictionary<String, String>) is priceless. Both Objective-C and Ruby are missing out on this. (In the same way, I might add, that C# is missing out on do-the-right-thing method dispatch - my god, it's full of modifier keywords!)

And I think it's important to qualify, to state as fact so that this subtle point isn't lost, that the reason people want to use Ruby or Python is not because people want to hide from specifying types. (It's probably not what you think personally, I'm not claiming you argued it, but if one wanted to hard enough, I think one could take it away from this article. )

For me, it's not a question of whether Objective-C is a good language, or even the best language to do Cocoa in. It's simply a question of: are there cases where using Ruby or Python would be significantly better? And the answer is: yes, definitely, of course. Are there cases where novices or adverse square bracket allergics could write their whole apps in those languages? Yes again. I'd recommend against that on the merit that every language should do what it's best at, and there's going to be a whole lot of what we call 'pure Cocoa' in there that Objective-C will be best at, but it'll certainly be possible.

Personally, the bridges are all about these two things. Making it easier for *me* to use Ruby when I need to, and making it easier for folks only familiar to Ruby to use it as much as possible when they start to use Cocoa. I think most people like Objective-C, and especially what it'll do for them in terms of 'getting' Cocoa, after using it for a while. But you just don't wake up one morning and sit down and learn it, you have to ease into it, which is another reason why it's very important for Apple that there's always a bridge.

Michael Stroeck — Feb 20, 07 3607

I think for standard Cocoa desktop development, ObjC 2.0 offers the best of both worlds. A well-formated Cocoa project with useful method naming in Objective C reads almost like prose, especially with all the noise of memory management and stuff like explicitly setting up NSEnumerators gone. A random line of code I was just looking over:

... if (![[[[NSWorkspace sharedWorkspace] launchedApplications]\ valueForKey:@"NSApplicationBundleIdentifier"]\ containsObject:externalEditorBundleIdentifier]) ...

Sure, the use of brackets is a bit excessive, but this is basically a sentence. If you can read English, you know what this is supposed to do. It may be verbose, but if you are actually typing out more than 10% of this line, you need to get a better editor instead of complaining about the syntax. In my book, code readability is far, far more important then "writability".

PyObjC and RubyCocoa have both been around for a long time. RubyCocoa has recently seen a lot of improvements (both in speed and features) because of the efforts of one Apple developer. These changes are significant, but not significant enough to say that Cocoa is now "gaining built-in Ruby support". You have been able to write Cocoa apps in Ruby or Python for years.

Of course it has been possible, but it was not exactly officially endorsed by Apple. If thinks break going from one version to the next, its now technically Apple's bug. I think that's quite a big difference.

Laurent Sansonetti — Feb 20, 07 3609

Hi Scott,

Nice post! Just a few additions.

You made a good point in the fact that Objective-C, as a subset of C, can call C/C++ APIs without much difficulty. Ruby and Python can't do that as easily without writing/generating an extension or dealing with the dynamic linker API. But we are working on a new mechanism to make the non Objective-C frameworks accessible from Ruby and Python without no cost. This is based on metadata files and briefly explained in the "RubyCocoa 1.0 Sneak Preview" page. We use this to cover everything that can't be retrieved at runtime (including Objective-C things like informal protocols, and very recently, inline functions). This mechanism would also be public so that 3th party developers could cover their own frameworks.

Secondly, regarding the Objective-C calling syntax, it is true that translating the selectors into Ruby and Python calls isn't an easy job. The PyObjC guys came up with this underscore-based syntax a long time ago, and the RubyCocoa team just followed them since. This syntax should be good enough for most cases (the long selectors are pretty rare). RubyCocoa has nevertheless this new #objc_send API that you can use to explode your selector, but it's still not perfect. We used to have alternative syntaxes (based on inline Hash) but we decided to deprecate them as they were not reliable enough. We have been discussing with the Ruby core team about adding "keyed-parameters" to a future Ruby version and both of us are very interested in doing this. For the moment we are just discussing it.

Jim Getzen — Feb 20, 07 3611

I suppose I'm part of the target market for the RubyCocoa and PyObjC bridges: a have a full-time job non-programming job, but like to program in my (family-limited) spare time as a hobby.

What RubyCocoa and PyObjC do is make that spare time more productive and fun. Who wants to fool around with header files and pointers and verbosity?

I have used Obj-C to make an app or two, and it's OK, and I understand that it will be getting some cool new features in 2.0, but I would much, much rather program in Ruby or Python. Not only it is more fun, it's a lot easier, for me at least, to jump back into a project after a week's absence and get back into the flow when I'm working with Ruby or Python.

(Speed has not been an issue except when intensive computation is needed. Of course, you can always call an Obj-C class from Ruby/Python to handle that sort of thing. Not ideal, but it works.)

I find Ruby to be particularly well-suited as a bridge language to Cocoa. It's messaging syntax is elegantly translated to Obj-C's. The only problem with Ruby is lack of code obfuscation. Open the app package and the source is sitting there in plain text. Hopefully, Ruby 2.0 (with YARV) will help in that regard.

I'm very excited about Leopard. Laurent has been doing some outstanding work Leopard's RubyCocoa 1.0. I haven't seen this discussed (maybe it's an NDA subject), but I am hoping that Xcode will gain some Ruby/Python enhancements as well.

Chris — Feb 20, 07 3612

I think you'll find that most Cocoa programmers enjoy the Objective-C syntax, mainly because it's very simple and straightforward.

I don't think so. I enjoy the Objective-C semantics. The Lisp-like multiple-bracket syntax is from hell, and only smart editors like TextMate make it really tolerable.

Yes, I think Ruby would be a better language for using a more SmallTalk/ObjC-like syntax:for:method: invocation. But getting rid of the curse of the nested brackets is a worthy tradeoff, and there are massive benefits to Ruby as a language that have nothing to do with the web. Closures (blocks), symbols, the infinitely superior switch (case) statement are some of my favorites. Unification of interface and implementation. No more confounding curlybrackets, and thus no arguments over curlybracket placement. Infinite precision for arithmetic, in addition to the familiar C bitwise operators. Plus, indentation is not significant, and thus you don't have the Pythonian "why am I getting a random syntax error in perfectly legitimate code on line 2661?<...16 hours pass...>Oh, there's a tab instead of some spaces on line 45, and somehow it was OK until I added this new code..."

Daniel Jalkut — Feb 20, 07 3613

I got so caught up in defending my chocolate honor that I neglected to say: great article! I think the point that ObjC is closest to Cocoa is important, and may indeed prevent any abandonment of ObjC by people who are already comfortable with it.

I had forgotten how ugly the "distributed selector name" -> procedural function name mapping can be. Which I shouldn't have forgotten so quickly, since I just ported a Cocoa Java app that was full of them.

Scott Stevenson — Feb 20, 07 3614 Scotty the Leopard

@Jim Getzen: Who wants to fool around with header files and pointers and verbosity?
Headers files are just a list of methods and instance variables, which are as useful to the human as the compiler. They might be a bit superfluous in very small projects, but I think anything with more than one window sees benefits.

As for pointers, you don't have to think about them much in Objective 2.0 if you don't want to. At least not if you're building the type of things you'd do in Ruby. In fact, if there was no asterisk you might not even know they exist. If you call into C you'll have think about that, of course.

As for verbosity, that's really determined by Cocoa, not Objective-C. The Ruby bridge doesn't change the method names in the frameworks. All that said, use whatever works best for you. I do wonder, though, how many people are typing all of their Objective-C code by hand, rather than using TextMate or Xcode's code-generation features? I can't imagine doing it all manually.

@Chris: Closures (blocks), symbols, the infinitely superior switch (case) statement are some of my favorites
I really like blocks, and I think they'd be a good addition to Objective-C. I also like auto-return of the last statement, but that might have some unintended side effects.

Unification of interface and implementation
I don't think that's universally a good idea. Headers files are often the only saving grace in large projects or those you don't have the source for. I guess I don't get why anybody would be scared of header files. It's just a list of the class contents.

Laurent Sansonetti — Feb 20, 07 3615

Jim: some Ruby code obfuscators exist, there is even a commercial one that is apparently very good: http://www.ruby-forum.com/topic/69161

As for the verbosity issue, I agree with Scott in the fact that it's mostly dependent of the bridged API, though it's definitely clear that Ruby is less verbose than Objective-C. But Objective-C isn't that much verbose anyway (do you remember programming in Java? :-)).

Michael Stroeck — Feb 20, 07 3616

Chris: Complaining about header files is a bit like complaining about tables of contents and indices, in my very humble opinion ;-)

Scott: Thanks for fixing up my formatting!

Jim Getzen — Feb 20, 07 3617

Regarding header files, I guess it's just me, my coding style, and the modest size of projects I've done, but having to switch back and forth between a source file and its header when I want to add/change a method or instance variable is inconvenient, not to mention other drawbacks (possible circular references, more file clutter, harder [for me] to debug errors). *shrug* Just a rookie's point of view I suppose.

Thinking about header files, pointers, and (relative) verbosity, none of those by itself is that big of a deal, but put them together and, well, it sure is nice to have choices that avoid them (and compile times!).

@Laurent: Yes, I recall that commercial obfuscator. Seems pretty expensive, but would probably be worth it in some situations. In the meantime, my strategy is to stick with Python where I need some source code protection. This is off-topic, but is that protection illusory? Is there a simple way to convert python byte-code files (foo.pyc) back into source code?

Ken — Feb 20, 07 3618

I actually like the objective-c syntax.

Method invocation:
[object makeDrink:@"Milk" with:@"Chocolate"];
Variable access:
id theDrink = object.drink;
Its the difference between a verb (action) and noun (variable), and its expressed using different syntax. I can know at a glance when code is bracketed, I'm invoking an action, and when I'm using dot-syntax I'm accessing a variable.

The difference between
object.drink
and
[object drink]
become immediate. What's so hard about that??

Scott Stevenson — Feb 20, 07 3619 Scotty the Leopard

@Jim Getzen: but having to switch back and forth between a source file and its header when I want to add/change a method or instance variable is inconvenient
Not as incovenient as not having headers to look at. :) Some of this may come down to project size and whether you're the only author or not, buy having a nice, summarized view of all the methods sure seems pretty nice to me.

Also, keep in mind that Objective-C doesn't force you to declare methods ahead of time. I often go along adding methods on the fly while I'm experimenting, and them only go back and add them to the header later if I plan to keep those methods around.

possible circular references
Do you mean double-includes? #import prevents that.

Scott Stevenson — Feb 20, 07 3620 Scotty the Leopard

@Ken: I can know at a glance when code is bracketed, I'm invoking an action, and when I'm using dot-syntax I'm accessing a variable
Just to be clear, the dot syntax does not mean you're directly accessing the instance variable. You're still going through an accessor method.

Michael Stroeck — Feb 20, 07 3621

Is there a simple way to convert python byte-code files (foo.pyc) back into source code?

Decompile used to be able to do this, but it hasn't been updated for 2.4 and 2.5 yet. I have no idea as to the status of the project:
Decompyle

Jim Getzen — Feb 20, 07 3622

@Scott: Not as incovenient as not having headers to look at. :)
You are, of course, free to create your own header-type index files as you develop a Ruby/Python project. ;)

Do you mean double-includes? #import prevents that.
I think I used the wrong terminology. I was referring to the situation where you can't do:

// In Class A's header
#import <ClassB.h>
// followed by some method declaration which uses a ClassB object

// In Class B's header
#import <ClassA.h>
// followed by some method declaration which uses a ClassA object

I realize the solution is to use:
// in ClassA's header
@class ClassB;

// in ClassB's header
@class ClassA;

It's not a difficult solution but, for me, it was another small Obj-C stumbling block -- it proved hard to Google a solution to that one... :)

Ivan — Feb 20, 07 3623

Speaking of scripting languages for Cocoa, I think F-Script provides the best syntax. To me it seems even better than Objective-C itself.
timer := NSTimer scheduledTimerWithTimeInterval: 1/60 target: self selector: tick userInfo: nil repeats: YES.

Chris Ryland — Feb 20, 07 3624

@Ivan: That's Smalltalk syntax.

Ivan — Feb 20, 07 3625

You're right, it is Smalltalk syntax. Or, more accurately, an improved Smalltalk syntax. Here is a nice example of dealing with collections in F-Script vs. Objective-C (putting some transparency in all of the app windows).

Objective-C 2.0:
for (NSWindow *window in [[NSApplication sharedApplication] windows]) { [window setAlphaValue:0.9]; }

F-Script:
NSApplication sharedApplication windows setAlphaValue:0.9

Isn't it nice?

David Wareing — Feb 20, 07 3626

1. Mac application development revolves around Cocoa.

Well, Cocoa Mac application development certainly revolves around Cocoa...

It's about using the right tools for the job.

For a complex project, the time spent in the compiler soon becomes a big factor, and the formal restrictions of your chosen language, IDE and SDK start to limit what you can do, and when.

There are many tasks which are better handed off to a scripting language, where you don't care about object types, compile times and linking errors. If you want to sort a generic list, you really don't want to be making choices about list mutability or wondering whether the list is disposed of properly.

If performance is a concern, again, pick the right tool for the job. We've been embedding Lua for some years now, for real-time use, and it's allowed us to create more stuff, much faster, with fewer bugs. Competitive advantages beat language wars any day of the week. :)

It's also allowed us to create content within the running app, scripting solutions on the fly, thus minimizing the edit-compile-link-run cycle of doom.

Chuck — Feb 21, 07 3627

Yeah, long method names look like crap in Ruby. That's because they look like crap in Objective-C too. The ugliness of [fooObject performBar:thing withBaz:whatsit floobity:boo chocolate:NO burrito:YES] is not much less than fooObject.performBar(thing, :withBaz, whatsit, :floobity, boo, :chocolate, false, :burrito, true), in my personal opinion. They're both packing a metric ton of info into your method signature with nothing more than colons to distinguish it all.

However, Ruby's spryness gives it the edge here in my book. In Ruby, if I find myself having to write out all this crap often, I can metaprogram it out of sight in one line of code. Heck, I could make it so all the arguments are passed in as a semantically accurate dictionary and have the runtime automatically put them in the right order. Objective-C could do something similar to the first option with a macro, but it would be much less elegant and macros are gross anyway.

victor — Feb 21, 07 3628

With all this hype about scripting languages and Cocoa, I thought I would also post an English translation of some exercises I'm doing in public in order to learn RubyCocoa. They're from Hillegass' book, so if you're familiar with them (and being a reader of Theocacao, I guess most of you are) you'll be able to see how Ruby compares to Objective-C.
I also plan to use C#, so if you come from the dark side you'll also find something familiar to relate to.

I don't have access to XCode 3 and Objective-C 2.0, so that's my only way of seeing how garbage collection feels with Cocoa.

Scott, if you dislike this blatant self promotion, feel free to autorelease this comment ;)

Scott Stevenson — Feb 21, 07 3629 Scotty the Leopard

@Chuck: The ugliness of [fooObject performBar:thing withBaz:whatsit floobity:boo chocolate:NO burrito:YES] is not much less than fooObject.performBar(thing, :withBaz, whatsit, :floobity, boo, :chocolate, false, :burrito, true).

Hmmmm. Whatever you say. :)

I could make it so all the arguments are passed in as a semantically accurate dictionary and have the runtime automatically put them in the right order. [...] Objective-C could do something similar to the first option with a macro

Macros? Dude, this is Objective-C. We don't mess around. It's not just C with some extra syntax, it's a fully dynamic language. You can intercept incoming messages, chop them up, alter the selector string, and redirect them. That's how NSUndoManager works, and that's why code can be loaded on the fly. Take a look the posts on NSInvocation and forwarding invocations. I believe the syntax for this stuff is a lot simpler in Objective-C 2.0.

Michael Stroeck — Feb 21, 07 3631

In Ruby, if I find myself having to write out all this crap often, I can metaprogram it out of sight in one line of code.

Ah, but you can do that in Obj-C, too:
#import "FuckYouMaintainer.h"

I keeeed, I keeed :-)

Seriously, though, if you find yourself typing anything longer than 4 characters even once, you need to look up the term "autocompletion".

Marco T. — Feb 21, 07 3632

There is a way to make the use of NSInvocation much easier: CInvocationGrabber

Jon H — Feb 22, 07 3638

You can definitely do Objective-C coding without getting into the hairy parts of C.

I started coding Objective-C before I learned C, having only Applesoft Basic, Hypertalk, and Pascal under my belt. And that was back in the days before autorelease pools and NSString.

The only hard part was when the API requires you to pass in a pointer to a buffer, or that kind of thing. That's relatively rare, however.

Even now, while I know C, I'm not what I call a 'gcc-level c programmer'. There's stuff in big, hardcore C programs that I still have no idea what it is.

Tom — Feb 25, 07 3651

@Scott Guelich: The long Ruby line definitely looks odd to me. I'm a compulsive line-breaker/indenter/vertical aligner in scripting languages (which is why I never could use Python...), so I'd certainly reformat that.

Python doesn't care about whitespace between tokens. Lines can be joined explicitly with backslash and are joined implicitly within parentheses, brackets, or braces. So you certainly can line up your conditions, arguments, etc. in Python.

Neither Python nor Ruby will let you insert whitespace into a method name, though, so there isn't much you can do with the first RubyCocoa example (other than rewrite it for objc_send).

@Chris: Plus, indentation is not significant, and thus you don't have the Pythonian "why am I getting a random syntax error in perfectly legitimate code on line 2661?<...16 hours pass...>Oh, there's a tab instead of some spaces on line 45, and somehow it was OK until I added this new code..."

If you can't be consistent, run tabnanny.

@Ken: I can know at a glance when code is bracketed, I'm invoking an action, and when I'm using dot-syntax I'm accessing a variable.

Other languages do that with trailing parentheses instead of enclosing brackets, and ObjC 2.0 throws that out the window anyway.

@Scott Stevenson: Some of this may come down to project size and whether you're the only author or not, buy having a nice, summarized view of all the methods sure seems pretty nice to me.

That's (among other things) what doc tools are for.

Scott Stevenson — Feb 25, 07 3652 Scotty the Leopard

@Tom: That's (among other things) what doc tools are for
In theory, yes. However, the docs can be out of date without any notice, but the compiler will tell you when the header is out of date.

Tom — Feb 26, 07 3658

However, the docs can be out of date without any notice, but the compiler will tell you when the header is out of date.

If you want "just a list of the class contents", the docs can be autogenerated.

nikolaus — Dec 20, 08 6568

The question "who's scared of header files" makes me want to say: Not me! I am not scared of header files. They are just totally unnecessary and get in the way of coding. One more thing I need to think of, and for no reason at all. I am architecting very large systems in Java, I have never missed header files.

I wouldn't mind so much if XCode were an actually good IDE a'la Eclipse or IDEA. Writing a new method would then work like this: 1 - Write it straight into the .m file. It ends up with a warning, one-click quick fix offers to add the definition into the corresponding .h file, done in the blink of an eye. But that's not what XCode does. [Note to Apple: XCode still sucks, there is no excuse, a glorified text editor just isn't good enough, this is not 1998.]

I find obj-c extremely painful but admittedly most of the pain is inflicted by the manual memory management and that's fixed in 2.0. Unfortunately not on the iPhone yet, so I can't use it.

Compared to Ruby there is still lots of code clutter in a typical Objective C class. So I just want to point out why Ruby is superior: Less code means not less typing, but rather a better focus on the function. In Ruby, a source file contains nearly 99% pure function. In the same class in Objective-C, you will see lots of stuff that is irrelevant to the function, things that the compiler wants, funny little symbols, pointers * which you can ignore (then why are they there), its a mess.

Scott Stevenson — Dec 20, 08 6570 Scotty the Leopard

@nikolaus: The question "who's scared of header files" makes me want to say: Not me! I am not scared of header files. They are just totally unnecessary and get in the way of coding.

The first programming languages I used were scripting languages, so I know exactly what you mean. When I first started with C and Objective-C, I wondered why you'd want a separate file that just lists functions. Eventually, though, I came to the conclusion that header files are so simple that it's not worth worrying about whether they should be there or not.

That said, I do appreciate them when trying to figure out a 16k line class file. Yes, there are documentation files, but often I just want to a see a straight list of functions that the compiler approves of. In any case, the main reason they need to be there is for transparent C compatibility.

I wouldn't mind so much if XCode were an actually good IDE a'la Eclipse or IDEA. Writing a new method would then work like this: 1 - Write it straight into the .m file. It ends up with a warning, one-click quick fix offers to add the definition into the corresponding .h file, done in the blink of an eye. But that's not what XCode does.

There's no reason that feature couldn't be in Xcode, so you should file an enhancement request. I used Eclipse for several months. I agree it has great functional features, but the user experience is far from what I want in a Mac app. What I'd like is for Apple to roll all of the great Eclipse features into the Xcode UI model.

Compared to Ruby there is still lots of code clutter in a typical Objective C class. So I just want to point out why Ruby is superior

I love Ruby. I'm a huge fan. But I don't think it's a better language for Cocoa than Objective-C is. Just as Rails was designed for Ruby, Cocoa was designed for Objective-C. For both frameworks, the entire design philosophy revolves around the language.

pointers * which you can ignore (then why are they there), its a mess.

The pointer symbols are there to satisfy C. I complete agree with you that it would better if we didn't need them, but the transparent integration with C makes it worthwhile. It's hard to overstate just how valuable that is for desktop apps.

Fredrik W — Jan 11, 09 6589

I just wanted to make you aware of MacRuby which is an Apple project (if I recall correctly) that seamlessly bridges ruby 1.9 and cocoa together.

This means that they've gotten rid of casting between NSStrings and Ruby strings etc, which really speeds things up.

Since named parameters is an inherent feature of Ruby 1.9 you won't need to use hash literals as a replacement anymore. :)

I suggest you check out http://www.macruby.org/trac/wiki/MacRubyTutorial for some examples.

lowell — Jan 11, 09 6591

(I'm not intentionally misformatting this. I'm not sure if it's convention to break these things up into multiple lines.)

aww.. respect for our conventions? makes me all warm inside

anyways.. yeah look into what fredrik said above me; there was also a talk given at rubyconf 08 about macruby that you can catch at confreaks if you'd rather watch things; it's about an hour long.

rebo — Jan 11, 09 6592

to configure a window instance in cocoa:

win = NSWindow.alloc.initWithContentRect [10,20,300,300],
:styleMask => (NSTitledWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask |
NSResizableWindowMask)

and in hotcocoa built on macruby:

win = window :frame => [10,20,300,300]

from ...http://www.macruby.org/trac/wiki/HotCocoa

So whilst you can argue that cocoa's syntax has clarity it can often be overly verbose and unnecessary.

sanbit — Jan 12, 09 6593

Macruby should solve all the problems you mentioned, so you really will have the best of both worlds. Go ruby!

Shashi P — Jan 14, 09 6595

In my 12 years of programming, Ruby is the cleanest syntax I have come across. I have been struggling with portions of Obj-C syntax. Ofcourse Obj-C 2.0 seems to have borrowed some from Ruby/Rails. It will be great to use Ruby syntax and let the compiler figure out how to to feed it to the machine/cpu.

Clay Bridges — Feb 09, 09 6609

If you are truly interested in the challenges of Cocoa bridges, or these types of interlanguage/library bridges in general, then this article{/url] by Tim Burks is really essential reading.

Essentially, after working withtwo Ruby/Cocoa bridges, Tim gave up on the idea, and decided to build a new language on top of Objective C and the Foundation classes. It's a Lisp-alike, and is called
Nu.

That's very much the strategy that MacRuby has going, and it seems like it is the winning one. Were these alternatives available for iPhone development, I would definitely be writing most of my application in one of Nu, MacRuby, or F-Script.

Clay Bridges — Feb 09, 09 6610

Re: above misformatting:

  1. Man, I knew I should have used Markdown.

  2. Is it karma that the formatting hung on using a brace instead of bracket?

Jay Kickliter — Mar 13, 09 6623

I know much of this is out of date, but I have a personal experience to share.

I really enjoy embedded programming, and maybe that is shaping my view of learning Application programming on a Mac. Nevertheless, I tried to learn RubyCocoa/MacRuby. But after a bit of frustration, I commited myself to learning Cocoa/Objc. I just couldn't see the benefit of Ruby/Python. Mayby some loops would be easier to do, but I just don't see the benefit. Especially since XCode autocompletes. It's not like there's that much more typing to do. I really like how readable objective-c is.

Not sure what my point is, other than I'm one of those casual programmers that the bindings where meant for, but found it to be a bigger pain than it was worth. Cocoa was designed with objective-c and has been around a long time, it works well. I just don't want Apple to overaccomodate different languages. With so many choices, you're actually making it harder for people to get started-the same people you were trying to help along. I don't want choices, just a platform that works very well and is consistant.

Susan — Apr 09, 09 6682

Objective-C does *NOT* have "named arguments".

Never has.

Never will.

Research paper — Dec 29, 09 7056

Great materials for making a good research.




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.





Copyright © Scott Stevenson 2004-2015