Stop to Smell the Roses

I would love to build a better Objective C language. It would be a language that embraces the functional programming world and the imperative programming world, the world of dynamic runtimes and static types, and build a bridge to the future from the past.

The following is taken from some of my notes, so the code samples might be a bit rough.

Class definitions would be simple and straight forward:

' All classes derive from `NSObject` by default. Use the `derives <class>` syntax
' to subclass differently. Also, use `implements <type>, <type>, ...` for protocols.
interface Person
    ' The `let` keyword creates readonly properties.
    let firstName :: NSString
    let lastName :: NSString

    ' The `var` keyword creates read/write properties.
    ' The `[copy]` is the attribute applied to the property, in this case
    ' all writes to `emailAddress` will create a copy of the incoming value.
    var emailAddress :: NSString [copy]

    ' initializer with parameters, defaults to returning `instancetype` in ObjC
    def initWithFirstName::NSString lastName::NSString
        _firstName = firstName
        _lastName = lastName

    ' a message name with a single parameter, defaults to returning `void` in ObjC
    def say message::NSString
        log("\(firstName) says \"\(message)\"")

    ' A simple message that returns a `NSString`
    def fullName -> NSString
        return "\(firstName) \(lastName)"

All function definitions would allow for partial application:

def sum x: Number -> y: Number -> Number
    return x + y

let sum1 := sum 1
let sum2 := sum1 2
let full := sum 3 4
log "sum of 1 + 2 = \(sum2)"

Syntax would be light and free of unnecessary tokens:

' No difference between message calls and function calls
let david := Person newWithFirstName:"David" lastName:"Owens
david.emailAddress := "david@owensd.io"

' Use () to group nested calls for ordering
let sally := (Person alloc) initWithFirstName:"Sally" lastName:"Sue"
sally say:"Hello all the peoples!"

let ages = {
    "Tim":  53,  "Angela": 54,  "Craig":   44,
    "Jony": 47,  "Chris":  37,  "Michael": 34,
}

let people = filter (key => ages[key] < 50) (sort < (ages allKeys))

All of this code can be re-written to ObjC (by a tool). I have prototypes of some of it and manual constructions of others. I know it’s possible and it allows for full interop between this language dubbed Proteus and ObjC.

But… what’s the point?

I don’t mean to ask that as a submission or a throw-in-the-towel remark. But really, what’s the point? Where do I want to go with it? It would be fun to go through designing this out and getting all of the main scenarios working – I haven’t done that since my college days. I don’t even think it’s a super amount of work. But the edge cases will suck. The considerations of certain C constructs will get a bit dodgy. And in order to really get the performance up to par, I’m likely going to need to emit LLVM code instead of going through the ObjC source code, or worse (in my opinion), need to make changes to LLVM or Clang like the Eero project did. And this is before I even get into editor support, code highlighting, debugging, etc…

Swift has it’s warts. It’s a baby that’s trying to grow up quickly in a world that is harsh. The question I’ve been asking myself, both through these posts and throughout the weeks is really this: are Swift’s warts and ugly places worse than those of Objective C’s? Will they be tomorrow?

There will be a lot I miss about ObjC. Hopefully we’ll see more of that over time. But I think it’s time for this station to get back to it’s regularly scheduled program.

Stop to Smell the Roses