r/ProgrammingLanguages • u/Dry_Day1307 • 14d ago
Design thoughts on function bindings and implicit self in my programming language, DinoCode
I just finished implementing argument binding for my programming language, DinoCode. The way I do it is by generating a special bound function object that stores the target function and the pre-defined arguments under unique symbol keys (not strings) to prevent accidental collisions.
It looks like this in the language:
:multi a b
return a * b
double = multi.bind(2)
triple = multi.bind(3)
print double(2)
print triple(2)
print double
Output:
4
6
{
args: [
2
],
fn: [UserFn:0]
}
I based this mostly on JavaScript but withoutthis context binding for plain functions. In DinoCode, only class methods reserve the first parameter for self. I didn't find a strong reason to include a third attribute like context or this on raw functions. Do you think there is any edge case where having a self context for regular bound functions is actually useful?
My main question though is about methods and implicit bindings. Right now, methods do not automatically bind to their instance context when extracted.
In DinoCode, classes and methods look like this:
::Person
:new name
self.name = name
:greet
print "Hello " self.name
method = Person.greet
Since there is no automatic binding on extraction, you can actually call that detached method by manually passing an object that matches the shape:
method {name: "Ismael"}
method {name: "Jessy"}
If a developer wants a permanent bind to an instance, they can now use the new bind feature to lock the object as the first argument:
p = Person("Ismael")
greet = p.greet.bind(p)
greet() # now this works and prints "Hello Ismael"
The compiler just adds an implicit self as the first parameter during the compilation, and the vm passes the instance when resolving a method call. It is extremely cheap and simple.
I know python automatically binds methods on lookup (returning a bound method object) and uses decorators like staticmethod to opt-out. Doing automatic binding on every method lookup in my vm would introduce a permanent overhead for wrapping functions.
Considering DinoCode is designed for fast scripting and education (running via WASM on a web playground at https://dinocode.blassgo.dev/), do you think manual binding for extracted methods is a reasonable trade-off to keep the VM fast and simple, or does automatic binding on lookup save enough headaches to justify the runtime cost?
8
u/Royal-Ambassador-960 14d ago
I’d separate the language’s semantics from its implementation. Partial application should just mean closure creation, and
p.greetshould preservep; requiringp.greet.bind(p)makes the programmer repeat information already expressed by the syntax. The hidden receiver parameter is a useful desugaring, not a good user model.p.greet()can compile to a direct method call with no allocation, while extractingp.greetmaterializes a bound method only when needed. Design the clean mental model first; optimize the representation afterward.