The
id-subset[1] of Objective-C is also memory safe, just like the Smalltalk it copied.
And Objective-C is a credible C competitor, partly because it is a true superset of C, partly because you can get it to any performance level you want (frequently faster than equivalent practical C code [2]) and it was even used in the OS kernel in NeXTStep.
Now obviously it's not done, as it is a true superset and thus inherits all of C's non-safety, and if you were to just use the id-subset that is memory safe, you wouldn't be fully competitive.
However, it does show a fairly clear path forward: restrict the C part of Objective-C so that it remains safe, let all the tricky parts that would otherwise cause non-safety be handled by the id-subset.
That is the approach I am taking with the procedural part of Objective-S[3]: let the procedural part be like Smalltalk, with type-declarations allowing you to optimize that away to something like Pascal or Oberon. Use reference counting to keep references safe, but potentially leaky in the face of cycles. Optional lifetime annotations such as weak can be used to eliminate those leaks and to eliminate reference counting operations. Just like optional type declarations can reduce boxing and dynamic dispatch.
[1] https://blog.metaobject.com/2014/05/the-spidy-subset-or-avoi...
[2] https://www.amazon.com/gp/product/0321842847/ref=as_li_tl?ie...
[3] https://objective.st/
However, it is important not to conflate "scripting language" and "dynamic language" and "interpreted". While there is some correlation there, it is not a necessary one.
Objective-C is an example of a fast AOT-compiled pretty dynamic language, and WebScript was an interpreted scripting language with pretty much identical syntax and semantics.[2]
What do I mean with fast? In my experience, Objective-C can be extremely fast [3], though it can also be used very much like a scripting language and can also be used in ways that are as slow or even slower than popular scripting languages. That range is very interesting.
So I don't actually think the tradeoff you describe between low-level unergonomic fast and high-level ergonomic slow is a necessary one, and one of the goals of Objective-S is to prove that point.[4]
So far, it's looking very good. Basically, the richer ways of connecting components appear to allow fairly simple "scripted" connections to achieve reasonably high performance [5]. However, I now have a very simple AOT compiler (no optimizations whatsoever!) and that gives another factor 2.6 [6].
Steve Sinowsky wrote: "Does developer convenience really trump correctness, scalability, performance, separation of concerns, extensibility, and accidental complexity?"[7].
I am saying: how about we not have to choose?
And I'd much rather debug/modify semantically rich, high-level code that my LLM generated.
[1] https://blog.metaobject.com/2015/10/jitterdammerung.html
[2] https://blog.metaobject.com/2019/12/the-4-stages-of-objectiv...
[3] https://www.amazon.com/gp/product/0321842847/ref=as_li_tl?ie...
[4] https://objective.st
[5]mpweiher (3) on hackernews27w The id-subset[1] of Objective-C is also memory safe, just like the Smalltalk it copied.
And Objective-C is a credible C competitor, partly because it is a true superset of C, partly because you can get it to any performance level you want (frequently faster than equivalent practical C code [2]) and it was even used in the OS kernel in NeXTStep.
Now obviously it's not done, as it is a true superset and thus inherits all of C's non-safety, and if you were to just use the id-subset that is memory safe, you wouldn't be fully competitive.
However, it does show a fairly clear path forward: restrict the C part of Objective-C so that it remains safe, let all the tricky parts that would otherwise cause non-safety be handled by the id-subset.
That is the approach I am taking with the procedural part of Objective-S[3]: let the procedural part be like Smalltalk, with type-declarations allowing you to optimize that away to something like Pascal or Oberon. Use reference counting to keep references safe, but potentially leaky in the face of cycles. Optional lifetime annotations such as weak can be used to eliminate those leaks and to eliminate reference counting operations. Just like optional type declarations can reduce boxing and dynamic dispatch.
[1] https://blog.metaobject.com/2014/05/the-spidy-subset-or-avoi...
[2] https://www.amazon.com/gp/product/0321842847/ref=as_li_tl?ie...
[3] https://objective.st/