Documentation
¶
Overview ¶
Package helpers provides shared utility functions for primitive implementations.
This package centralizes reusable patterns for implementing Scheme primitives:
Numeric Operations ¶
- NumericFoldVariadic: fold variadic args with binary operation (+, *)
- NumericFoldWithFirst: fold with required first arg (-, /)
- NumericChainCompare: chain comparisons (=, <, >, <=, >=)
- NumericExtremum: find min/max with exactness contagion
- IntegerFold: integer fold for gcd/lcm with big.Int fallback
Comparisons ¶
- Eqv: R7RS eqv? semantics for memv/assv
- CharCompare, CharCompareVariadic: character comparisons
- StringCompare, StringCompareVariadic: string comparisons
Type Conversion ¶
- ToComplex128, ToFloat64: convert Scheme numbers to Go types
- ComplexOrFloat: return Float if imaginary part is zero
- MakeTypePredicate: factory for type predicate primitives
- MakeNumericPredicate: factory for numeric predicates (exact?, zero?, etc.)
Sequence Accessors ¶
- SequenceLength: generic length for Vector/ByteVector
- SequenceRef: generic indexed read with element conversion closure
- SequenceSet: generic indexed mutation with element setter closure
List Operations ¶
- ListToVector: convert list to vector
- AssocLookup: generic alist lookup with custom equality
Index ¶
- func AssocLookup(mc machine.CallContext, name string, eq func(a, b values.Value) bool) error
- func CharCompare(mc machine.CallContext, name string, cmp func(a, b rune) bool) error
- func CharCompareVariadic(mc machine.CallContext, name string, cmp func(a, b rune) bool) error
- func CheckIndexBounds(idx int64, length int, name string) error
- func CollectStrings(rest values.Value, name string) ([]*values.String, [][]rune, int, error)
- func CollectVectors(rest values.Value, name string) ([]*values.Vector, int, error)
- func ComplexOrFloat(c complex128) values.Value
- func EqIdentity(a, b values.Value) bool
- func Eqv(a, b values.Value) bool
- func ExtractInteger(v values.Value, name string) (int64, *big.Int, bool, error)
- func ExtractReal(v values.Value, name string) (float64, bool, error)
- func FloorDivide(n0, n1 int64) (q, r int64)
- func ForEachList(ctx context.Context, t values.Tuple, name string, ...) error
- func GcdInt(a, b int64) int64
- func IntegerFold(mc machine.CallContext, op FoldOp, identity int64, ...) error
- func ListToVector(mc machine.CallContext, name string) error
- func MakeCharPredicate(name string, test func(rune) bool) machine.ForeignFunction
- func MakeCharTransform(name string, transform func(rune) rune) machine.ForeignFunction
- func MakeNumericPredicate[T any](name string, sentinel error, test func(T) bool) machine.ForeignFunction
- func MakeTypePredicate(check func(values.Value) bool) machine.ForeignFunction
- func MaybeToInexact(n values.Number, hasInexact bool) values.Value
- func MemberLookup(mc machine.CallContext, name string, eq func(a, b values.Value) bool) error
- func NumericChainCompare(mc machine.CallContext, name string, fails func(prev, curr values.Number) bool) error
- func NumericChainCompareReal(mc machine.CallContext, name string, fails func(prev, curr values.Number) bool) error
- func NumericExtremum(mc machine.CallContext, name string, ...) error
- func NumericFoldVariadic(mc machine.CallContext, name string, identity values.Number, ...) error
- func NumericFoldWithFirst(mc machine.CallContext, name string, ...) error
- func OptionalArg[T any](rest values.Value, defaultVal T, sentinel error, name string) (T, error)
- func ParseOptionalArg(rest values.Value) (values.Value, bool)
- func ParseOptionalStartEnd(rest values.Value, defaultEnd int64, name string) (int64, int64, error)
- func ParseSubrange(rest values.Value, length int, name string) (int, int, error)
- func RequireArg[T any](mc machine.CallContext, index int, sentinel error, name string) (T, error)
- func RequireIndex(mc machine.CallContext, argIdx int, length int, name string) (int, error)
- func RequireType[T any](v values.Value, sentinel error, name string) (T, error)
- func SequenceLength[T interface{ ... }](mc machine.CallContext, sentinel error, name string) error
- func SequenceRef[T interface{ ... }](mc machine.CallContext, sentinel error, name string, ...) error
- func SequenceSet[T interface{ ... }](mc machine.CallContext, sentinel error, name string, ...) error
- func StringCompare(mc machine.CallContext, name string, cmp func(a, b string) bool) error
- func StringCompareVariadic(mc machine.CallContext, name string, cmp func(a, b string) bool) error
- func ToComplex128(v values.Value) (complex128, error)
- func ToFloat64(v values.Value) (float64, error)
- func ValidateStartEnd(start, end, length int64, name string) error
- type FoldOp
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssocLookup ¶
AssocLookup is a helper for alist lookup primitives (assq, assv, assoc). Takes key at index 0, alist at index 1. Uses eq predicate to find match.
func CharCompare ¶
CharCompare is a helper for binary character comparison primitives. It extracts two characters from the primitive's arguments and applies the comparator.
func CharCompareVariadic ¶
CharCompareVariadic is a helper for variadic character comparison primitives. It extracts characters from the variadic args and applies the comparator pairwise.
func CheckIndexBounds ¶ added in v1.2.0
CheckIndexBounds validates that idx is in range [0, length). Returns a wrapped ErrIndexOutOfRange error if the index is out of bounds.
func CollectStrings ¶ added in v1.5.0
CollectStrings extracts zero or more strings from a rest argument, validates that each element is a string, converts them to rune slices, and returns the minimum length of the strings. Callers are responsible for rejecting an empty argument list if a non-empty list is required. Used by string-map and string-for-each.
func CollectVectors ¶ added in v1.2.0
CollectVectors extracts a non-empty list of vectors from a rest argument, validates that each element is a vector, and returns the minimum length. Used by vector-map, vector-for-each, and vector-append.
func ComplexOrFloat ¶
func ComplexOrFloat(c complex128) values.Value
ComplexOrFloat returns a Float if the imaginary part is zero, otherwise returns a Complex. This follows R7RS behavior where real results are returned as real numbers. Special case: If both parts are NaN, returns Float(NaN) since this typically results from operations on real NaN inputs.
func EqIdentity ¶ added in v1.6.0
EqIdentity implements eq? semantics: pointer identity for all types except symbols, which compare by name (R7RS §6.1, §6.5).
func Eqv ¶
Eqv is a helper implementing eqv? semantics for memv and assv.
R7RS §6.1: eqv? returns #t for numbers that are = and both exact or both inexact. For exact integers (Integer and BigInteger), this means comparing numeric values.
func ExtractInteger ¶ added in v1.3.0
ExtractInteger extracts an integer value from Integer, BigInteger, or Float (if integral). Returns (int64Value, bigIntValue, isInexact, error). If bigIntValue is non-nil, use that; otherwise use int64Value.
R7RS §6.2.6: Integer operations accept exact and inexact integer arguments.
func ExtractReal ¶ added in v1.3.0
ExtractReal extracts a float64 from a real number, tracking exactness. Returns the float64 value, whether the input was exact, and any error.
R7RS §6.2.6: Division procedures work on all real numbers.
func FloorDivide ¶
FloorDivide performs floor division, returning quotient and remainder.
func ForEachList ¶ added in v1.10.7
func ForEachList(ctx context.Context, t values.Tuple, name string, fn func(context.Context, int, bool, values.Value) error) error
ForEachList calls fn on each element of t and returns ErrNotAList if the tail is not an empty list (i.e., t is an improper list). If fn returns an error, that error is returned unchanged.
func IntegerFold ¶
func IntegerFold( mc machine.CallContext, op FoldOp, identity int64, combiner func(acc, val int64) (int64, bool), ) error
IntegerFold is a helper for integer fold operations (gcd, lcm). Takes rest args at index 0, applies absolute value, then folds with combiner.
R7RS §6.2.6: gcd and lcm accept either exact or inexact integer arguments and always return an integer. If any argument is inexact, the result is inexact.
The fold pattern combines a list into a single value using a binary operation:
fold(f, identity, [a, b, c]) = f(f(f(identity, a), b), c)
See SRFI-1 (List Library) for the canonical Scheme definition of fold:
https://srfi.schemers.org/srfi-1/srfi-1.html
func ListToVector ¶
func ListToVector(mc machine.CallContext, name string) error
ListToVector is a helper that converts a list argument to a vector.
func MakeCharPredicate ¶ added in v1.5.0
func MakeCharPredicate(name string, test func(rune) bool) machine.ForeignFunction
MakeCharPredicate creates a character predicate primitive that extracts arg 0 as a Character and applies a boolean test on the rune value.
func MakeCharTransform ¶ added in v1.5.0
func MakeCharTransform(name string, transform func(rune) rune) machine.ForeignFunction
MakeCharTransform creates a character transformation primitive that extracts arg 0 as a Character, applies a rune transformation, and returns a new Character.
func MakeNumericPredicate ¶ added in v1.2.0
func MakeNumericPredicate[T any]( name string, sentinel error, test func(T) bool, ) machine.ForeignFunction
MakeNumericPredicate creates a numeric predicate primitive that extracts arg 0 via RequireArg[T] and applies a boolean test. Unlike MakeTypePredicate, this returns an error if the argument doesn't satisfy the type constraint (e.g., "exact? requires a number").
T is typically values.Number or values.RealNumber.
func MakeTypePredicate ¶
func MakeTypePredicate(check func(values.Value) bool) machine.ForeignFunction
MakeTypePredicate creates a type predicate primitive function. The check function should return true if the value matches the expected type.
func MaybeToInexact ¶
MaybeToInexact converts an exact number to inexact if needed. If the number is already inexact or hasInexact is false, returns it unchanged.
func MemberLookup ¶ added in v1.5.0
MemberLookup is a helper for list membership primitives (memq, memv). Takes obj at index 0, list at index 1. Uses eq predicate to find match. On match, returns the tail of the list starting at the matched element.
func NumericChainCompare ¶
func NumericChainCompare( mc machine.CallContext, name string, fails func(prev, curr values.Number) bool, ) error
NumericChainCompare is a helper for numeric chain comparison primitives. First arg at index 0, rest at index 1. Returns true if all consecutive pairs satisfy the comparator, false otherwise.
func NumericChainCompareReal ¶ added in v1.3.0
func NumericChainCompareReal( mc machine.CallContext, name string, fails func(prev, curr values.Number) bool, ) error
NumericChainCompareReal is a helper for ordering comparison primitives (<, >, <=, >=). It wraps NumericChainCompare with complex-number rejection: any non-real complex argument causes an immediate error rather than a boolean #f result.
The fails callback should return true when the comparison fails (i.e. the pair does not satisfy the ordering relation), false when it succeeds.
func NumericExtremum ¶
func NumericExtremum( mc machine.CallContext, name string, isBetter func(candidate, current values.Number) bool, ) error
NumericExtremum is a helper for min/max primitives. First arg at index 0, rest at index 1. Returns the extremum value where isBetter returns true if candidate should replace current. Per R7RS, if any argument is inexact, the result is inexact.
func NumericFoldVariadic ¶
func NumericFoldVariadic( mc machine.CallContext, name string, identity values.Number, binOp func(acc, val values.Number) (values.Number, error), ) error
NumericFoldVariadic is a helper for variadic arithmetic operations (+ and *). It takes a rest parameter at index 0 and folds with the binary operation. Returns identity for empty list, first arg for single element.
func NumericFoldWithFirst ¶
func NumericFoldWithFirst( mc machine.CallContext, name string, unaryOp func(val values.Number) (values.Number, error), binOp func(acc, val values.Number) (values.Number, error), ) error
NumericFoldWithFirst is a helper for arithmetic operations with required first arg (- and /). First arg at index 0, rest at index 1. Applies unaryOp for single arg case.
func OptionalArg ¶ added in v1.5.0
OptionalArg extracts an optional typed argument from variadic rest args. If no argument is present, defaultVal is returned. If present but not of type T, an error using sentinel and name is returned.
func ParseOptionalArg ¶ added in v1.3.0
ParseOptionalArg extracts a single optional argument from variadic rest args. Returns the value and true if present, or nil and false if rest is empty or not a valid argument list.
func ParseOptionalStartEnd ¶ added in v1.1.0
ParseOptionalStartEnd extracts optional [start [end]] integer arguments from a rest list. defaultEnd is the value used if end is not provided. name is used in error messages (e.g., "bytevector-copy").
func ParseSubrange ¶ added in v1.2.0
ParseSubrange extracts optional [start [end]] from a rest list, validates bounds against length, and returns the range as int values. This bundles ParseOptionalStartEnd + ValidateStartEnd + int conversion for the common case where the caller works with int-indexed collections.
func RequireArg ¶ added in v1.1.0
RequireArg extracts mc.Arg(index) and asserts it has concrete type T. On failure it returns a wrapped error using the given sentinel and primitive name. The error message format is "<name>: expected <type> but got <actual>", where <type> is derived from the sentinel message by trimming the "not " prefix (e.g., ErrNotAVector "not a vector" → "a vector").
func RequireIndex ¶ added in v1.2.0
RequireIndex extracts an exact integer index from mc.Arg(argIdx) and validates it is in range [0, length). Accepts *Integer, *BigInteger, and integer-valued *Rational via values.ExactInteger, which is more R7RS-correct than requiring *Integer alone (R7RS §6.1: indices are exact non-negative integers).
func RequireType ¶ added in v1.1.0
RequireType asserts that v has concrete type T. On failure it returns a wrapped error using the given sentinel and primitive name.
func SequenceLength ¶ added in v1.2.0
func SequenceLength[T interface{ Length() int }](
mc machine.CallContext,
sentinel error,
name string,
) error
SequenceLength extracts a sequence of type T from arg 0, and sets the machine context value to its length as an exact integer. T must be a pointer type satisfying interface{ Length() int }.
func SequenceRef ¶ added in v1.2.0
func SequenceRef[T interface{ Length() int }](
mc machine.CallContext,
sentinel error,
name string,
getElement func(T, int) values.Value,
) error
SequenceRef extracts a sequence of type T from arg 0, validates an exact integer index from arg 1, and sets the machine context value to getElement(seq, idx). The getElement closure handles type-specific element retrieval (e.g., Vector.Get vs ByteVector byte-to-integer conversion).
func SequenceSet ¶ added in v1.2.0
func SequenceSet[T interface{ Length() int }](
mc machine.CallContext,
sentinel error,
name string,
setElement func(T, int, machine.CallContext) error,
) error
SequenceSet extracts a sequence of type T from arg 0, validates an exact integer index from arg 1, and delegates to setElement(seq, idx, mc) for the type-specific mutation. Sets Void on success.
func StringCompare ¶
StringCompare is a helper for binary string comparison primitives. It extracts two strings from the primitive's arguments and applies the comparator.
func StringCompareVariadic ¶
StringCompareVariadic is a helper for variadic string comparison primitives. It extracts strings from the variadic args and applies the comparator pairwise.
func ToComplex128 ¶
func ToComplex128(v values.Value) (complex128, error)
ToComplex128 converts a Scheme number to a Go complex128. This supports all numeric types: Integer, BigInteger, Float, BigFloat, Rational, Complex, and BigComplex.
func ToFloat64 ¶
ToFloat64 converts a Scheme real number to a Go float64, covering the full real numeric tower: Integer, BigInteger, Float, BigFloat, and Rational. Complex types are excluded — they cannot be reduced to a single float64 without information loss. Use ToComplex128 for complex values.
func ValidateStartEnd ¶ added in v1.2.0
ValidateStartEnd checks the invariant 0 <= start <= end <= length. Returns a wrapped ErrIndexOutOfRange error if any bound is violated.