BjoManual/_03.Standard-library.sz
Linus Björnstam 40f4783fa5 std/url: URLs read, written, resolved and percent-encoded
The standard library chapter gets std/url after std/http: the quoted
literal that encodes each value for its part, parse-url's strict reading,
the round trip, url-resolve, the decoded parts and the encoders.
modules/std/url.sz is the reference page, generated from (std url)'s docs.

🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-7)

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-17 12:39:22 +02:00

131 lines
17 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@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/url}
URLs by RFC 3986. A URL is written as a quoted literal, as @code{(std run)} writes a pipeline: @code{(link '(url https "example.com" (path "users" ,name) (query (page 2) (tag ,tag)) (fragment "top")))}, or @code{'(path "users" ,id "edit")} for a path on this site. Each value is encoded for the part that it is in, so a @code{/} in a computed segment does not make a second segment, and a @code{&} in a computed value does not make a second parameter. The compiler checks the parts of a literal where it is written. @code{parse-url} reads a URL or a relative reference strictly, and refuses text that is not one with the column where it goes wrong. A @code{Url} keeps each part as it was written, so @code{url->string} gives back the same text. @code{url-resolve} reads a link where a page is. @code{url-segments} and @code{url-params} decode the path and the query, and there is one percent-encoder for each part of a URL.
For more details, see @link["modules/std/url.html"]{@code{(std url)}}.
@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/bench}
Benchmarks, written like tests. @code{def/bench} registers a benchmark, with a setup outside the time, parameters that make a row for each combination of values, cold runs for a slow body, and groups. @code{(run-benches)} is the @code{main} of the file. A run warms each benchmark up until its times are steady, calibrates how many calls make a sample, and takes samples until the median is known to ±1%. It prints a table of the median, the spread, the minimum, the allocation and the collections, a row as each benchmark finishes. With no names at a terminal, a menu asks what to run. @code{--save} and @code{--compare} keep a run in a file and compare with it, with p-values corrected for the number of comparisons and a verdict that needs both a significant and a large enough change. @code{bjo bench FILE --against REF} runs a file against itself at a git ref, the two versions measured in turns. @code{time-it} is here too: a body measured in place, on one line.
@code{(std bench stats)} has the statistics: medians, quantiles, bootstrap intervals of a ratio, and the Wilcoxon, Mann–Whitney and t tests, each checked against SciPy. @code{(std bench store)} has saved runs as data, and the two kinds of comparison.
The section on benchmarking in "Writing programs" shows all of it with the card game. For more details, see @link["modules/std/bench/"]{@code{(std bench)}}, @link["modules/std/bench/stats.html"]{@code{(std bench stats)}} and @link["modules/std/bench/store.html"]{@code{(std bench store)}}.
@subsection{std/stopwatch}
Stopwatches that read the ambient clock, so a test can bind a clock and get an exact time. The module also has @code{time-it}, which is @code{(std bench)}'s: a body measured as a benchmark is, reported on one line.
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.