Receiver modules¶
A module that names a type pattern after for, module club.titles for
String, is a receiver module. Its functions take self as their first
parameter, at the module's pattern, and once the module is imported they
resolve as receiver calls, value.f(args), on every value the pattern
fits. This is lib/club/titles.hql:
/// Receiver functions over a book's title.
module club.titles for String
/// The first letter of each word, `"The Hobbit".initials()` is `"TH"`.
fn initials(self) : String = self.words().map(w => w.slice(0, 1)).join("")
/// A shelf mark: the initials and the year, `"TH-1937"`.
fn shelf_mark(self, year: Int) : String = fmt("{}-{}", self.initials(), year)
self is written untyped: its type is the module's pattern, String. Inside
the module, self.initials() calls the module's own receiver function.
import club.titles
["The Hobbit".initials(), "Dune".shelf_mark(1965), titles.initials("Mrs Dalloway")]
["TH", "D-1965", "MD"]
value.f(args) is module.f(value, args): the value fills self, and
titles.initials("Mrs Dalloway") is the same call written with its module. A
function declared without self takes no receiver and is called only through
its module.
Receiver calls throughout the book¶
The prelude's modules are receiver modules too: string is module string
for String, so "Dune".upper() calls string.upper, and [1, 2].size()
calls the collection's size. A receiver call is resolved by the value's
type among the modules in scope, so two modules may declare one name over
different types: "abc".contains("b") is the string's and
[1, 2].contains(2) the collection's.
c.title without parentheses is a field read, not a call.
A receiver function's body¶
A receiver function is a function, and its body takes either form. A block
over self names its steps as any block does:
module counting for Int
fn twice(self) : Int {
doubled = self * 2
doubled
}
A program declares no receiver functions: self belongs to a module's
pattern, and a program has none.
fn initials(self: String) : String = "TH"
"The Hobbit".initials()
parse failure[unexpected-token]: a function with a body takes its receiver at the module's pattern: write `self` untyped
--> <expression>:1:19
|
1 | fn initials(self: String) : String = "TH"
| ^^^^^^