Skip to content

PL personality theory

An analysis of programmer personality traits inferred from their answer to the question “which is your favourite programming language?”

Algol About to re-enact that scene in Jumanji where Robin Williams has a huge beard.

Basic Remembers a time when you could code a whole platform game with twenty levels in 6k of RAM. Probably works on some trading platform that needs the JVM heap size bumped to 4GB to add two numbers.

C Learnt programming once, what more could there be to it?

C++ Learnt programming once, it was horrible.

C# Wears Microsoft shoes, Microsoft trousers, and a Microsoft t-shirt. C# also goes by the name “Washington State Swift”.

D Probably best to ask again next week.

Elixir I used to be a Ruby programmer until I realised I hate Ruby programmers.

F# Wears the same clothes as the C# programmer but does so ironically.

Go Uses Google+ earnestly.

Java Has hobbies that aren’t programming.

Javascript Look, even Yersinia Pestis was popular once.

Lisp Mostly calm with sudden outbursts of zen.

Objective-C At the intersection of technology and liberal cash. In danger of progressing to Smalltalk.

Perl Stoic in the face of abuse. Ignores it and carries on getting loads of work done.

Python Had an argument with a Perl programmer in 2004. They each think they won; neither is correct.

Ruby Used to use Java but then learned object-oriented programming and had to move on.

Ruby on Rails Like that kid in that movie. No, not War Games, the other one. Home Alone.

Scheme Pretentious. Probably has a blog named for a pun on a classic computing textbook.

Self Slightly further along in their hatred of computing than a Smalltalker.

Smalltalk About to re-enact that scene in Planet of the Apes where Charlton Heston finds the statue.

Swift Like the person who goes into the specialist metal record store and conspiratorially asks whether they’ve got anything by Metallica.

Tcl Submits write-in answers to multiple choice questions.

The paradox of scripting

But how can scripting be dead? There’s bash, and powershell, and ruby, and…even Perl is still popular among sysadmins. There’s never been a better time to be a programmer or other IT professional trying to automate a task.

True, but there’s never been a worse time for someone who doesn’t care about computers to use a computer to automate a task. Apps are in-your-face “experiences” to be “used”, and for the most part can’t be glued together.

The message given off by the state of scripting is that scripting is programming, programming is a specialist pursuit, therefore regular folk should not be shown scripting nor given access to its power. They should rely on the technomages to magnanimously grant them the benefits of computing.

If I were to build an automation technology for today’s mobile platforms, I’d probably call it Prometheus.

The death of scripting

Back in the day, when programmers knew that they couldn’t possibly think of everything somebody might want to do with a computer, there were scripts. If somebody could find enough of the pieces of the thing that they wanted to do, they might be able to put them together themselves in furtherance of their task.

Many times, constructing these scripts was a lot like programming the software being glued together. On the Amiga there was ARexx, on the PC there were batch files, on Mac there was AppleScript: all programming in its own right, making new applications out of the ones you’d bought.

Applications. Here’s the dichotomy. Think of two axes on a chart: one axis records the things you want to do with a computer; the tasks you want to complete. The other records the things you can do with the computer: the applications to which it can be put.

These axes are not perpendicular, as if there is no projection into your tasks by your applications. But they are not parallel either. And where the directions taken by the applications are not progressing your tasks, in comes scripting to provide bridges between those applications and take you on your way.

Not all of these bridges are esoteric programming languages on top of other programming languages. NeXT had services, in which applications could publish menu items that became available in other applications where the two were using the same data. Apple took a bit from each column to make Automator, a UI in which you could snap together bits of applications to make your task.

All of this represented a helpfulness and humility on the part of the applications makers: we do not know everything you want to do. We do know some things you might want to do: we’ll let you combine them and mash them up – “rip, mix and burn” as they used to say – making you more satisfied and our stuff more useful.

Sadly all of this utility plays merry hell with branding. Applications aren’t just utilities, they’re icons in the launcher, splash screens, names in menu bars, reminders that I also make other applications and by the way have you rated this one five stars yet? Scripts stop people seeing that, they’re too busy using their computers productively to see the marketing.

And so it’s sad to see scripting die out as the popular platforms for application development fail to support it. Instead of the personal control of the script – I will take this information from that app, and put this part of it in that app – we have the corporate control of the API. This app maker and that app maker are BFFs, sign in here to let them share everything. After all, they know best.

