Logos primitives reference
Copy MarkdownEvery Layer-1, Elixir-implemented primitive (Logos.Primitives) --
interned directly into logos.core (or logos.map, for get/
assoc/dissoc) as an ordinary Var, looked up through exactly the
same symbol-resolution path as everything else. Everything in the
special-forms and stdlib-namespace pages is ultimately built from
these plus the six special forms. For prose/narrative explanation and worked examples, see the language reference; for everything else generated (the overview, special forms, primitives, and every other stdlib namespace), see the other pages in this "Stdlib Reference" section.
*
(* & nums)
Multiplication. Ratio-/decimal-aware. (*) is 1.
Example:
(* 2 3 4)
;;=> 24+
(+ & nums)
Addition. Ratio-/decimal-aware; mixing a narrower numeric type into a wider one (integer -> ratio -> decimal -> float) always upgrades to the wider type. (+) is 0.
Example:
(+ 1 2 3)
;;=> 6-
(- a & more)
Subtraction, or negation with a single argument ((- 5) => -5). Ratio-/decimal-aware, same numeric-tower rules as +.
Example:
(- 10 3)
;;=> 7/
(/ a & more)
Division. Two plain integers produce a ratio, auto-demoted to an integer when exact ((/ 6 3) => 2, (/ 1 3) => 1/3); a single argument is a reciprocal ((/ 2) => 1/2). Ratio-/decimal-aware.
Example:
(/ 1 3)
;;=> 1/3<
(< a & more)
Strictly increasing, chained ((< 1 2 3) checks both steps). Ratio-/decimal-aware.
Example:
(< 1 2 3)
;;=> true<=
(<= a & more)
Non-decreasing, chained. Ratio-/decimal-aware; value-based for decimals ((<= 1.10M 1.1M) is true even though = says false).
Example:
(<= 1 1 2)
;;=> true=
(= a & more)
Structural equality, chained across every argument. Ratio-/decimal-aware: a ratio always auto-reduces to lowest terms first, and a decimal compares scale-sensitively ((= 1.10M 1.1M) is false -- use <=/>= together for value-based equality).
Example:
(= 1 1 1)
;;=> true>
(> a & more)
Strictly decreasing, chained. Ratio-/decimal-aware.
Example:
(> 3 2 1)
;;=> true>=
(>= a & more)
Non-increasing, chained. Ratio-/decimal-aware.
Example:
(>= 2 2 1)
;;=> trueapply
(apply f a b ... coll)
Calls f with a/b/... then every element of trailing coll (list/vector/set/map/nil) as further positional arguments.
Example:
(apply + 1 2 (list 3 4))
;;=> 10assoc
(assoc coll k v & more)
Associates k with v in coll (variadic: more k v pairs may follow), returning a new collection of the same shape. nil is treated as {}. Also works on a vector by index (an existing index, or exactly one past the end -- matching conj -- anything further raises).
Example:
(assoc {:a 1} :b 2)
;;=> {:a 1 :b 2}assoc!
(assoc! t k v)
Associates k with v in transient t in place, mutating it -- returns t itself.
Example:
(persistent! (assoc! (transient {:a 1}) :b 2))
;;=> {:a 1 :b 2}compare
(compare a b)
Clojure's general-purpose ordering: a negative/zero/positive integer. Handles any comparable pairing (numbers, strings, chars, keywords/symbols, vectors/lists elementwise), not just numbers -- backs sort/sort-by (logos.seq) and sorted-map/sorted-set's default ordering.
Example:
(compare 1 2)
;;=> -1concat
(concat & colls)
Flattens every one of colls (list/vector/nil) into one list, in order.
Example:
(concat (list 1 2) (list 3 4))
;;=> (1 2 3 4)conj!
(conj! t x)
Adds x to transient t in place, mutating it -- returns t itself.
Example:
(persistent! (conj! (transient [1 2]) 3))
;;=> [1 2 3]cons
(cons x coll)
Prepends x onto list coll (nil treated as ()).
Example:
(cons 1 (list 2 3))
;;=> (1 2 3)current-ns
(current-ns)
The bare current namespace name, as a string.
Example:
(current-ns)
;;=> "user"demonitor
(demonitor ref)
Cancels monitor ref.
Example:
(let [p (spawn (fn [] (receive [msg] (true msg))))] (let [m (monitor p)] (demonitor m) :done))
;;=> :donedisj!
(disj! t x)
Removes x from transient set t in place, mutating it -- returns t itself.
Example:
(persistent! (disj! (transient (list->set (list 1 2 3))) 2))
;;=> #{1 3}dissoc
(dissoc coll & ks)
Removes each of ks from map coll (variadic), returning a new map. nil is treated as {}.
Example:
(dissoc {:a 1 :b 2} :a)
;;=> {:b 2}dissoc!
(dissoc! t k)
Removes k from transient map t in place, mutating it -- returns t itself.
Example:
(persistent! (dissoc! (transient {:a 1 :b 2}) :a))
;;=> {:b 2}exit
(exit) / (exit reason) / (exit pid reason)
0/1-arity exits the CALLING process itself (with reason, default nil); 2-arity sends an exit signal reason to pid instead.
Example:
(let [p (spawn (fn [] (receive [msg] (true msg))))] (exit p :normal) :done)
;;=> :donefirst
(first coll)
The first element of list coll, or nil if coll is empty or nil.
Example:
(first (list 1 2 3))
;;=> 1gensym
(gensym) / (gensym "prefix")
Returns a fresh, guaranteed-unique symbol -- what syntax-quote's own x# auto-gensym uses internally, also callable directly.
Example:
(gensym "tmp")
;;=> tmp9get
(get coll k) / (get coll k not-found)
Looks up k in coll -- a map/sorted-map/record key, a vector index (bounds-checked), or set/sorted-set membership (the element itself if present). not-found (default nil) is returned when missing. nil never contains anything.
Example:
(get {:a 1} :a)
;;=> 1import
(import dotted-sym) / (import dotted-sym doc)
Interns an allowlisted Elixir function under its bare name in the current namespace -- e.g. (import 'String.upcase) interns upcase. Optional trailing docstring, same shape as def's own 3-arg form.
Example:
(import 'String.trim "Trims whitespace.")
(doc trim)
;;=> "Trims whitespace."in-ns
(in-ns name)
Switches (creating if needed) the current namespace to name, returning name as a bare symbol.
Example:
(in-ns 'my-prim-ns)
;;=> my-prim-nsintern-var!
(intern-var! qualified-sym value)
Interns/mutates qualified-sym's (an ns/name symbol) Var directly, bypassing def's "current namespace only" restriction -- what logos.multimethod/logos.test use internally to mutate their own shared registry Vars from a caller in any namespace.
Example:
(intern-var! (symbol "user" "my-interned") 42)
my-interned
;;=> 42keyword
(keyword "name") / (keyword "ns" "name") / (keyword sym)
Builds a keyword from a string (bare or namespaced) or from a symbol's own name/namespace.
Example:
(keyword "a")
;;=> :alink
(link pid)
Links the calling process to pid.
Example:
(let [p (spawn (fn [] (receive [msg] (true msg))))] (link p) (unlink p) :done)
;;=> :donelist
(list & xs)
Builds a list from its arguments, in order.
Example:
(list 1 2 3)
;;=> (1 2 3)list->map
(list->map coll)
Converts a list of (k v) 2-element lists into a map.
Example:
(list->map (list (list :a 1) (list :b 2)))
;;=> {(:a 1) (:b 2)}list->set
(list->set coll)
Converts list coll into a set.
Example:
(list->set (list 1 2 2 3))
;;=> #{1 2 3}list->vector
(list->vector coll)
Converts list coll into a vector.
Example:
(list->vector (list 1 2 3))
;;=> [1 2 3]macro?
(macro? sym)
True if sym resolves (through the full refer chain) to a Var flagged :macro.
Example:
(macro? 'if)
;;=> truemeta
(meta x)
A symbol value's own ^meta/with-meta-attached metadata ({} by default), or nil for anything that isn't a symbol -- with-meta's read-side counterpart. NOT a resolved Var's stored metadata (:doc/:private/:macro, that's var-doc/macro?) -- a different, unrelated piece of state.
Example:
(meta 'x)
;;=> {}monitor
(monitor pid)
Monitors pid, returning a monitor reference.
Example:
(let [p (spawn (fn [] (receive [msg] (true msg))))] (let [m (monitor p)] (demonitor m) :done))
;;=> :donenormal-exit?
(normal-exit? reason)
Whether a :DOWN/:EXIT message's reason was a clean exit -- needed since reason is a raw Elixir term (the bare atom :normal), not something Logos source can construct or =-compare against directly.
Example:
(let [spawned (spawn-monitor (fn [] :ok)) pid (first spawned)]
(receive [msg]
((and (= (first msg) :DOWN) (= (first (rest (rest (rest msg)))) pid))
(normal-exit? (first (rest (rest (rest (rest msg)))))))))
;;=> truens-list
(ns-list)
A list of every namespace name currently registered -- logos.repl introspection support.
Example:
(ns-list)
;;=> ("logos.concurrency" "logos.core" "logos.map" "logos.multimethod" "logos.seq" "logos.set" "logos.string" "logos.test" "logos.walk" "user")ns-vars
(ns-vars ns-name)
A list of every Var name interned directly in namespace ns-name -- logos.repl introspection support.
Example:
(ns-vars 'logos.walk)
;;=> ("postwalk" "prewalk" "walk")persistent!
(persistent! t)
Converts transient t back into an ordinary immutable vector/map/set, ending its mutable phase -- using t again afterward raises.
Example:
(persistent! (transient [1 2 3]))
;;=> [1 2 3]pid->atom
(pid->atom pid)
Wraps Pid pid as an Atom -- used internally by atom (logos.concurrency).
Example:
(do (pid->atom (spawn (fn [] (receive [msg] (true msg))))) :wrapped)
;;=> :wrappedpop!
(pop! t)
Removes the last element from transient vector t in place, mutating it -- returns t itself.
Example:
(persistent! (pop! (transient [1 2 3])))
;;=> [1 2]pop-thread-binding!
(pop-thread-binding! quoted-sym)
Per-BEAM-process dynamic-var override pop -- push-thread-binding!'s counterpart; not meant to be called directly.
Example:
(def ^:dynamic *pv* 1)
(push-thread-binding! '*pv* 2)
(pop-thread-binding! '*pv*)
*pv*
;;=> 1pr-str
(pr-str & vs)
Like str, but every argument (strings included) goes through the same reader-round-trippable printer unchanged: (pr-str "hi") => the quoted form. Multiple arguments join with a single space.
Example:
(pr-str "hi")
;;=> "\"hi\""push-thread-binding!
(push-thread-binding! quoted-sym value)
Per-BEAM-process dynamic-var override push -- the Elixir-side half of binding (logos.core); not meant to be called directly.
Example:
(def ^:dynamic *pv* 1)
(push-thread-binding! '*pv* 2)
*pv*
;;=> 2quot
(quot n d)
Integer-only quotient, truncated toward zero -- wraps Erlang's div directly, exactly Clojure's own quot.
Example:
(quot 7 2)
;;=> 3read-string
(read-string s)
Parses s as Logos source text and returns the FIRST form as plain, unevaluated data. Malformed s raises a catchable :read-error.
Example:
(read-string "(1 2 3)")
;;=> (1 2 3)receive-match!
(receive-match! pred handler) / (receive-match! pred handler timeout-ms default-fn)
The primitive receive (logos.concurrency) compiles down to: pops one mailbox message, calls (pred msg); on a truthy match, calls (handler msg); on a miss, sends it back to itself and keeps scanning. With timeout-ms, gives up and calls zero-arg default-fn after that many milliseconds with no match.
Example:
(do (send (self) :ping) (receive-match! (fn [m] (= m :ping)) (fn [m] m)))
;;=> :pingrecord
(record type-kw fields-map)
Builds a genuine record value directly, tagged type-kw with fields fields-map -- the Elixir-side plumbing defrecord (logos.core) needs, since Logos has no generic "construct an arbitrary struct" facility of its own.
Example:
(record (keyword "user" "Point") {:x 1 :y 2})
;;=> #user/Point{:x 1 :y 2}register-data-reader!
(register-data-reader! tag dotted-name)
Registers a #tag value reader for tag (a string or bare symbol), resolved through the same allowlist import uses.
Example:
(register-data-reader! 'upper 'String.upcase)
(read-string "#upper \"hi\"")
;;=> "HI"rem
(rem n d)
Integer-only remainder; sign matches the dividend n (unlike mod (logos.core), whose sign matches the divisor). Wraps Erlang's rem directly.
Example:
(rem -7 2)
;;=> -1require
(require & specs)
Loads each of specs (a bare namespace symbol, or [ns :as alias]/[ns :refer [names...]]/[ns :refer [:all]]) into the current namespace.
Example:
(do (require 'logos.set) :required)
;;=> :requiredrest
(rest coll)
Every element of list coll after the first, or () if coll has one or zero elements, or is nil.
Example:
(rest (list 1 2 3))
;;=> (2 3)self
(self)
The calling process's own Pid.
Example:
(= (self) (self))
;;=> truesend
(send pid msg)
Delivers msg (any Logos value, including a closure) to pid's mailbox.
Example:
(do (send (self) :ping) (receive [msg] (true msg)))
;;=> :pingset-macro!
(set-macro! sym flag)
Sets/clears the :macro metadata flag on the Var sym refers to -- an alternative to def's own ^:macro reader sugar.
Example:
(defn my-fn [x] x)
(set-macro! 'my-fn true)
(macro? 'my-fn)
;;=> truesorted-map
(sorted-map & kvs)
Builds a sorted map from alternating key/value arguments, ordered by compare.
Example:
(sorted-map :b 2 :a 1)
;;=> {:a 1 :b 2}sorted-map-by
(sorted-map-by comparator & kvs)
Like sorted-map, but ordered by a caller-supplied comparator function (must return a negative/zero/positive integer, compare's own convention) instead of compare itself.
Example:
(sorted-map-by (fn [a b] (compare b a)) :a 1 :b 2)
;;=> {:b 2 :a 1}sorted-set
(sorted-set & xs)
Builds a sorted set from its arguments, ordered by compare.
Example:
(sorted-set 3 1 2)
;;=> #{1 2 3}sorted-set-by
(sorted-set-by comparator & xs)
Like sorted-set, but ordered by a caller-supplied comparator function.
Example:
(sorted-set-by (fn [a b] (compare b a)) 1 2 3)
;;=> #{3 2 1}sorted-set-put
(sorted-set-put s x)
Adds x to sorted-set s, keeping it sorted -- conj's (logos.seq) own sorted-set worker.
Example:
(sorted-set-put (sorted-set 1 2) 3)
;;=> #{1 2 3}sorted-set-remove
(sorted-set-remove s x)
Removes x from sorted-set s, keeping it sorted -- disj's (logos.seq) own sorted-set worker.
Example:
(sorted-set-remove (sorted-set 1 2 3) 2)
;;=> #{1 3}spawn
(spawn thunk)
Runs zero-arg closure thunk in a brand-new, genuine BEAM process, returning its Pid.
Example:
(do (spawn (fn [] :ok)) :spawned)
;;=> :spawnedspawn-link
(spawn-link thunk)
Like spawn, atomically linked to the calling process.
Example:
(do (spawn-link (fn [] :ok)) :spawned)
;;=> :spawnedspawn-monitor
(spawn-monitor thunk)
Like spawn, atomically monitored -- returns (pid monitor-ref).
Example:
(do (spawn-monitor (fn [] :ok)) :spawned)
;;=> :spawnedstr
(str & vs)
Stringifies every argument and concatenates. nil stringifies to "", a string passes through bare; everything else reuses the same printer pr-str does, but WITHOUT re-quoting a string argument -- "what a human should see", not "what reads back to this value" (that's pr-str).
Example:
(str "count: " 3 ", ok? " true)
;;=> "count: 3, ok? true"string?
(string? x)
True if x is a Logos string. Kept as a primitive (not built on type-of, unlike the other type predicates) specifically so defn/defmacro/defn- can detect an optional leading docstring argument before type-of's own wrapper macros exist yet.
Example:
(string? "hi")
;;=> truesymbol
(symbol "name") / (symbol "ns" "name")
Builds a fresh symbol (bare or namespaced) from a string -- keyword's counterpart.
Example:
(symbol "a")
;;=> asystem-argv
(system-argv)
A vector of strings -- mix logos.run's own script arguments.
Example:
(system-argv)
;;=> []throw
(throw tag) / (throw tag value)
Raises a value tagged with keyword tag (value defaults to nil), catchable by an enclosing try/catch with a matching tag.
Example:
(try (throw :oops "bad") (catch :oops e e))
;;=> "bad"to-list
(to-list coll)
Coerces coll (a list, vector, map, set, sorted-map/-set, or nil) to a plain list -- a map's entries surface as 2-element lists (k v), not vectors. Already-a-list is an O(1) no-op (same reference back). What every logos.seq function uses internally to accept any collection shape.
Example:
(to-list [1 2 3])
;;=> (1 2 3)transient
(transient coll)
Builds a mutable, in-place-editable view of vector/map/set coll, for fast repeated updates (conj!/assoc!/dissoc!/disj!/pop!) before converting back via persistent!.
Example:
(transient [1 2 3])
;;=> #<Transient>trap-exits!
(trap-exits! flag)
Sets whether the calling process traps exits (a linked process's crash arrives as an :EXIT message instead of also crashing this process) -- flag's Logos truthiness (only nil/false are falsy). Returns the PREVIOUS value of the flag (Erlang Process.flag/2's own convention), not the new one -- false the first time it's ever called in a given process.
Example:
(trap-exits! true)
;;=> falsetype-of
(type-of x)
Returns a keyword type tag for x (:nil, :integer, :decimal, :vector, ...) -- the one primitive every other type predicate (nil?/list?/vector?/map?/set?/number?/decimal?/sorted?/transient?, all pure Logos in logos.core) builds on.
Example:
(type-of [1 2])
;;=> :vectorunlink
(unlink pid)
Removes a link between the calling process and pid.
Example:
(let [p (spawn (fn [] (receive [msg] (true msg))))] (link p) (unlink p) :done)
;;=> :doneuse
(use & specs)
Like require, but implies :refer [:all] for every spec with no explicit :refer/:as.
Example:
(do (use 'logos.set) :used)
;;=> :usedvar-doc
(var-doc quoted-sym)
Resolves quoted-sym through the full refer chain and returns its Var's :doc metadata, or nil -- backs doc (logos.core).
Example:
(var-doc 'inc)
;;=> "`x` plus 1."vector
(vector & xs)
Builds a vector from its arguments, in order.
Example:
(vector 1 2 3)
;;=> [1 2 3]with-meta
(with-meta sym meta)
Returns a copy of symbol sym with its own metadata replaced by map meta.
Example:
(meta (with-meta 'x {:private true}))
;;=> {:private true}