hissp.macros module

Hissp’s bundled macros.

The bundled macros are just enough to test and demonstrate Hissp’s macro system; they are not intended to be a standard library for general use, but may suffice for small projects.

As a convenience, they are automatically made available unqualified in the Lissp REPL, but this does not apply to modules. (A Hissp module with better alternatives need not use the bundled macros at all.) In modules, either use the fully-qualified names, or start with the prelude macro.

You can abbreviate qualifiers with the alias macro:

(hissp.._macro_.alias b/ hissp.._macro_.)
;; Now the same as (hissp.._macro_.define foo 2).
(b/#define foo 2)

The bundled macros are deliberately restricted in design.

They have NO DEPENDENCIES in their expansions; they use only the standard library with no extra helper functions. This means that all helper code must be inlined, resulting in larger expansions than might otherwise be necessary. But because macros expand before run time, the compiled code does not require Hissp to be installed to work.

They also have no prerequisite initialization, beyond what is available in a standard Python module. For example, a _macro_ namespace need not be available for defmacro. It’s smart enough to check for the presence of _macro_ (at compile time) in its expansion context, and inline the initialization code when required.

With the exception of prelude (which uses exec), they also eschew any expansions to Python code, relying only on the built-in special forms quote and lambda, which makes their expansions compatible with advanced rewriting macros that process the Hissp expansions of other macros.

To help keep macro definitions and expansions manageable in complexity, these macros lack some of the extra features their equivalents have in Python or in other Lisps.

_macro_

hissp.macros._macro_.QzAT_(*xs)

@ ‘list of’

:* unpacks the next argument. Mnemonic: @rray list.

hissp.macros._macro_.QzAT_QzHASH_(symbol)

@# ‘attrgetter-’ Makes an attr getter function from the symbol.

hissp.macros._macro_.QzBAR_QzBAR_(first=(), *rest)

|| ‘or’. Shortcutting logical OR. Returns the first true value, otherwise the last value. There is an implicit initial value of ().

hissp.macros._macro_.QzET_QzET_(*exprs)

&& ‘and’. Shortcutting logical AND. Returns the first false value, otherwise the last value. There is an implicit initial value of True.

hissp.macros._macro_.QzET_QzHASH_(e)

&# ‘thunk’ Make e an anonymous function with no parameters.

hissp.macros._macro_.QzHASH_(*xs)

# ‘set of’

:* unpacks the next argument. Mnemonic: Hash (#) set.

hissp.macros._macro_.QzLT_QzLT_QzHASH_(single, *lines)

<<# comment-string reader macro.

Converts a line comment to a raw string.

#> <<#;Don't worry about the "quotes".
>>> 'Don\'t worry about the "quotes".'
'Don\'t worry about the "quotes".'

Or joins extra comments with a string object, such as #"\n".

#> <<#
#..!;C:\bin
#..!;C:\Users\ME\Documents
#..!;C:\Users\ME\Pictures
#..";"
>>> 'C:\\bin;C:\\Users\\ME\\Documents;C:\\Users\\ME\\Pictures'
'C:\\bin;C:\\Users\\ME\\Documents;C:\\Users\\ME\\Pictures'
hissp.macros._macro_.QzPCENT_(*kvs)

% ‘dict of’.

Key-value pairs are implied. :** unpacks mappings. Mnemonic: dict of pairs (%).

hissp.macros._macro_.Qz_QzGT_(expr, *forms)

-> ‘Thread-first’.

Converts a pipeline to function calls by recursively threading expressions as the first argument of the next form. E.g. (-> x (A b) (C d e)) is (C (A x b) d e) Makes chained method calls easier to read.

hissp.macros._macro_.Qz_QzGT_QzGT_(expr, *forms)

->> ‘Thread-last’.

Converts a pipeline to function calls by recursively threading expressions as the last argument of the next form. E.g. (->> x (A b) (C d e)) is (C d e (A b x)). Can replace partial application in some cases. Also works inside a -> pipeline. E.g. (-> x (A a) (->> B b) (C c)) is (C (B b (A x a)) c).

hissp.macros._macro_.XQzHASH_(e)

X# Anaphoric. Make e an anonymous function with paramter X.

hissp.macros._macro_.XYQzHASH_(e)

XY# Anaphoric. Make e an anonymous function with paramters X Y.

hissp.macros._macro_.XYZQzHASH_(e)

XYZ# Anaphoric. Make e an anonymous function with paramters X Y Z.

hissp.macros._macro_.XYZWQzHASH_(e)

XYZW# Anaphoric. Make e an anonymous function with paramters X Y Z W.

hissp.macros._macro_.alias(alias, module)

Defines a reader macro abbreviation of a qualifier. For example,

(hissp.macros.._macro_.alias M/ hissp.macros.._macro_)
;; Now the same as (hissp.macros.._macro_.alias op sub.).
(M/#alias op operator.)
;; Use an extra to name a reader macro.
M/#!b"byte string"
(op#sub 2 3)
#> op#!pow !3 2
>>> (8)
8
hissp.macros._macro_.anyQzSTAR_map(variables, xss, *body)

any*map ‘any star map’ Bind each x to a variable and evaluate the body for each xs from xss until any result is true (and return True), or until xss is exhausted (and return False).

hissp.macros._macro_.anyQz_map(variable, xs, *body)

any-map Bind the variable and evaluate the body for each x from xs until any result is true (and return True), or until xs is exhausted (and return False).

hissp.macros._macro_.attach(target, *args)

Attaches the named variables to the target as attributes.

Positional arguments must be unqualified identifiers, and use that as the attribute name. Names after the : are identifier-value pairs. Returns the target.

hissp.macros._macro_.bQzHASH_(raw)

b# bytes literal reader macro

hissp.macros._macro_.case(key, default, *pairs)

Switch case macro. Must switch on a hashable key. The default case is first and required. The remainder are implicitly paired.

hissp.macros._macro_.chainQzHASH_(itr)

chain# Abbreviation for itertools.chain.from_iterable

hissp.macros._macro_.cond(*pairs)

Multiple condition branching.

Pairs are implied. Default is (). Use :else to change it. For example:

(cond) ; ()
;; Assume some number 'x
(cond (op#gt x 0) (print "positive")
      (op#lt x 0) (print "negative")
      (op#eq x 0) (print "zero")
      :else (print "not a number"))
hissp.macros._macro_.define(name, value)

Assigns a global the value in the current module.

hissp.macros._macro_.defmacro(name, parameters, docstring=(), *body)

Creates a new macro for the current module.

If there’s no _macro_, creates one (using types.ModuleType). If there’s a docstring, stores it as the new lambda’s __doc__. Adds the _macro_ prefix to the lambda’s __qualname__. Saves the lambda in _macro_ using the given attribute name.

hissp.macros._macro_.defonce(name, value)

Assigns a global the value in the current module, unless it exists.

hissp.macros._macro_.deftype(name, bases, *body)

Defines a type (class) in the current module.

Key-value pairs are implied in the body.

hissp.macros._macro_.deftypeQzAT_(decorators, name, bases, *body)

deftype@ Defines a decorated type (class) in the current module.

Key-value pairs are implied in the body.

hissp.macros._macro_.doto(self, *invocations)

Configure an object.

Calls multiple ‘methods’ on one ‘self’.

Evaluates the given self, then injects it as the first argument to a sequence of invocations. Returns self.

hissp.macros._macro_.enQzHASH_(f)

en# reader macro. Wrap a function of one iterable as a function of its elements.

#> (en#list 1 2 3)
>>> (lambda *_QzNo53_xs:
...   list(
...     _QzNo53_xs))(
...   (1),
...   (2),
...   (3))
[1, 2, 3]

#> (en#.extend _ 4 5 6) ; Methods too.
>>> (lambda _QzNo52_self,*_QzNo52_xs:
...   _QzNo52_self.extend(
...     _QzNo52_xs))(
...   _,
...   (4),
...   (5),
...   (6))

#> _
>>> _
[1, 2, 3, 4, 5, 6]
hissp.macros._macro_.ensure(e, predicate, *args)

Anaphoric. Raises AssertionError unless (-> e predicate).

Additional arguments are evaluated in a context where it refers to the result of e. These (if any) are passed to the AssertionError.

Compilation is simply the it when __debug__ is off.

hissp.macros._macro_.getQzHASH_(e)

get# ‘itemgetter-’ Makes an item getter function from e.

hissp.macros._macro_.iQzHASH_(_QzNo27_prime, _QzNo27_reader=None, *_QzNo27_args)

Aliases itertools. as i#.

hissp.macros._macro_.ifQz_else(test, consequent, alternate)

if-else Basic ternary branching construct.

Like Python’s conditional expressions, the ‘else’ clause is required.

hissp.macros._macro_.let(pairs, *body)

Creates local variables. Pairs are implied. Locals are not in scope until the body.

hissp.macros._macro_.letQzSTAR_from(pairs, *body)

let*from Nested let-from.

hissp.macros._macro_.letQz_from(syms, itr, *body)

let-from Create listed locals from iterable.

hissp.macros._macro_.loopQz_from(syms, inits, *body)

loop-from Anaphoric. Loop/recur with trampoline.

Set local values for the first loop with an iterable as let-from.

Creates a stack to schedule future loops. Call the recur-from anaphor with an iterable of values for the locals to push another loop to the schedule. Call with None to abort any remaining schedule.

Returns the value of the final loop.

hissp.macros._macro_.opQzHASH_(_QzNo27_prime, _QzNo27_reader=None, *_QzNo27_args)

Aliases operator. as op#.

hissp.macros._macro_.prelude(ns=('builtins..globals',))

Hissp’s bundled micro prelude.

Brings Hissp up to a minimal standard of usability without adding any dependencies in the compiled output.

Imports functools.partial and functools.reduce. Star imports from itertools and operator.

Defines engarde, which calls a function for you, handling any targeted exceptions with the given handler.

Defines enter, which calls a function with a context manager.

Defines Ensue for trampolined continuation generators.

Adds the bundled macros, but only if available, so its expansion does not require Hissp to be installed. (This replaces _macro_ if you already had one.)

Mainly intended for single-file scripts that can’t have dependencies, or similarly constrained environments (e.g. embedded, readerless). There, the first form should be (hissp.._macro_.prelude), which is also implied in $ lissp -c commands.

Larger projects with access to functional and macro libraries need not use this prelude at all.

The REPL has the bundled macros loaded by default, but not the prelude. Invoke (prelude) to get the rest.

hissp.macros._macro_.prog1(expr1, *body)

Evaluates each expression in sequence (for side effects), resulting in the value of the first.

hissp.macros._macro_.progn(*body)

Evaluates each body expression in sequence (for side effects), resulting in the value of the last (or () if empty).

hissp.macros._macro_.setQzAT_(name, val)

set@ ‘setat’ Assigns an attribute, returns the value. Mnemonic: set @tribute.

hissp.macros._macro_.setQzBANG_(coll, key, val)

set! ‘setbang’ Assigns an item, returns the value. Mnemonic: set !tem.

hissp.macros._macro_.spyQzHASH_(e)

spy# Print e => its value to stderr, return the value.

hissp.macros._macro_.theQzHASH_(e)

the# Anaphoric. Let the be a fresh types.SimpleNamespace in a lexical scope surrounding e.

hissp.macros._macro_.throw(exception)

Raise an exception.

hissp.macros._macro_.throwQzSTAR_(*exception)

throw* Creates a closed generator and calls its throw method.

Despite PEP 3109, .throw still seems to accept multiple arguments. You should basically never use more than one, except when implementing your own throw method overrides. Otherwise, use throw instead.

hissp.macros._macro_.throwQz_from(exception, cause)

Raise an exception with a cause, which can be None.

hissp.macros._macro_.timeQzHASH_(e)

time# Measure execution time of e, return its value.

hissp.macros._macro_.unless(condition, *body)

Unless the condition is true, evaluates each expression in sequence for side effects, resulting in the value of the last. Otherwise, skips them and returns ().

hissp.macros._macro_.when(condition, *body)

When the condition is true, evaluates each expression in sequence for side effects, resulting in the value of the last. Otherwise, skips them and returns ().

hissp.macros._macro_.zapQzAT_(op, name, *args)

zap@ ‘zapat’ Augmented attribute assignment operator.

The current attribute value becomes the first argument. Mnemonic: zap @tribute.

hissp.macros._macro_.zapQzBANG_(op, coll, key, *args)

zap! ‘zapbang’ Augmented item assignment operator.

The current item value becomes the first argument. Mnemonic: zap !tem.