5. Methods take an explicit self parameter
- Status: Accepted
- Date: 2026-09-02
Context
Korrin has classes with methods (decided with the project owner). A method needs
access to the instance it was called on. Languages either pass it implicitly and
expose it as a keyword (this in Java/C++/JavaScript, self in Ruby/Swift) or
pass it explicitly as the first parameter (Python, Rust).
Decision
A method is just a function defined in a class body whose first parameter is
self:
class Point:
fn init(self, x, y):
self.x = x
self.y = y
fn dist_sq(self):
return self.x * self.x + self.y * self.y
self is an ordinary parameter name, bound like any other. It is not a keyword
and is not implicitly in scope. Calling p.dist_sq() passes p as self.
The constructor is the method named init; instances are created by calling the
class (Point(1, 2)), which allocates the instance and runs init on it.
Consequences
- No special scoping rule for
self; the resolver treats it as a normal binding. The only method-specific checks are "self/superonly appear inside a method" and those are about lexical position, not about a magic variable. - The relationship between a function and a method is "a method has
selfas parameter one" — nothing more. One concept, not two. - Method definitions are two characters wider and the
self.prefix is required to touch fields. This explicitness is the point: field access is never ambiguous with local-variable access. - A function pulled out of a class body and a method are the same kind of value, which keeps the interpreter's callable handling uniform.
Alternatives considered
- Implicit
thiskeyword. Saves typing, but introduces an invisibly-injected binding and the "unqualified name: is it a field or a local?" ambiguity that causes real bugs. @fieldsigil for fields (Ruby, CoffeeScript). New punctuation for somethingself.already expresses.newkeyword for construction. An extra keyword; calling the class is sufficient and reads well.