A programming language idea: no static code, explicit caller context (Kite)
Marconi
soldate at gmail.com
Wed Apr 29 19:34:04 UTC 2026
On Wednesday, 29 April 2026 at 18:47:41 UTC, H. S. Teoh wrote:
> On Wed, Apr 29, 2026 at 05:50:08PM +0000, Marconi via T
Thanks, this is really helpful feedback — it made me realize I
need to refine the idea quite a bit.
On “why object-oriented?”
I think “everything is object-oriented” was a poor way to express
what I actually want.
What I really need is:
any code that can cause effects must have an explicit owner.
So the role of OO here is not philosophical (“everything is an
object”), but structural:
effectful code must always have a responsible object.
That’s why I need something like a base Object: to guarantee that
every caller has a minimal set of capabilities (like allocation
and error reporting).
However, I don’t think this should forbid pure functions.
Something like:
sqrt(x)
max(a, b)
does not allocate, does not perform I/O, and does not need
authority. So a better rule would be:
pure code can be free; effectful code requires a caller.
On allocation
You’re right to question whether every object would need its own
allocator.
That’s not the intention.
The idea is that every object has access to allocation
capability, but not necessarily its own implementation. In
practice, it would likely delegate:
buffer = caller.alloc(size)
internally becoming something like:
caller.allocator.alloc(size)
with the allocator coming from a root object or environment.
The key point is:
the callee cannot silently decide allocation policy.
It must request it from the caller.
On error handling
I agree with your concern — the initial caller.error("...")
example was too naive.
I don’t expect the top-level caller to handle every possible
low-level error. That would be impractical.
A better model would be:
callees detect and classify errors; callers decide the policy.
So instead of just passing strings:
return caller.error(FileNotFound(path))
Each layer can:
handle the error locally (if it has enough context),
transform it into a higher-level/domain error,
propagate it unchanged.
For example:
on FileNotFound:
useDefault()
else:
return caller.error(ConfigLoadFailed(err))
So errors don’t blindly bubble up to the top — they are
progressively interpreted or transformed.
The intent is not that the caller knows everything, but that:
no callee unilaterally decides what an error means.
A better way to phrase it might be:
Callees know what failed. Callers decide what it means.
On global state, I/O, and external systems
I agree that replacing globals with singletons would defeat the
purpose.
A better direction is capability-based design. For example:
caller.fs.open(...)
caller.console.write(...)
caller.memory.alloc(...)
These are not globals — they are capabilities exposed by the
caller/root environment.
So instead of hidden global state, authority must be explicitly
passed.
Refining the idea
Based on your feedback, I think the core idea is better expressed
as:
pure functions are allowed and free
effectful operations require explicit authority
caller represents authority/policy, not just context
libraries can request resources but should not silently decide
policies
external effects are accessed through explicit capabilities, not
globals
So perhaps the real principle is:
Pure code is free. Effectful code requires authority.
Thanks again — your questions helped clarify what the idea
actually is (and what it isn’t).
More information about the Digitalmars-d
mailing list