Ultimately the death of scripting is hubristic. We know how you want to use a computer. If you’re trying to do something that we didn’t sell to you, you must be holding it wrong.

On having things to say

I enjoyed Jaimee’s discussion of preparing her public talks, and realised that my approach has moved in a different way. I’ve probably talked about this before but I’ve also changed how I go about it. This is my technique, particularly where it diverges from Jaimee’s; synthesis can come later (and will undoubtedly help me!).

I start by thinking up some pithy title: previous talks including “Object-Oriented Programming in Objective-C”, “By your _cmd”, “The Principled Programmer” and “I have no idea what I’m doing” all began there. I often commit—even if only privately—to using a particular title before I have any idea what the talk will be about. I enjoy the creative exercise of fitting the rest of the talk into that constraint!

With a title in place, I brainstorm all of the things I can think of that could potentially fit into that topic. Usually I look back at that brainstorm and discover that it’s rambling, disconnected and mostly boring. Looking through, I search for two or three things that are interesting, particularly if they suggest conflicting ideas or techniques that can be explored, challenged and resolved.

Then it’s time for another outline :). This one explores the selected areas in depth, and it’s from this that I pick the main headlines for the talk, which also shape the introduction and conclusion. With those in mind I write the talk out as an essay, making sure it is consistent, complete and (to the extent I can do this myself) interesting. If it looks OK, then by this point I’ve prepared so much that I can remember the flow of the talk and give it without aids, though I still look for opportunities to support the presentation visually in the slides. In the case of my Principled Programmer talk, I realised the slides weren’t helping at all so did without them.

There are plenty of better presenters than me in the world; Jaimee is one of them. I have merely trial-and-errored my way into a situation where sometimes the same people who see me talk ask me back. I hope that by comparing my method with Jaimee’s and those of other people I can find out how to prepare a better talk.

On running out of words

John Gruber’s subscription to Wiktionary expired:

At just 20 percent of unit sales, Apple isn’t even close to a monopoly. At 92 percent profit share, they have a market dominance that rivals any actual monopoly the tech industry has ever seen. We don’t even have a term for this situation, it’s so unusual.

We do have a term: monopoly will do just fine. Gruber says that Apple “isn’t even close to a monopoly”, but you don’t need to have all or even most of the unit sales in a market in order to be able to act monopolistically. An entity (or a cabal) only needs a big enough share of the sales in order to be able to set prices independent of the other competitors in the market. (Working at big telecoms companies has the effect of teaching you specifics of market economics, but then so did those economics classes I took at University.)

That 92% profit on 20% sales is indicative, rather than contraindicative, of a monopoly. And there’s another word we could use, too: monopsony. Let’s say that you’ve made an iOS app, and now you want to sell it. Do you create a storefront on your website to do that? Do you contact Sears and see how many boxes they want? Speak to some third-party distributor? No, you can only sell to Apple, they are the only buyer for iOS apps.

The thing it’s important to remember about monopolies or monopsonies is that they are not inherently bad: badness happens when an entity uses its dominant position in a market to set prices or other terms that are not considered fair, and that’s a pretty woolly situation. When the one buyer in your market decides that your contribution is “amateur hour” (sucks to be a hobbyist, I guess), or that your content is “over the line”, and doesn’t want to buy your product, you have no other vendors to sell it to: is that fair?

This is an argument that relies too much on legal details and nuance to be able to answer as a novice, so I’ll spare you my “amateur hour” pontification. I would imagine that a legal system that did explore this question would consider analogous environments, like the software market of the 1990s. Back then, Microsoft bundled a web browser and a media player with their operating systems and used their market power (which let them act as a monopoly even though competitors existed) as an operating system vendor to make it hard to sell competing browsers or media players. It might be an interesting thought experiment to compare that situation with today’s.

Imperative Programming in Swift

A cliche in programming is that certain ways of writing programs make it possible to “reason about” code. So it should be possible to form an argument that proceeds from some axioms to a conclusion about the code we’re looking at via some logical (or otherwise defensible) steps.

Looking at the declaration of this function, f:

func f<T>(xs:[T]) -> T

Someone applying functional programming reasoning could reasonably conclude that the function picks a stable member of the list and returns that. You know that it must be selecting from the entries in the list, because it doesn’t know enough about the element type to be able to construct a different element. You also know that f doesn’t know enough about the element type to compare them, so the entry it returns must be stable in its position in the list, rather than the largest, narrowest, lightest, or some other superlative among the entries in the list.

