Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Just a note as to the distinction in dispatch mechanisms here: ObjC, Ruby, and other Smalltalk-like languages use “message passing”, which encapsulates a call symbolically as a “message” (name + args) then does a “dispatch” operation that looks up the code through the inheritance chain and runs it. If you override the dispatch mechanism you can do things like delegation or forwarding with great flexibility.

NewtonScript does the symbol lookup first (same as for any member lookup) and retrieves a function/closure object, then executes that function with an implicit “this” argument. Closer to the way JavaScript, Python, Go, or C++ do it.



Something like: implementing your own small if/else DSL [1]! I'm not saying that this is a good idea. I am saying that this is possible with overriding the method dispatch :')

In Pharo (a Smalltalk descendant) one needs to override the doesNotUnderstand method.

The thing is: the whole DSL that I made (with if/else/elif) is its own method call. It's exactly one method call. So if you write "code" like that, then you'll always have a variable length type of method call that Pharo won't understand. By overwriting it and checking for the right symbols (If, Else and Elif) one can group them together and mimic if-statement type of behavior.

I think it's really wild, awesome and fun.

[1] https://www.youtube.com/watch?v=BUEnRrUZ-Ug


> Of you override the dispatch mechanism…

AKA Method Swizzling. ObjC developers took advantage of this feature and it was a wild frontier (but illegal in Apple’s eyes).

1: https://nshipster.com/method-swizzling/


Method swizzling is actually something different: replacing a concrete method definition.

There really isn't any good way of messing with the underlying message dispatch mechanism, objc_msgSend() unless you do DYLD interposing or some such hackery.

However, objc_msgSend() has enough hooks to allow you to do custom dispatching, but only after the normal lookup has failed.

Initially there was -forward:: which essentially gave you a pointer to a stack frame. Later, -forwardInvocation: gave you an NSInvocation, which was the message wrapped in an object. Nice, but slow. Since a lot of time the idea was just to forward the exact same message to another object, we later got a new intercession point that allowed you to return that other object.

But again, all these only got activated once ordinary lookup failed, hence NSProxy and friends (objects with very few methods implemented).

Oh, and there was the nil class hook: objc_msgSend() short-circuits when the receiver is nil, but for a while you could theoretically set a class to which the messages to nil would be dispatched. I tried it out a couple of times and it worked, but it was never really used, mostly undocumented and has since been removed, AFAICT.


Right, method swizzling is actually "monkey patching" in ruby parlance. You arent replacing the _dispatch mechanism_, you are relying on the fact that its a dynamic lookup to replace that entry in the lookup table at runtime. Which then the dispatch mechanism happily plays along with.


Ah my bad, I jumped the gun without reading the whole comment and it's context.


The original Doom was developed on NeXT, so a lot of the tooling (like DoomEd) was written in ObjC. If I recall correctly they abused this whole thing by making proxy objects that would happily call methods across the network, so they had level cooperative editing back in the early 90s (minus all the concurrent edit stuff we take for granted today, of course).


Check out NSProxy :) - fun fact it's the only* other root class in Foundation, a peer of NSObject - and NSDistantObject.

Part of the super-deprecated Distributed Objects precursor to XPC. [1]

[1] https://developer.apple.com/library/archive/documentation/Co...


There was even PDO and a bridge to MS OLE

https://en.wikipedia.org/wiki/Portable_Distributed_Objects

Loong long ago…


I was trying to google for some sort of reference to what I meant, but couldn't find one (found this thread instead...) but NSProxy seems to have been around long enough that it might well be the core of the implementation for what I was talking about.


Thank you for not mentioning CORBA.


Yes and no. Concurrency was still a problem that got short shrift. But the "overload doesNotUnderstand:, serialize the message and dispatch it over the network" was a fun way to do rpc-ishness in Smalltalk and ObjC before people got hung up on writing IDLs. (Looking at you, CORBA)

I'm reminded of Larry Wall's quote: "languages differ not in what they make possible, but in what they make easy."

Smalltalk and ObjC made proxy objects easy.


What’a the pros / cons with dispatch compared to the latter?


With the latter approach, you can save the bound method as a value. Depending on the way this is implemented, it can carry some additional overhead—because you create an object to represent the closure. The Objective-C dispatch, objc_msgSend, is very fast and allocates no memory. This is an implementation detail, however.

I’d say that there’s a big difference between Python/Go and JS/C++.

In Python, obj.method returns a bound method call—basically, a function that saves obj and passes it in as the first argument, and obj.method() has exactly the same semantics as x=obj.method;x(). In JS, obj.method returns an unbound method, and the equivalent to obj.method() is x=obj.method;x.call(obj).

Objective-C has some nice semantics and a little bit of typing to help you out here.


objc_msgSend does allocate memory - for the IMP caches, and the class initialization costs (and calling +initialize) the first time you message a class.


Sure. It allocates zero heap memory per call, amortized.


Isn’t this what inspired the win api? The message loop, and window messages. Architecturally it’s the same




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: