(std test) and (std stm) were pages next to folders of their submodules, and the std menu lists folders first, so each showed up twice, far apart. The module page is now the folder's index.sz, so the menu has one entry for it, and its submodules are listed at the top of the page and in the menu below. (std test prop), (std test gen) and (std test expect) get pages, and the standard library chapter says what they have and links to them. 🤖 Generated with [ECA](https://eca.dev) Co-Authored-By: eca-agent <git@eca.dev>
118 lines
15 KiB
Text
118 lines
15 KiB
Text
@section{The standard library}
|
|
|
|
A short tour of the standard library. Each module's full reference is its own page under @link["modules/index.html"]{Modules}.
|
|
|
|
@subsection{std/prelude}
|
|
|
|
The prelude is what every module has without importing anything: the collections and their functions, strings and characters, files and ports, Concurrent ML and scopes, and the macros the language is written with, such as @code{cond}, @code{if-let} and @code{type/derive}. Its reference also covers the builtins, the functions compiled into the runtime rather than written in Bjolang, since every program gets them with the prelude. At the REPL, @code{:show name} prints the same documentation.
|
|
For more details, see @link["modules/std/prelude.html"]{@code{(std prelude)}}.
|
|
|
|
@subsection{std/maths}
|
|
|
|
Numbers beyond the operators. Integer division has Racket's names: @code{quotient} and @code{remainder} are what @code{/} and @code{%} do, and @code{modulo} takes the sign of the divisor, so @code{(modulo -1 10)} is 9. There are @code{gcd}, @code{lcm}, an integer @code{expt} and an exact @code{integer-sqrt} at every integer type, the @code{exact-} roundings from a double to an int, and the rest of @code{System.Math} over doubles. The prelude has @code{abs}, @code{min}, @code{max} and @code{clamp} from here without an import.
|
|
For more details, see @link["modules/std/maths.html"]{@code{(std maths)}}.
|
|
|
|
@subsection{std/fmt}
|
|
|
|
Formatting in Bjolang is divided into two layers: interpolation and layout.
|
|
Interpolation provides a simple way to combine mixed scalar types into strings or print them directly using @code{println*} and @code{str*}.
|
|
The layout layer provides a composable block algebra for more complex text formatting, such as padding, aligning, wrapping paragraphs, and laying out tables.
|
|
For more details, see @link["modules/std/fmt.html"]{@code{(std fmt)}}.
|
|
|
|
@subsection{std/rx}
|
|
|
|
Bjolang provides a built-in regular expression engine. Unlike languages that use strings for regex (like @code{"[a-z]+"}), Bjolang uses structural S-expressions. This means you never have to double-escape characters, and the compiler validates your patterns at compile time. Built-in character sets and anchors are written as keywords (e.g., @code{:bos}, @code{:digit}), and operations that group or repeat patterns are function-like lists (e.g., @code{(seq ...)}).
|
|
For more details, see @link["modules/std/rx.html"]{@code{(std rx)}}.
|
|
|
|
@subsection{std/http}
|
|
|
|
The @code{std/http} module allows you to build and send HTTP requests. Sending a request three ways — blocking, suspending, or as an event — is the only thing that differs between the entry points. There is no C# in this module: @code{System.Net.Http} is reached with @code{import/extern}, and the response body is an ordinary @code{TextInputPort}.
|
|
For more details, see @link["modules/std/http.html"]{@code{(std http)}}.
|
|
|
|
@subsection{std/run}
|
|
|
|
The @code{std/run} module provides a way to run external programs. A form is one thing to run, written as a quoted literal, like @code{'(cat "hej.txt")}. You can connect programs in a pipe with @code{'(pipe (cat "a") (wc -l))}, and redirect input and output to files. Redirections can nest, and you can even splice computed arguments or write stages in Bjolang.
|
|
For more details, see @link["modules/std/run.html"]{@code{(std run)}}.
|
|
|
|
@subsection{std/random}
|
|
|
|
The random module provides a ChaCha20 generator, seeded with 256 bits from the OS CSPRNG, with one generator per thread. The default path locks nothing and shares nothing, making it safe and fast on a bjoroutine. The ambient source has no state to race on, so drawing from multiple threads is efficient. You can generate random integers and more.
|
|
For more details, see @link["modules/std/random.html"]{@code{(std random)}}.
|
|
|
|
@subsection{std/atomic}
|
|
|
|
An atomic is a cell that threads can read and write without a lock. @code{(make-atomic v)} makes one of any type, and @code{atomic-ref}, @code{atomic-set!}, @code{atomic-swap!}, @code{atomic-compare-and-swap!} and @code{atomic-update!} work on it. For @code{int}, @code{uint}, @code{long} and @code{ulong} there are also @code{atomic-increment!}, @code{atomic-decrement!}, @code{atomic-add!} and @code{atomic-sub!}, which compile to direct calls to @code{System.Threading.Interlocked} and wrap on overflow. Swap and compare-and-swap return the value from before the call; the other operations that change the atomic return the new value. The width of a counter comes from type inference, so write @code{(make-atomic 0L)} for a long counter: @code{(make-atomic 0)} is an int.
|
|
For more details, see @link["modules/std/atomic.html"]{@code{(std atomic)}}.
|
|
|
|
@subsection{std/stm}
|
|
|
|
Software transactional memory, after the OCaml library kcas. A @code{(Loc T)} holds one value, and a transaction is a function of a @code{Tx} that reads and writes locations with @code{tx-ref}, @code{tx-set!}, @code{tx-update!} and @code{tx-swap!}. @code{atomically} runs it and commits all of its writes as one step, and runs it again if another transaction changed what it read. @code{tx-retry} stops a transaction until a location that it read changes, and @code{atomically-evt} is the transaction as a CML event, so waiting for a condition combines with timeouts, channels and cancellation in a @code{choose}. @code{tx-or-else} tries alternatives. Three modules build data structures out of locations: @code{(std stm queue)} has the FIFO queue @code{TQueue}, with the channel names @code{queue-send}, @code{queue-recv}, @code{queue-put} and @code{queue-get} outside a transaction; @code{(std stm map)} has the hash map @code{TMap}, whose operations are named as those of the prelude's @code{Map}; and @code{(std stm counter)} has @code{TCounter}, a number that fibers on different CPUs add to without conflicts. Part II has a guide in the section on concurrency.
|
|
For more details, see @link["modules/std/stm/"]{@code{(std stm)}}, @link["modules/std/stm/queue.html"]{@code{(std stm queue)}}, @link["modules/std/stm/map.html"]{@code{(std stm map)}} and @link["modules/std/stm/counter.html"]{@code{(std stm counter)}}.
|
|
|
|
@subsection{std/datetime}
|
|
|
|
This module provides types and functions for handling time. The clock is an argument (with a default that a program can rebind), and the types refuse operations that mean nothing, such as adding a calendar day to an instant. The module separates @code{Date} (a calendar date without a timezone), @code{Time} (a time of day without a timezone), and @code{DateTime} (a date and time without a timezone), as well as handling timezones.
|
|
For more details, see @link["modules/std/datetime.html"]{@code{(std datetime)}}.
|
|
|
|
@subsection{std/eq and std/clr-ord}
|
|
|
|
@code{(std eq)} has the traits @code{Eq} and @code{Ord}. @code{Eq} has @code{=} and @code{eq-hash}, and every type has an implementation: a type with no implementation of its own uses .NET's @code{Equals} and @code{GetHashCode}. @code{Ord} has one method, @code{compare}. The other functions of the module, such as @code{less?}, @code{least}, @code{greatest}, @code{list-sort}, @code{list-min} and @code{list-max}, use only @code{compare}, so a type that implements @code{compare} gets all of them. Strings compare by code point, so the order is the same on every machine. The prelude re-exports every name of @code{(std eq)}, so you do not usually import it. @code{(std clr-ord)} adds @code{Ord} for the .NET time types, @code{Guid} and @code{Version}.
|
|
For more details, see @link["modules/std/eq.html"]{@code{(std eq)}} and @link["modules/std/clr-ord.html"]{@code{(std clr-ord)}}.
|
|
|
|
@subsection{std/monad}
|
|
|
|
The @code{Monad} trait has @code{pure} and @code{bind}, with instances for @code{List}, @code{Option} and @code{Result}. A @code{(do ...)} block writes a chain of @code{bind} calls as a list of steps: @code{(:bind x e)}, @code{(:let x e)} and @code{(:return e)}. For @code{Option} and @code{Result}, the block stops at the first @code{None} or @code{Err}. For @code{List}, it runs once for each combination of items.
|
|
For more details, see @link["modules/std/monad.html"]{@code{(std monad)}}.
|
|
|
|
@subsection{std/effect}
|
|
|
|
Effect handlers that resume once. @code{defeffect} declares operations and their default handlers. A call of an operation calls the handler that is installed, and @code{with-handler} installs other handlers for an extent. A test can, for example, collect what the code logs. A handler runs on the stack of the caller, so it can return a value or raise an exception, and nothing else: no continuation is captured. The prelude declares its own effects, such as @code{log}, @code{warn} and the filesystem operations, so you import this module to handle them.
|
|
For more details, see @link["modules/std/effect.html"]{@code{(std effect)}}.
|
|
|
|
@subsection{std/hashset, std/orderedset and std/orderedmap}
|
|
|
|
Persistent collections beside the prelude's @code{Map}: an update returns a new collection and does not change the old one. @code{(std hashset)} has the unordered @code{HashSet}, a CHAMP trie that compares elements with @code{Eq}. @code{(std orderedset)} and @code{(std orderedmap)} have @code{OrderedSet} and @code{OrderedMap}, B-trees kept in the order of @code{compare}. They add what the order gives: @code{-min}, @code{-max}, @code{-successor}, @code{-predecessor} and the range walks @code{-range}, @code{-from} and @code{-until}. Each collection has a builder, which makes it in one pass, and a transient, which edits it in place and gives it back as a persistent collection in O(1).
|
|
For more details, see @link["modules/std/hashset.html"]{@code{(std hashset)}}, @link["modules/std/orderedset.html"]{@code{(std orderedset)}} and @link["modules/std/orderedmap.html"]{@code{(std orderedmap)}}.
|
|
|
|
@subsection{std/mutable}
|
|
|
|
Collections that change in place. Use them for a cache, an index, a worklist or a scratch buffer, where you do not need old versions. @code{(std mutable vec)}, @code{(std mutable map)}, @code{(std mutable set)} and @code{(std mutable heap)} are the .NET @code{List<T>}, @code{Dictionary<K,V>}, @code{HashSet<T>} and @code{PriorityQueue<T,P>} themselves, not wrappers, so .NET code that takes those types accepts them as they are. They compare with .NET's equality and order. @code{(std mutable deque)} is a double-ended queue with O(1) amortized push and pop at both ends. None of them has a lock.
|
|
For more details, see @link["modules/std/mutable/vec.html"]{@code{(std mutable vec)}}, @link["modules/std/mutable/map.html"]{@code{(std mutable map)}}, @link["modules/std/mutable/set.html"]{@code{(std mutable set)}}, @link["modules/std/mutable/heap.html"]{@code{(std mutable heap)}} and @link["modules/std/mutable/deque.html"]{@code{(std mutable deque)}}.
|
|
|
|
@subsection{std/inbox}
|
|
|
|
An inbox is how .NET code gives work to Bjolang. A thread that is not a fiber, such as a timer, a @code{FileSystemWatcher} or a Kestrel thread, posts an item and returns. A fiber takes the item with its own handlers, parameters and cancellation scope. An inbox always has a capacity, and a @code{WhenFull} policy says what a post does when the inbox is full. @code{inbox-call} is a request and a reply: the .NET caller gets a @code{Task}, and a fiber answers it.
|
|
For more details, see @link["modules/std/inbox.html"]{@code{(std inbox)}}.
|
|
|
|
@subsection{std/ports and std/net}
|
|
|
|
@code{(std ports)} reads and writes bytes on the prelude's ports. The byte reads @code{read-some-evt}, @code{read-bytes-evt} and @code{eof-evt} are CML events: a read that loses its @code{choose} takes nothing, so a read can race a timeout. @code{read-line} and @code{read-bytes} can be used on the same port. The module also drains ports into lists and vecs, streams them as a @code{Seq} or a channel, and has @code{byte-pipe}, a pair of ports with no file and no network, for tests. @code{(std net)} gives a TCP connection as a pair of these ports, so a protocol written for ports also runs over TCP. @code{accept-evt} is an event too: a branch that loses accepts nothing.
|
|
For more details, see @link["modules/std/ports.html"]{@code{(std ports)}} and @link["modules/std/net.html"]{@code{(std net)}}.
|
|
|
|
@subsection{std/test and std/simpletest}
|
|
|
|
@code{(std test)} has tests that are silent unless they fail. @code{deftest} registers a test, @code{check} reports the values that it saw when it fails, and @code{(run-tests)} is the @code{main} of the file. Each test runs in a scope with a deadline. The test fails if it leaves a resource open, and the scope waits for the fibers that the test started. @code{bjo test} builds and runs the test files of a project. @code{(std simpletest)} is the older harness: an assertion prints one line, and a failure prints a line that starts with @code{FAILURE:}. Its @code{with-fake-fs}, a filesystem in memory, also works inside a @code{deftest}.
|
|
|
|
@code{(std test prop)} has property tests. @code{for-all} runs its body many times with generated values. When a run fails, @code{for-all} shrinks it to a small case, reports that case, and stores it beside the test file, so the next run tries it first. @code{assume} discards a run, @code{label} names the failures in its body, and @code{classify} and @code{collect} count the runs for @code{--stats}. @code{(std test gen)} has the generators, and @code{Arbitrary}, which gives the default generator of a type. @code{(std test expect)} has @code{expect-output}, which compares the output of a body with a text in the test, and @code{--promote} updates that text.
|
|
|
|
For more details, see @link["modules/std/test/"]{@code{(std test)}}, @link["modules/std/test/prop.html"]{@code{(std test prop)}}, @link["modules/std/test/gen.html"]{@code{(std test gen)}}, @link["modules/std/test/expect.html"]{@code{(std test expect)}} and @link["modules/std/simpletest.html"]{@code{(std simpletest)}}.
|
|
|
|
@subsection{std/stopwatch}
|
|
|
|
Stopwatches that read the ambient clock, so a test can bind a clock and get an exact time. @code{time-it} runs a body a number of times and reports the time and memory that it used.
|
|
For more details, see @link["modules/std/stopwatch.html"]{@code{(std stopwatch)}}.
|
|
|
|
@subsection{std/syntax-match}
|
|
|
|
@code{syntax-match} takes a form apart with patterns, with @code{...} for repetition. Write macro transformers with it, and build the result with @code{#'}.
|
|
For more details, see @link["modules/std/syntax-match.html"]{@code{(std syntax-match)}}.
|
|
|
|
@subsection{text/bjodat}
|
|
|
|
bjodat is Bjolang's shapes read as data: no evaluation, no macro expansion, no environment. It is what a package manifest, a lockfile, or a config file is written in. You can parse text straight into a record using @code{bjodat-parse-<Name>}, which avoids intermediate trees and allocations.
|
|
For more details, see @link["modules/text/bjodat.html"]{@code{(text bjodat)}}.
|
|
|
|
@subsection{text/json}
|
|
|
|
The @code{text/json} module provides JSON parsing and generation capabilities. Like @code{bjodat}, it allows for working with structured data but using the standard JSON format, which is essential for web communication.
|
|
For more details, see @code{prelude.org} and related standard library documentation.
|