Property commands
A field is written only with `=`, everywhere; the one command call left is a trailing block on a field whose value is a record, which configures that value in place rather than replacing it - no hand-written setters.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
A command call on a method calls it. A field is written only with =
(2026-09-25), everywhere, including inside a receiver closure. The one command call left on a field is a trailing
block on a value that is a record, never a function: it configures that value in place instead of replacing it.
Example#
type Server {
var port: Int = 8080
var onStart: () => Void = {}
}
var server = Server()
server.port = 9090
server.onStart = { print "started" }
print "Listening on {server.port}"
server.onStart()Syntax#
value.field = <expression> Writes the field
value.field { ... } Configures the value the field holds in place - only when it is a record type
value.field() Calls the function the field holds
value.field Reads the fieldRules#
A field is written with
=, never with a command.server.port 9090is an error: "portis a field: writeport = 9090", the fix reconstructed from what was written.server.onStart { print "started" }is an error the same way: "onStartis a field: writeonStart = { print \"started\" }".Kompiliert nichttype Server { var port: Int = 8080 } var server = Server() server.port 9090 print server.port // error: `port` is a field: write `port = 9090`Kompiliert nichttype Server { var onStart: () => Void = {} } var server = Server() server.onStart { print "started" } // error: `onStart` is a field: write `onStart = { print "started" }`A trailing block on a field whose value is a record configures it in place, and is not an assignment.
server.database { url = "..." }reads the field and runs the block as a receiver closure over the value it already holds - the value is changed where it lies, never replaced. Inside the block a field is still written with=:url = "..."is itself an ordinary field write, resolved against the block's own receiver.type DatabaseConfig { var url: String = "" } type Server { var database: DatabaseConfig = DatabaseConfig() } var server = Server() server.database { url = "postgres://..." } print server.database.urlParentheses always call.
server.onStart()runs the closure that is stored in the field; without the parentheses,server.onStartonly reads it. A field that holds no function has nothing to call, soserver.port(9090)is an error - parentheses call, and a field is written with=- and neither isserver.onStart({ ... }), which hands the closure to a function that takes none.Kompiliert nichttype Server { var port: Int = 8080 } var server = Server() server.port(9090) print server.port // error: `port` is a field, and parentheses call a functionKompiliert nichttype Button { var onClick: () => Void = {} } var button = Button() button.onClick({ print "clicked" }) // error: `onClick` holds a function: `onClick = { ... }` assigns it, `onClick()` calls itBoth forms need a
varpath to the field, exactly like an assignment does. A block on aconstrecord field is rejected the same wayfield = valuewould be, with a note that names the syntax.Kompiliert nichttype Database { var url: String = "" } type Server { database: Database = Database() } var server = Server() server.database { url = "postgres://..." } print server // error: `database` never changes after constructionThere is no line that could mean two things. A command on a method calls it; the one command left on a field - a trailing block on a record value - configures it in place; parentheses call. Which one happens is decided by what the name refers to and by whether the call has parentheses, never by anything else.
What this is not#
A trailing block on a field is not calling it with an implicit (). server.database { url = "..." } configures
the field and calls nothing; server.database(...) is not the same line with parentheses, it calls, and a record
field has nothing to call.
A command carries no permission of its own either: a field another file cannot name is not configured by one, and one
it may only read is not configured by one. private reaches as far as the file that declares it
(Fields, rule 5).
use Workspace from "std/project"
var workspace = Workspace()
workspace.memberPatterns = ["packages/*"]
print workspace.memberPatterns
// error: `memberPatterns` is write-protected: only the file that declares `Workspace` writes itRelated#
- Fields -
var,privateandprotected var, which decide whether a write may reach the field. - Methods and
static fns - what the same command syntax does when the name is a method instead. - Declaring a type - the one namespace a property command and a method call share.