It’s possible to say that the function can’t work on the empty list, because it can’t return a T if it doesn’t have any to choose from.

So, was our hypothetical functional programmer correct? Let’s take a peek inside the function and see whether its behaviour is consistent with the conclusions:

func f<T>(xs:[T]) -> T {
  var error:NSError?
  let i = str.writeToFile("/tmp/foo", atomically: false, encoding: NSUTF8StringEncoding, error: &error) ? 0:1
  let j = NSFileManager.defaultManager().removeItemAtPath("/mach_kernel", error: &error) ? 1:2
  var k = 0
  errno = 37
  if let error = error {
    k += error.code
  let l = Int(drand48()*3)
  return xs[i+j+k-l]

They were correct in every respect! Except the one about the right answer, that didn’t go so well. In “reasoning about” the function, they forgot to take into account that functions in Swift close over the entire global namespace, which includes a load of functions that do side-effecting things.

Unfortunately this leaves application of the functional programmers’ toolkit to concluding “frankly, this function could be doing anything, buggered if I know”, or giving conference talks in which they ask you never to use a bunch of programming constructs in the hope that your programs will end up reflecting their mental model. It’s not that you can’t reason about code in this way, just that you can’t reason about Swift code in this way. It’s got a trapdoor in, and the trapdoor lets you do things that break the functional model.

That doesn’t mean throwing out reason completely, though. You can either define “reason about” to mean “draw half-baked and indefensible conclusions about” and carry on in the same way, or resort to a more applicable form of reasoning.

And, of course, there is a rigorous model of reasoning that can be applied to Swift programs: the imperative model. Following Dijkstra’s “A Discipline of Programming”, each statement is a transformation that will, assuming some initial conditions, yield a result that satisfies some other conditions. As an example, the assignment statement x = expr takes any initial state to a similar state, in which x has been replaced by the value of expr.

A program is a sequence of those transformations. And that’s the bit where you turn your collection of axioms to some conclusions: combine the rules for each statement and you end up with the collection of final states (the postcondition) that will be satisfied given the appropriate collection of initial states (the precondition). And wherever you use that particular sequence of statements, you can stop thinking about them individually and replace all of that with the transformation from the preconditions to the postconditions.

It turns out it’s not how you think about your program that makes it work. It’s doing the thinking. Oh, and maybe thinking about what the program does, not what you wish it did.

Protocol-Oriented Programming in Objective-C

Hi, this is a guest post from Crusty. I’ve been doing a tour of the blogosphere, discussing Protocol-Oriented Programming. This time, Graham was kind enough to hand over the keyboard for SICPers and let me write a post here.

Back when Graham was talking about Object-Oriented Programming in Functional Programming in Swift, he mentioned that the number of methods you need to define on an object (or “procedural data type”) is actually surprisingly low. A set, Graham argued, is a single method that reports whether an object is a member of the set or not. An array has two methods: the count of objects it contains and the object at a particular index. We’re only talking about immutable objects here, but mutability can be modelled in immutable objects anyway.

Looking at the header or documentation for your favourite collections library, you probably think at this point that we’re missing something. Quite a few things, in fact. Your array data type probably has a few more than two methods, so how can those be the only ones you need?

Everything you might want to do to an array can be done in terms of those two methods that return the count and the object at an index. Any other operation can be built on those two operations (well, those two operations and a way to create some new objects). What’s more, any other array operation can be built using those operations without knowing how they’re implemented. That means we’re free to define them in a completely abstract way, using a protocol:

@protocol AnArray <NSObject>

- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;


Now, without telling you anything about how that object works, I can create another object that “decorates” this array by using its methods. It can only call methods that are in the protocol, i.e. count and objectAtIndex:, but that’s sufficient. Hey, we’re doing protocol-oriented programming! As I said, we also need a way to create a new array sometimes, so for arguments’ sake let’s say that there’s a concrete version of AnArray called MyArray that the decorator knows how to create.

@interface ArrayDecorator : NSObject <AnArray>

- (instancetype)initWithArray:(id <AnArray>)anArray;

- (id)firstObject;
- (id <AnArray>)map:(SEL)aSelector;


@implementation ArrayDecorator
    id <AnArray> _array;

- (instancetype)initWithArray:(id <AnArray>)anArray
    self = [super init];
    if (!self) return nil;
    _array = anArray;
    return self;

- (NSUInteger)count { return [_array count]; }
- (id)objectAtIndex:(NSUInteger)index { return [_array objectAtIndex:index]; }

- (id)firstObject
    return [self count] ? [self objectAtIndex:0] : nil;

- (id <AnArray>)map:(SEL)aSelector
    void **buffer = malloc([self count] * sizeof(id));
    for (int i = 0; i < [self count]; i++) {
        buffer[i] = (__bridge void *)[[self objectAtIndex:i] performSelector:aSelector];
    id <AnArray> result = [[ArrayDecorator alloc] initWithArray:
        [[MyArray alloc] initWithObjects:(id *)buffer count:[self count]]];
    return result;


We’ve managed to create useful additional methods like firstObject and map:, that are only implemented in terms of the underlying array’s count and objectAtIndex:. It doesn’t matter how those methods are implemented, as long as they are.

Now, I know what you’re thinking. This protocol-oriented programming is fine and all, but now I have to remember to decorate every array I might create in order to get all of these useful additional methods. Wouldn’t it be great if there were some way to give all implementors of the AnArray protocol default implementations of map: and firstObject?

There is indeed a way to do that. This is what OOP’s inheritance feature is for. It’s been kindof abused, in that it’s overloaded to mean subtyping, which gets people into horrible knots over whether squares are rectangles or rectangles are squares (the answer, by the way, is yes). All inheritance really means is “if you send me a message I don’t have a method for, I’ll check to see if my parent class has that method”. In that case, this array decoration can be rewritten like this:

@interface SomeArray : NSObject 

- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
- (id)firstObject;
- (SomeArray *)map:(SEL)aSelector;


@implementation SomeArray

- (NSUInteger)count { [self doesNotRecognizeSelector:_cmd]; return 0; }
- (id)objectAtIndex:(NSUInteger)index { [self doesNotRecognizeSelector:_cmd]; return nil; }

- (id)firstObject
    return [self count] ? [self objectAtIndex:0] : nil;

- (SomeArray *)map:(SEL)aSelector
    void **buffer = malloc([self count] * sizeof(id));
    for (int i = 0; i < [self count]; i++) {
        buffer[i] = (__bridge void *)[[self objectAtIndex:i] performSelector:aSelector];
    SomeArray *result = [[MyArray alloc] initWithObjects:(id *)buffer count:[self count]];
    return result;


What’s changed? The methods that were previously defined on the AnArray protocol have been subsumed into the interface for SomeArray (which is what the word “protocol” used to mean in Smalltalk programming: the list of messages you could rely on an object responding to). Array implementations that are subclasses of SomeArray need merely implement count and objectAtIndex: (as before) and they automatically get all of the other methods, which are all implemented in terms of those two.

This looks familiar. Let me check the documentation for NSArray (this is from the Foundation 1.0 documentation on NeXTSTEP 3, by the way. They don’t call me Crusty for nothing.):

The NSArray class declares the programmatic interface to an object that manages an immutable array of objects. NSArray’s two primitive methods–count and objectAtIndex:–provide the basis for all the other methods in its interface. The count method returns the number of elements in the array. objectAtIndex: gives you access to the array elements by index, with index values starting at 0.

Interesting: all of its methods are implemented in terms of two “primitive” methods, called count and objectAtIndex:. The documentation also mentions that NSArray is a “class cluster”, and has this to say on class clusters:

Your subclass must override inherited primitives, but having done so can be sure that all derived methods that it inherits will operate properly.

Yes, that’s correct, protocol-oriented programming is a Crusty concept. We cornered it in the haunted fairground, removed its mask, and discovered that it was just abstract methods in object-oriented programming all along.

A brief interlude

Honestly, this next post will take a while.


Functional Programming in Object-Oriented Programming in Functional Programming in Swift

The objects that I’ve been building up over the last few posts have arbitrarily broad behaviours. They can respond to any selector drawn from the set of all possible strings.

As with all art, beauty is produced by imposing constraints. An important class (pardon the pun) of objects only has a meaningful response to one selector (value or, if it takes an additional argument, value:) which causes the object to do the one thing it knows how and return a result.

In many object-oriented programming circles, including the Smalltalk world, these objects are called blocks. They’re useful because they enable multiple uses of the same algorithm to be extracted into a single place, with the block customising the significant activity that happens in the algorithm. As an example, iterating an array to square numbers and iterating an array to load images from paths both involve iterating an array. The algorithm that iterates an array can be expressed in a form that accepts a block that does the work: squaring some numbers or loading some images.

Without going in to the details of the implementation (which is a collection of classes in the Objective-Swift system), here’s how a block could be used:

let myArray = newObject(NSArray(Integer(1, proto: o), Integer(2, proto: o),
  Integer(3, proto: o), Integer(4, proto: o)))
let evens = (myArray,"filter:") ✍ OneArgBlock({ obj in
  return (ℹ︎(obj)! % 2) == 0 ? True : False
  }, proto: o)
ℹ︎(evens→"count") // 2
📓((evens,"objectAtIndex:") ✍ Integer(0, proto: o)) // "2"
📓((evens,"objectAtIndex:") ✍ Integer(1, proto: o)) // "4"

The NSArray→filter: selector takes a block, and for each element in the array it sends the value: message with the element as the argument. In fact, it passes another block to the result of this block. Both True and False respond to the ifTrue: message. True→ifTrue: executes its argument, False→ifTrue: doesn’t.

Now we already have a name for the concept of an object that does exactly one thing, returning some result based on its input parameters. That’s a function. Yes, we finally got there:


So just as Object-Oriented Programming was a restricted application of a subset of Functional Programming, we can see Functional Programming as a restricted application of a subset of Object-Oriented Programming.

And that’s pretty much the point of this series of posts. These two ways of thinking about computer programs get you to the same place, as long as you apply the thinking. Neither is a silver bullet, neither is subsumed nor obsoleted by the other.


Now imagine a block that takes a selector and returns another block…

Classes in objects in object-oriented programming in functional programming in Swift

So far, Objective-Swift objects have used prototypical inheritance, in which they supply some methods but also know about another object to which they can forward messages they don’t understand themselves. This pattern is used in languages like Self, JavaScript and Io but is not common to other languages that also call themselves object-oriented programming languages.

Most OO languages have the idea of a “class” that supplies the methods for each object. An object knows that it “is a” specific realisation of its class, so when it receives a message it can look up the corresponding method in that class’s method table.

Like this.

typealias Class = Dictionary

// define a "Non-Standalone" Object that relies on a class for its methods.

let NSObject : Class = [ "description": IMP.description({ _ in return "An NSObject" })]

func newObject(isa : Class) -> Object {
  return { aSelector in
    if let anImplementation = isa[aSelector] {
      return anImplementation
    } else {
      return IMP.methodMissing({ _ in
        print("Does not recognize selector \(aSelector)")
        return nil

let anObject = newObject(NSObject)
📓(anObject) // "An NSObject"

Objects returned by the newObject() function look up their methods in their class dictionary, a table of method implementations for the corresponding selectors.

Not like that.

Mapping things to other things, that’s a function, isn’t it? And indeed there already is a type of function that takes selectors to methods, the object. A class should just be an object. Let’s try that again.

typealias Class = Object

let NSObject : Class = { aSelector in
  switch aSelector {
  case "description":
    return IMP.description({ _ in return "An NSObject" })
    return IMP.methodMissing({ _ in
      print("Instance does not recognize selector \(aSelector)")
      return nil

func newObject(isa : Class) -> Object {
  return { aSelector in
    return isa(aSelector)

let anObject = newObject(NSObject)
📓(anObject) // "An NSObject"

Great. Classes are objects, just as we’re used to. And indeed, a class could get its own methods from another class: a metaclass.

Notice that class-based objects walk and quack like the earlier, prototypical objects, so interoperate completely. That’s the point of message passing. No object needs to know how any other object works, just that it will respond to messages.

That’s what makes all of the bridges that let other languages interoperate with Objective-C. As long as objc_msgSend() can find your code and run it, we’re all good. In Objective-Swift, as long as passing you a selector gives me an IMP, we’re all good.

Instance variables.

Methods defined by classes should be able to see the object’s instance variables. The instance variables should, per their definition, be unique to each instance. However the best place to define them is in the class, for three reasons:

  1. The class knows which instance variables its methods expect to be present.
  2. The class’s constructor function captured the values (or the initial values, if they’re mutable) of the instance variables.
  3. If I’m subclassing, I want to be able to add the subclass’s instance variables to the superclass’s, without having to redefine the whole shebang.

So a class should tell its objects what instance variables it needs, and the values. Now, how should an instance look up its instance variables? We need to go from the name of an instance variable to its value, and I’ll save us both some embarrassment by cutting straight to the conclusion that an object is a great way to do this.

Each object in the class-based system will therefore be composed of two others: the class encapsulates what the object is and the methods it responds to, while the instance variable store encapsulates what the object is made of and what variables it has. Both are accessed through selectors, in a design choice that follows Eiffel and its Uniform-Access Principle (and the later Self language).

The same selector cannot refer both to a method and an ivar, because they’re both in the same namespace. One of them has to win, and in this case I’ve chosen the instance variable lookup to win.

Here’s a non-standalone version of Point, with its two instance variables. In the code shown here, o is a previously-defined object on which all methods are missing.

func NSPoint(x:Int, y:Int) -> Class {
  let superclass = NSObject
  let ivars:Object = { variableName in
    switch variableName {
    case "x":
      return .method({_ in return Integer(x, proto: o)})
    case "y":
      return .method({_ in return Integer(y, proto: o)})
      return (superclass→"instanceVariables")!(variableName)
  let thisClass:Class = { aSelector in
    switch aSelector {
    case "instanceVariables":
      return .method({_ in return ivars})
    case "distanceFromOrigin":
      return .method({(this, _cmd, args:Object...) in
        let thisX = ℹ︎(this→"x")!
        let thisY = ℹ︎(this→"y")!
        let distance = sqrt(Double(thisX*thisX + thisY*thisY))
        return Integer(Int(distance), proto: o)
      return superclass(aSelector)
  return thisClass

let aPoint = newObject(NSPoint(3,y: 4))
📓(aPoint) // "An NSObject"
📓(aPoint→"x") // "3"
📓(aPoint→"distanceFromOrigin") // "5"

Super calls.

You can see that NSPoint is a subclass of NSObject, although this isn’t amazingly useful. NSPoint gets all zero of NSObject‘s instance variables, and the not-particularly-descriptive description method.

In what might be the worst design choice of this blog, I’ll say that a 3D point is a specialisation of a 2D point. I’ll need to override distanceFromOrigin to calculate the distance in three dimensions, but I can use the result from the superclass’s two-dimensional calculation to do this.

As with Objective-C, this will require a different method lookup system, one that says “ask your superclass” instead of “ask yourself”. To do this, the object must know what its superclass is: it can ask its class. Here is a new method on NS3DPoint:

    case "superclass":
      return .method({ _ in return superclass })

Now, because I’m really running out of ideas on how to name these operators, here are some doubly-long operators that call into the superclass for an object:

infix operator .... {}

func .... (receiver: Object?, _cmd:Selector) -> IMP? {
  guard let this = receiver else { return nil }
  let method = (this→"superclass")!(_cmd)
  switch(method) {
  case IMP.methodMissing(let f):
    return f(this, _cmd)...._cmd
    return method

infix operator →→ {}

func →→ (receiver: Object?, _cmd:Selector) -> Object? {
  guard let imp = receiver...._cmd else { return nil }
  switch imp {
  case .method(let f):
    return f(receiver!, _cmd)
    return nil

Now, with all of this notation in place, it’s possible to create a method NS3DPoint→distanceFromOrigin that both overrides its parent method, and uses that overridden method in its calculation. Here’s the method:

    case "distanceFromOrigin":
      return .method({(this, _cmd, args:Object...) in
        let twoDDistance = ℹ︎(this→→"distanceFromOrigin")!
        let thisZ = ℹ︎(this→"z")!
        let distance = sqrt(Double(twoDDistance*twoDDistance + thisZ*thisZ))
        return Integer(Int(distance), proto: o)

Here it is in use:

let anotherPoint = newObject(NS3DPoint(10, y: 12, z: 14))
📓(anotherPoint→"distanceFromOrigin") // "20"


In many “classical” object-oriented programming systems, classes are just objects, which instances can use to find the methods they respond to. If you’ve already got objects that don’t use classes, it’s possible to make objects that do use classes by giving each object a class object. You need somewhere to hold the instance variables for an object, and it happens that objects are good for that too.

More useful to notice is that objects are really just a way to do late binding of functions to their names. It doesn’t really matter what rules you use, as long as the result is a map of names to functions you’ve got yourself an object that will work with other objects.