hissp.basic module

Hissp’s basic macros.

The basic 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 basic 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.basic.._macro_.alias b/ hissp.basic.._macro_.)
;; Now the same as (hissp.basic.._macro_.define foo 2).
(b/#define foo 2)

The basic 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_ 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 basic macros lack some of the extra features their equivalents have in Python or in other Lisps.

macros

hissp.basic._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.basic._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.basic._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.basic._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.basic._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.basic._macro_.alias(alias, module)

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

(hissp.basic.._macro_.alias M/ hissp.basic.._macro_)
;; Now the same as (hissp.basic.._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.basic._macro_.anyQz_for(variable, iterable, *body)

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

hissp.basic._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.basic._macro_.bQzHASH_(raw)

b# bytes literal reader macro

hissp.basic._macro_.cond(*pairs)

Multiple condition branching.

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

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

Assigns a global the value in the current module.

hissp.basic._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.basic._macro_.deftype(name, bases, *body)

Defines a type (class) in the current module.

Key-value pairs are implied in the body.

hissp.basic._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.basic._macro_.enQzHASH_(f)

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

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

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

#> _
>>> _
[1, 2, 3, 4, 5, 6]
hissp.basic._macro_.ifQz_else(test, then, otherwise)

if-else Basic ternary branching construct.

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

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

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

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

The basic prelude.

Imports functools.partial and functools.reduce. Star imports from itertools and operator. Defines the en- group: entuple, enlist, enset, endict, and enstr, which build collections from individual elements, and engarde, which calls a function for you, handling any targeted exception with the given handler.

Adds the basic 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.basic.._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 basic macros loaded by default, but not the prelude. Invoke (prelude) to get the rest.

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

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

hissp.basic._macro_.progn(*body)

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

hissp.basic._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.basic._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 ().