What every operation follows
Every namespace follows the same rules, so a call you haven't seen before reads like one you have. Here are some calls, and what they give:
text.trim(input.title) // " Rye loaf " gives "Rye loaf"text.split("flour,sugar,,eggs", ",") // ["flour", "sugar", "", "eggs"]text.pad_start(text.from(order.number), 6, fill: "0") // 42 gives "000042"list.sum(list.map(basket.lines, line -> line.price * line.count))set.contains(recipe.allergens, Allergen.tree_nuts)encoding.to_hex(hash.sha256(upload.body)) // 64 lowercase hexadecimal digitsattempt encoding.from_base64(input.attachment) { malformed: AttachmentUnreadable}
- One namespace per type it works on:
list.,set.andmap.forList<T>,Set<T>andMap<K, V>,text.for text,money.forMoney. The namespace says what the first argument is, soset.containsandlist.containsstay distinct where they behave differently (order, repeats). - Always called through its namespace:
text.trim(name), nevertrim(name)(Project layout and modules). A namespace's name can't be used to name a declaration, domain, library, parameter or variable. A field or a named argument can still be calledtext, sincenote.textandset:are never read as the namespace. - A moved operation keeps working while you rename the call. A call
to an operation, or through a namespace, that the library has moved is
the error
semantic.standard_operation_movedwhere it is resolved, with an edit to the new name. Meanwhile it is checked as the operation it moved to. - Pure, with one named exception. Each operation gives the same
result for the same arguments, in the interpreter and on every compiled
target, and may be called in a function. The exception is randomness:
random.*,crypto.encryptandcrypto.hash_passwordread the random generator, so, as withclock.now, you call them only in actions, and tests fix their results. - Reference data is pinned. Unicode data (case mapping, white space, the slug's decomposition), CLDR formats and ISO lists are fixed versions shipped with Jadpo, and upgrading them is a reviewed change, as the time-zone database is.
- Representations in, representations out
(Expressions and operators). A
parameter written
Texttakes any value built onText,EmailandUrlincluded, and one writtenBytesany value built onBytes. A result writtenTextis plain text, which you turn into a named type by constructing it. A result keeps the argument's named type only where the operation returns one of its arguments or their items unchanged (integer.max,list.filter,set.union), since only then can no rule break. - Named arguments only where a value needs saying
(Calling). The first arguments are positional,
and options and modes are named, as
rounding:is. - Failures are typed (Failures). An operation that
can fail names each condition it fails on, and the call's
attemptmaps each by that name, asdst:andinvalid_day:are mapped in Zones and local times. The failure isinvalid_value, andinvalid:covers every condition without its own arm. Overflow is a defect, as it is for+. - Bad arguments are ruled out while compiling where they can be, as
/rules out a zero divisor. Besidenever_zero, an operation's argument can benever_empty(a literal isn't"", and a value's type has amin_lengthof at least 1) ornever_negative(a literal isn't below 0, and a value's type has aminof at least 0). - Results carry facts for proofs. A result whose type can't say its
bounds carries them in the operation table, as
list.count'sat_least: 0does (Values and types), so constructing a value from it needs no arm for a rule it can't break.at_most_length_ofmarks a text result never longer than an argument (text.trim,text.keep_first). SoTitle(text.trim(title))can't breakTitle'smax_length, though it can still breakmin_lengthor apattern.
Markdown for agents: /docs/what-every-operation-follows.md.Built from Jadpo main at a707efb.