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. Save this
as main.jadpo and run jadpo test main.jadpo:
test "calls through the standard library" { assert text.trim(" Rye loaf ") == "Rye loaf" assert text.split("flour,sugar,,eggs", ",") == ["flour", "sugar", "", "eggs"] assert text.pad_start(text.from(42), 6, fill: "0") == "000042" assert list.sum([3, 4, 5]) == 12}
text. and list. are built-in namespaces, so nothing is imported.
- 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 aee2e8f.