hissp.macros module#
Hisspâs bundled tag and macro metaprograms.
While completely optional, these bring Hissp up to a minimal standard of
practical utility without adding dependencies. As a convenience, they
are automatically made available unqualified in the Lissp REPL, but
this is not true of modules.
Hisspâs standalone property means the compiled output of code written
using these metaprograms need not have Hissp installed at run time to
work, only the Python standard library. All helper code must therefore
be inlined, resulting in larger expansions than might otherwise be
necessary.
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 mix, which is a text macro specifically made
for creating a Python injection, the other metaprograms eschew
expansions of any of their arguments to a Python injection (other than
the standard symbol or string literal fragment cases), 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.
(The -[# and my# tags are also something of an
exception, as one argument is written in Python to begin with.)
That only goes for arguments and doesnât apply to inlined helper
functions in the expansions that contain no user code, because thatâs no
worse than using an opaque name imported from somewhere else. if-else is one such example, expanding to a lambda containing an
injected conditional expression, that is called immediately.
_macro_#
Hisspâs bundled tag and macro namespace.
See hissp.macros.
- hissp.macros._macro_.At_(*xs)#
@âlist ofâMnemonic: @rray list.
Creates the
listfrom each expressionâs result. A:*unpacks the next argument:#> (@ :* "AB" (math..sqrt 9) :* "XY" 2 1) >>> # At_ ... (lambda *xs: [*xs])( ... *('AB'), ... __import__('math').sqrt( ... (9)), ... *('XY'), ... (2), ... (1)) ['A', 'B', 3.0, 'X', 'Y', 2, 1]
See also:
#,%,en#,operator.matmul.
- hissp.macros._macro_.At_Hash_(decoration_or_attr=None, definition=None, /, **attr)#
Overloads:
@#âattribute tagâ gets attribute.@##âdecoratorâ applies decoration to definition and reassigns.
Mnemonic: @tribute.
#> (@#join="" (filter @#intersection=(set "abc") "abracadabra")) >>> # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'join')( ... (''))( ... filter( ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'intersection')( ... set( ... ('abc'))), ... ('abracadabra'))) 'abacaaba' #> (@#'__class__.__name__ 1+1j) ; Note the `.`. >>> # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... '__class__.__name__')( ... ((1+1j))) 'complex' #> (let (eggs @#'upper #.. spam 'intersection) #.. ;; Various chaining techniques. Note ' and =@#. #.. @#__name__=@#__class__=(-> (set) @#spam @#'__doc__ eggs)) >>> # let ... ( ... lambda eggs=# hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'upper'), ... spam='intersection': ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... '__name__')( ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... '__class__')( ... # Dash_Gt_ ... eggs( ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... '__doc__')( ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... spam)( ... set()))))) ... )() 'builtin_function_or_method'
See also:
getattr,operator.attrgetter,X#,!#.
Definition form must assign an attribute identified by its first arg. Expands to a
define, meaning decorators can stack.Decorator syntax is for definitions, like
defineanddefun, and would work on any definition macro that has the definition qualname as its first argument (notdefmacro, butdefuncan target the_macro_namespace if it exists).Use
zap@to decorate an attribute after its definition.#> @##.swapcase #..@##.title #..(define spam 'spam) ; Unlike Python def, not always a function. >>> # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... spam=# hissp.macros.._macro_.progn ... (# hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... spam=# hissp.macros.._macro_.progn ... (# define ... __import__('builtins').globals().update( ... spam='spam'), ... spam.title()) [-1]), ... spam.swapcase()) [-1]) #> spam >>> spam 'sPAM'
- hissp.macros._macro_.At_sHash_(names)#
@s#âattribute namesâdestruct->helper shorthand. Destructures a namespace using the binding names as the attributes.#> (destruct-> (types..SimpleNamespace : spam 1 foo 2) #.. (|| whole #.. || @s#(spam foo)) #.. (print whole spam foo)) >>> # destruct___Gt_ ... # hissp.macros.._macro_.let___call ... (lambda whole, spam, foo: ... print( ... whole, ... spam, ... foo) ... )( ... *# hissp.macros.._macro_.let ... ( ... lambda _g4JOGNIEV__data=__import__('types').SimpleNamespace( ... spam=(1), ... foo=(2)): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... ( ... _g4JOGNIEV__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _g4JOGNIEV__data=# hissp.macros.._macro_.Dash_Gt_ ... ( ... _g4JOGNIEV__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'spam')( ... _g4JOGNIEV__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'foo')( ... _g4JOGNIEV__data), ... ) ... )(), ... ) ... )()) namespace(spam=1, foo=2) 1 2
- hissp.macros._macro_.BHash_(symbol)#
B#âbytesymbolâConverts a
parsed objectof typestrtobytes.#> B#|bytes!| >>> b'bytes!' b'bytes!' #> B#oops! ; Works directly on symbols, but beware munging. >>> b'oopsBang_' b'oopsBang_' #> B#"oops!" ; You probably wanted b# instead. >>> b"('oops!')" b"('oops!')" #> B#.#"OK" ; Note the .#. >>> b'OK' b'OK' #> B#|\xff || "\n'" BBQ| ; Escapes allowed, like b#. >>> b'\xff | "\n\'" BBQ' b'\xff | "\n\'" BBQ'
See also:
b#.
- hissp.macros._macro_.Bang_Hash_(*keys)#
!#âitem tagâMnemonic: !tem.
#> (define first !#0) ;Gets an item by index. >>> # define ... __import__('builtins').globals().update( ... first=# hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))) #> (first "abc") >>> first( ... ('abc')) 'a' #> (!#(slice None None -1) "abc") ;Slicing without injection. >>> # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... slice( ... None, ... None, ... (-1)))( ... ('abc')) 'cba' #> (!###2 0 1 "abc") ;Multiple lookups. >>> # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (2), ... (0), ... (1))( ... ('abc')) ('c', 'a', 'b') #> (!#'+ (dict : foo 2 + 1)) ;These also work on dicts. >>> # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... 'Plus_')( ... dict( ... foo=(2), ... Plus_=(1))) 1 #> (-> '(foo bar) !#1 .upper !#0) ;Unary compatible with ->. >>> # Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))( ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (1))( ... ('foo', ... 'bar',)).upper()) 'B'
See also:
operator.getitem,operator.itemgetter,[#,set!,@#.
- hissp.macros._macro_.Bang_sHash_(names)#
!s#âitem namesâdestruct->helper shorthand. Destructures a mapping using the binding names as the keys.#> (destruct-> (dict : spam 1 foo 2) #.. (|| whole #.. || !s#(spam foo)) #.. (print whole spam foo)) >>> # destruct___Gt_ ... # hissp.macros.._macro_.let___call ... (lambda whole, spam, foo: ... print( ... whole, ... spam, ... foo) ... )( ... *# hissp.macros.._macro_.let ... ( ... lambda _gK53PHZRK__data=dict( ... spam=(1), ... foo=(2)): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... ( ... _gK53PHZRK__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _gK53PHZRK__data=# hissp.macros.._macro_.Dash_Gt_ ... ( ... _gK53PHZRK__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... 'spam')( ... _gK53PHZRK__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... 'foo')( ... _gK53PHZRK__data), ... ) ... )(), ... ) ... )()) {'spam': 1, 'foo': 2} 1 2
- hissp.macros._macro_.Colon_Hash_(attr, /, *args, **kwargs)#
Aliases
unittest.mock..sentinelasColon_#.
- hissp.macros._macro_.Dash_Gt_(expr, *forms)#
->âThread-firstâ.Converts a pipeline to function calls by recursively threading expressions as the first argument of the next form. Non-tuple forms (typically function identifiers) will be wrapped in a tuple. Can make chained method calls easier to read.
#> ((|| _macro_.->) 'x '(A a) 'B '(C c cc)) >>> ( ... _macro_.Dash_Gt_)( ... 'x', ... ('A', ... 'a',), ... 'B', ... ('C', ... 'c', ... 'cc',)) ('C', ('B', ('A', 'x', 'a')), 'c', 'cc') #> (-> 'a set (en#list 'bc) (en#tuple 'de)) >>> # Dash_Gt_ ... (lambda *_gJHUL5GC3__xs: ... tuple( ... _gJHUL5GC3__xs) ... )( ... (lambda *_gJHUL5GC3__xs: ... list( ... _gJHUL5GC3__xs) ... )( ... set( ... 'a'), ... 'bc'), ... 'de') ([{'a'}, 'bc'], 'de')
- hissp.macros._macro_.Dash_Lt_Gt_Gt_(expr, *forms)#
-<>>âThread-throughâ.Converts a pipeline to function calls by recursively threading expressions into the next form at the first point indicated with
:<>, or at the last if no:<>is found. Non-tuple forms (typically function identifiers) will be wrapped in a tuple first. Can replace partial application in some cases.#> ((|| _macro_.-<>>) 'x 'A '(:<> b bb) '(C c cc)) >>> ( ... _macro_.Dash_Lt_Gt_Gt_)( ... 'x', ... 'A', ... (':<>', ... 'b', ... 'bb',), ... ('C', ... 'c', ... 'cc',)) ('C', 'c', 'cc', (('A', 'x'), 'b', 'bb')) #> (-<>> 'a set (en#list 'bc) (en#tuple 'de :<> 'fg :<>)) >>> # Dash_Lt_Gt_Gt_ ... (lambda *_gJHUL5GC3__xs: ... tuple( ... _gJHUL5GC3__xs) ... )( ... 'de', ... (lambda *_gJHUL5GC3__xs: ... list( ... _gJHUL5GC3__xs) ... )( ... 'bc', ... set( ... 'a')), ... 'fg', ... ':<>') ('de', ['bc', {'a'}], 'fg', ':<>')
- hissp.macros._macro_.Et_Hash_(f, *arg_funs, **kwarg_funs)#
forked compositionPoint-free functions.Creates a new function applying
fto the results ofarg_funsandkwarg_funs, which are each passed all arguments:#> (define mean &###op#truediv sum len) >>> # define ... __import__('builtins').globals().update( ... mean=(lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... __import__('operator').truediv( ... sum( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw), ... len( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw)) ... )) #> (mean (range 6)) >>> mean( ... range( ... (6))) 2.5
Literals or quoted forms act like constant functions:
#> (&####print &##X#X 1 _#; constant function #.. '(op#add 1 1) _#; quoted #.. sep=: _#|<-literal (and kwarg)|) >>> (lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... print( ... (lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... (lambda X: X)( ... (1)) ... )( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw), ... __import__('operator').add( ... (1), ... (1)), ... sep=':') ... )() 1:2
Chaining:
#> &##.title &###.join "" &###filter 'X#|X!='a'| sorted >>> (lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... (lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... ('').join( ... (lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... filter( ... (lambda X: X!='a'), ... sorted( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw)) ... )( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw)) ... )( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw).title() ... ) <function <lambda> at 0x...> #> (_ 'abracadabra) >>> _( ... 'abracadabra') 'Bbcdrr'
Macros can work in some cases, like
ors:#> (define symbol-or-node? &###ors H#is_symbol H#is_node) >>> # define ... __import__('builtins').globals().update( ... symbol___or___nodeEh_=(lambda *_g5FRXO76U__a, **_g5FRXO76U__kw: ... # ors ... (lambda x0, x1: x0 or x1())( ... __import__('hissp').is_symbol( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw), ... (lambda : ... __import__('hissp').is_node( ... *_g5FRXO76U__a, ... **_g5FRXO76U__kw) ... )) ... )) #> (list (map symbol-or-node? '(foo 2 () (foo)))) >>> list( ... map( ... symbol___or___nodeEh_, ... ('foo', ... (2), ... (), ... ('foo',),))) [True, False, False, True]
See also:
statistics.mean,->,destruct->.
- hissp.macros._macro_.Fsol_Hash_(f)#
/#âreduce byâ Wrap a binary function as a variadic via reduce.#> (/#operator..add 1 2 3 4) >>> (lambda *_gVBXQOUGG__xs: ... __import__('functools').reduce( ... __import__('operator').add, ... _gVBXQOUGG__xs) ... )( ... (1), ... (2), ... (3), ... (4)) 10
- hissp.macros._macro_.Fsol_XYHash_(expr)#
/XY#âreduce X Yâ Anaphoric.Make
expra reducing function with parameters X Y. The resulting function is a partial application offunctools.reduce.#> /XY#(op#add Y X) >>> __import__('functools').partial( ... __import__('functools').reduce, ... (lambda X, Y: ... __import__('operator').add( ... Y, ... X) ... )) functools.partial(<built-in function reduce>, <function <lambda> at 0x...>) #> (_ 'ABCD) >>> _( ... 'ABCD') 'DCBA'
- hissp.macros._macro_.HHash_(attr, /, *args, **kwargs)#
Aliases
hissp.asH#.
- hissp.macros._macro_.Hash_(*xs)#
#âset ofâ Mnemonic: Hash (#) set.Creates the
setfrom each expressionâs result. A:*unpacks the next argument.#> (# 1 :* (@ 1 2 3) 4) ;Set, with unpacking. >>> # Hash_ ... (lambda *xs: {*xs})( ... (1), ... *# At_ ... (lambda *xs: [*xs])( ... (1), ... (2), ... (3)), ... (4)) {1, 2, 3, 4}
- hissp.macros._macro_.Lsqb_Hash_(lookup, table=None)#
[#âsubscriptâ Injection. Pythonâs subscription operator.Interpret the lookup as Python code prepended with a
[. Primarily used for Pythonâs slice notation, but unrestricted.#> [##1][::2] '(foo bar) >>> # hissp.macros.._macro_._backapply ... (lambda _gER3ASVPQ__table: (_gER3ASVPQ__table[1][::2]))( ... ('foo', ... 'bar',)) 'br'
Unary compatible with
->.#> (-> '(foo bar) [#1] .upper [#::2]) >>> # Dash_Gt_ ... # hissp.macros.._macro_._backapply ... (lambda _gQVGKJX6Z__table: (_gQVGKJX6Z__table[::2]))( ... # hissp.macros.._macro_._backapply ... (lambda _gQVGKJX6Z__table: (_gQVGKJX6Z__table[1]))( ... ('foo', ... 'bar',)).upper()) 'BR' #> (.join "" (map [#1] '(abc xyz |123|))) >>> ('').join( ... map( ... # hissp.macros.._macro_._backapply ... (lambda _gFMSK2DQ7__table: (_gFMSK2DQ7__table[1])), ... ('abc', ... 'xyz', ... '123',))) 'by2'
See also:
!#,->,slice,Subscriptions,Slicings.
- hissp.macros._macro_.Lt_Hash_(comment)#
<#âcomment stringâ tag.Converts a block of line comments to a raw string. Roughly equivalent to
'hissp.reader..Comment.contents#.#> <#;You won't have to #..;; escape the "quotes". #.. >>> 'You won\'t have to\nescape the "quotes".' 'You won\'t have to\nescape the "quotes".'
See also:
triple-quoted string,hissp.reader.Comment.
- hissp.macros._macro_.MHash_(M)#
M#âDecimalâ Exact decimal tag.Abbreviation for
decimal.Decimal, with ademungefor symbols.Mnemonic: âMoneyâ. Chosen to resemble Clojureâs
BigDecimalliteral, likely inspired by C⯠where âDâ was taken for double-precision floats, leaving âMâ as the next best letter in âdeciMalâ.The usual construction has a trailing underscore to avoid going through a float literal, which would have limited precision:
#> M#1.23e6_ >>> # Decimal('1.23E+6') ... __import__('pickle').loads(b'cdecimal\nDecimal\n(V1.23E+6\ntR.') Decimal('1.23E+6')
When converting a read-time constant float, go through
strfirst:#> M#.#(repr math..tau) >>> # Decimal('6.283185307179586') ... __import__('pickle').loads(b'cdecimal\nDecimal\n(V6.283185307179586\ntR.') Decimal('6.283185307179586')
See also:
Q#.
- hissp.macros._macro_.OHash_(expr)#
O#âthunkâ Makeexpran anonymous function body with no parameters.See also:
X#.
- hissp.macros._macro_.Pcent_(*kvs)#
%âdict ofâ. Mnemonic:dictof pairs (%).Key-value pairs are implied by position. A
:**mapping-unpacks the next argument.#> (% 1 2 :** (dict : x 3 y 4) 5 6) ; Dict, with mapping unpacking. >>> # Pcent_ ... (lambda x0, x1, x3, x4, x5: {x0:x1,**x3,x4:x5})( ... (1), ... (2), ... dict( ... x=(3), ... y=(4)), ... (5), ... (6)) {1: 2, 'x': 3, 'y': 4, 5: 6} #> (%) >>> # Pcent_ ... {} {}
See also:
@,#,operator.mod.
- hissp.macros._macro_.QHash_(numerator, denominator=None)#
Q#âRationalâ Exact fraction tag.Abbreviation for
fractions.Fraction, with ademungefor symbols.Mnemonic: âuotient.
#> Q#2/3 >>> # Fraction(2, 3) ... __import__('pickle').loads(b'cfractions\nFraction\n(V2/3\ntR.') Fraction(2, 3) #> Q#.2 ; Be careful converting binary float literals. >>> # Fraction(3602879701896397, 18014398509481984) ... __import__('pickle').loads(b'cfractions\nFraction\n(V3602879701896397/18014398509481984\ntR.') Fraction(3602879701896397, 18014398509481984) #> Q#|.2| ; Fragment, not a float literal. >>> # Fraction(1, 5) ... __import__('pickle').loads(b'cfractions\nFraction\n(V1/5\ntR.') Fraction(1, 5) #> Q##1 2 ; Note ##. >>> # Fraction(1, 2) ... __import__('pickle').loads(b'cfractions\nFraction\n(V1/2\ntR.') Fraction(1, 2) #> Q##Q#1/4 0b10 ; Other numbers.Rational types work. >>> # Fraction(1, 8) ... __import__('pickle').loads(b'cfractions\nFraction\n(V1/8\ntR.') Fraction(1, 8)
See also:
M#,numbers.Rational.
- hissp.macros._macro_.XHash_(expr)#
X#Anaphoric. Makeexpran anonymous function with parameter X.Examples:
Convert macro to function.
#> (list (map X#(@ X) "abc")) ; en#list would also work here. >>> list( ... map( ... (lambda X: ... # At_ ... (lambda *xs: [*xs])( ... X) ... ), ... ('abc'))) [['a'], ['b'], ['c']]
Compact function definition using Python operators.
#> (define teen? X#|13<=X<20|) >>> # define ... __import__('builtins').globals().update( ... teenEh_=(lambda X: 13<=X<20)) #> (teen? 12.5) >>> teenEh_( ... (12.5)) False #> (teen? 19.5) >>> teenEh_( ... (19.5)) True
Get an attribute without calling it.
#> (X#X.upper "shout") >>> (lambda X: X.upper)( ... ('shout')) <built-in method upper of str object at ...> #> (_) >>> _() 'SHOUT' #> (define class-name X#X.__class__.__name__) ; Attributes chain. >>> # define ... __import__('builtins').globals().update( ... class___name=(lambda X: X.__class__.__name__)) #> (class-name object) >>> class___name( ... object) 'type' #> (class-name "foo") >>> class___name( ... ('foo')) 'str'
- hissp.macros._macro_.XYHash_(expr)#
XY#Anaphoric. Makeexpran anonymous function with parameters X Y.#> (functools..reduce XY#(op#concat Y X) 'abcd) >>> __import__('functools').reduce( ... (lambda X, Y: ... __import__('operator').concat( ... Y, ... X) ... ), ... 'abcd') 'dcba'
- hissp.macros._macro_.XYZHash_(expr)#
XYZ#Anaphoric. Makeexpran anonymous function with parameters X Y Z.#> (XYZ#|X*Y == Z| : X math..pi Y 2 Z math..tau) >>> (lambda X, Y, Z: X*Y == Z)( ... X=__import__('math').pi, ... Y=(2), ... Z=__import__('math').tau) True
- hissp.macros._macro_.XYZWHash_(expr)#
XYZW#Anaphoric. Makeexpran anonymous function with parameters X Y Z W.#> (XYZW#|X[Y:Z:W]| "QuaoblcldefHg" -2 1 -2) >>> (lambda X, Y, Z, W: X[Y:Z:W])( ... ('QuaoblcldefHg'), ... (-2), ... (1), ... (-2)) 'Hello'
- hissp.macros._macro_.alias(abbreviation, qualifier)#
Defines a
tagabbreviation of aqualifier.#> (hissp..alias H hissp.) >>> # hissp..alias ... # hissp.macros.._macro_.defmacro ... __import__('builtins').setattr( ... __import__('builtins').globals().get( ... ('_macro_')), ... 'HHash_', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _g5W6NQPRW__lambda=(lambda attr, /, *args, **kwargs: ... __import__('hissp.macros',fromlist='*')._alias( ... (lambda : ... __import__('builtins').getattr( ... __import__('hissp')._macro_, ... f'{attr}Hash_') ... ), ... 'hissp.', ... attr, ... *args, ... **kwargs) ... ): ... (( ... *__import__('itertools').starmap( ... _g5W6NQPRW__lambda.__setattr__, ... __import__('builtins').dict( ... __doc__='Aliases ``hissp.`` as ``H#``.', ... __name__='HHash_', ... __qualname__='_macro_.HHash_', ... __code__=_g5W6NQPRW__lambda.__code__.replace( ... co_name='HHash_')).items()), ... ), ... _g5W6NQPRW__lambda) [-1] ... )()) #> 'H#munge ; One-arg form of new tag prepends qualifier. >>> 'hissp..munge' 'hissp..munge' #> (H#munge "*") ; Normal function call. >>> __import__('hissp').munge( ... ('*')) 'Star_' #> '.##H#munge|*| ; Read-time apply via .#, like a fully qualified tag. >>> 'Star_' 'Star_' #> (H#let-call ab (:* "AB") b) ; Macro form. Compiler checks _macro_. >>> # hissp..let___call ... (lambda a, b: b)( ... *('AB')) 'B' #> H#(% 'qualified (% 'not 'recursive) ; Qualifies qualifiable 'symbol keys. #.. 'foo..bar 'baz ; Already qualified. No effect. #.. operator..add "quoted symbols only" #.. '7 '8 ; quoting other things is OK. #.. (|| 'identity-form) "doesn't count") >>> # Pcent_ ... (lambda x0, x1, x2, x3, x4, x5, x6, x7, x8, x9: {x0:x1,x2:x3,x4:x5,x6:x7,x8:x9})( ... 'hissp..qualified', ... # Pcent_ ... (lambda x0, x1: {x0:x1})( ... 'not', ... 'recursive'), ... 'foo..bar', ... 'baz', ... __import__('operator').add, ... ('quoted symbols only'), ... (7), ... (8), ... ( ... 'identity___form'), ... ("doesn't count")) {'hissp..qualified': {'not': 'recursive'}, 'foo..bar': 'baz', <built-in function add>: 'quoted symbols only', 7: 8, 'identity___form': "doesn't count"} #> (H#b\#"a b# at compile time") ; Macro form. >>> # hissp..bHash_ ... b'a b# at compile time' b'a b# at compile time' #> hissp.._macro_.b#"Fully qualified b# at read time." ; \# implied. >>> b'Fully qualified b# at read time.' b'Fully qualified b# at read time.' #> H##b"Read-time b# via multiple-arg alias." ; _macro_ & \# implied. >>> b'Read-time b# via multiple-arg alias.' b'Read-time b# via multiple-arg alias.' #> H##@ tau=math. ; Kwargs also work. >>> # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'tau')( ... __import__('math')) 6.283185307179586
The bundled
op#andi#tags are aliases foroperatoranditertools, respectively.
- hissp.macros._macro_.ands(*exprs)#
Variadic shortcutting logical AND.
Returns the first false value, otherwise the last value. There is an implicit initial value of
True.#> (ands True True False) ; and finds the False >>> # ands ... (lambda x0, x1, x2: x0 and x1()and x2())( ... True, ... (lambda : True), ... (lambda : False)) False #> (ands False (print 'oops)) ; Shortcutting. >>> # ands ... (lambda x0, x1: x0 and x1())( ... False, ... (lambda : ... print( ... 'oops') ... )) False #> (ands True 42) >>> # ands ... (lambda x0, x1: x0 and x1())( ... True, ... (lambda : (42))) 42 #> (ands) >>> # ands ... True True #> (ands 42) >>> # ands ... (42) 42
See also:
ors,Boolean operations,all,when.
- hissp.macros._macro_.anyStar_map(params, xss, *body)#
any*mapâany star mapâ imperative iteratorforloop & unpack.Bind each
xto a variable and evaluate the body for eachxsfromxssuntil any result is true (and returnTrue), or untilxssis exhausted (and returnFalse).#> (any*map (i c : P print * op#mul) ; Extra locals (P and *) via default params. #.. (enumerate 'abc 1) ; As any-map, but with starmap. #.. (P (* i c))) >>> # anyStar_map ... __import__('builtins').any( ... __import__('itertools').starmap( ... ( ... lambda i, ... c, ... P=print, ... Star_=__import__('operator').mul: ... P( ... Star_( ... i, ... c)) ... ), ... enumerate( ... 'abc', ... (1)))) a bb ccc False
See also:
itertools.starmap,any-map,let-again,let*call,my#.
- hissp.macros._macro_.any___map(variable, xs, *body)#
any-mapimperative iteratorforloop.Bind the variable and evaluate the body for each
xfromxsuntil any result is true (and returnTrue), or untilxsis exhausted (and returnFalse).#> (any-map index (range 1 11) ;Imperative loop with break. #.. (print index : end :) #.. (not (op#mod index 7))) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda index: ... (print( ... index, ... end=':'), ... not( ... __import__('operator').mod( ... index, ... (7)))) [-1] ... ), ... range( ... (1), ... (11)))) 1:2:3:4:5:6:7:True
See also:
any,map,any*map,The for statement,The break statement,functools.reduce.
- hissp.macros._macro_.assure(expr, predicate, *args)#
Anaphoric. Raises
AssertionErrorunless(-> expr predicate).As
avow, but expansion is simplyexprwhen__debug__is off:$ python -Om hissp -c "(print (assure 0 bool))" 0 $ lissp -c "(print (assure 0 bool))" Hissp abort! Traceback (most recent call last): ... AssertionError
Note that for pre-compiled code, itâs the
__debug__state at compile time, not at run time, that determines if assure assertions are turned on.For internal integrity checks, prefer
avowtoassure, unless profiling indicates the check is unacceptably expensive in production, and the risk of not checking is acceptable; assume__debug__will later be turned off.Also useful at the top level for quick unit tests in smaller projects, because they can be turned off. Larger projects may be better off with
unittestand separated test modules, which need not be distributed and likely produce better error messages.#> (assure 7 (X#|X%2 == 0|) #.. it "That's odd.") >>> # assure ... # hissp.macros.._macro_.avow ... # hissp.macros.._macro_.let ... (lambda it=(7): ... (# hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... # hissp.macros.._macro_.Dash_Gt_ ... (lambda X: X%2 == 0)( ... it), ... (lambda : ... # hissp.macros.._macro_.throw ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... __import__('builtins').AssertionError( ... it, ... ("That's odd."))) ... )), ... it) [-1] ... )() Traceback (most recent call last): ... AssertionError: (7, "That's odd.")
See also:
The assert statement.
- hissp.macros._macro_.attach(target, *args)#
Attaches the named variables to the target as attributes.
Positional arguments must be identifiers. The identifier name becomes the attribute name. Names after the
:are identifier-value pairs. Returns the target.#> (attach (types..SimpleNamespace) _macro_.attach : a 1 b 'Hi) >>> # attach ... # hissp.macros.._macro_.let ... (lambda _g5UWMEC5Z__target=__import__('types').SimpleNamespace(): ... (__import__('builtins').setattr( ... _g5UWMEC5Z__target, ... 'attach', ... _macro_.attach), ... __import__('builtins').setattr( ... _g5UWMEC5Z__target, ... 'a', ... (1)), ... __import__('builtins').setattr( ... _g5UWMEC5Z__target, ... 'b', ... 'Hi'), ... _g5UWMEC5Z__target) [-1] ... )() namespace(attach=<function _macro_.attach at 0x...>, a=1, b='Hi')
- hissp.macros._macro_.avow(expr, predicate, *args)#
Anaphoric. Raises
AssertionErrorunless(-> expr predicate).Additional arguments are evaluated in a context where
itrefers to the result ofexpr. These (if any) are passed to theAssertionError. Evaluates to the result ofexpr.Assertions document assumptions that should never be false; only raise
AssertionErrors to fail fast when there is a bug in your code violating one, which can never happen if the code was written correctly. Though implemented as exceptions in Python, they should almost never be caught, except (perhaps) by a supervising system (such as aREPL) capable of dealing with broken subsystems. They are not to be used like normal exceptions to handle expected cases.#> (avow 7 (X#|X%2 == 0|) #.. it "That's odd.") >>> # avow ... # hissp.macros.._macro_.let ... (lambda it=(7): ... (# hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... # hissp.macros.._macro_.Dash_Gt_ ... (lambda X: X%2 == 0)( ... it), ... (lambda : ... # hissp.macros.._macro_.throw ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... __import__('builtins').AssertionError( ... it, ... ("That's odd."))) ... )), ... it) [-1] ... )() Traceback (most recent call last): ... AssertionError: (7, "That's odd.")
See also:
The assert statement,assure,throw.
- hissp.macros._macro_.bHash_(string)#
b#âbytestringâ bytes literal tagConverts a
Hissp stringtobytes.#> b#"bytes #..with\nnewlines" >>> b'bytes\nwith\nnewlines' b'bytes\nwith\nnewlines' #> b#'bytes! ; Note the '. Beware munging. >>> b'bytesBang_' b'bytesBang_' #> b#<# #..;; Bytes, #..;; newlines, \46 escapes! #.. >>> b'Bytes,\nnewlines, & escapes!' b'Bytes,\nnewlines, & escapes!'
See also:
B#,hissp.reader.is_hissp_string.
- hissp.macros._macro_.binding(pairs, *body)#
Runs body in a new
contextvars.Context, with additional bindings.#> (defvar *greeting*) >>> # defvar ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'Star_greetingStar_'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... Star_greetingStar_=__import__('contextvars').ContextVar( ... '*greeting*')) ... )) #> *greeting* >>> Star_greetingStar_ <ContextVar name='*greeting*' at 0x...> #> (defvar *greeted* "World!") >>> # defvar ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'Star_greetedStar_'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... Star_greetedStar_=__import__('contextvars').ContextVar( ... '*greeted*', ... default=('World!'))) ... )) #> *greeted* >>> Star_greetedStar_ <ContextVar name='*greeted*' default='World!' at 0x...> #> (defun greet : (print (.get *greeting* "Hello,") (.get *greeted*))) >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... greet=# hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gM7G4BACH__lambda=(lambda : ... print( ... Star_greetingStar_.get( ... ('Hello,')), ... Star_greetedStar_.get()) ... ): ... (( ... *__import__('itertools').starmap( ... _gM7G4BACH__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='greet', ... __qualname__='greet', ... __code__=_gM7G4BACH__lambda.__code__.replace( ... co_name='greet')).items()), ... ), ... _gM7G4BACH__lambda) [-1] ... )()) #> (greet) >>> greet() Hello, World! #> (binding (*greeting* "Goodbye," #.. *greeted* "all!") #.. (greet)) >>> # binding ... __import__('contextvars').copy_context().run( ... (lambda : ... (Star_greetingStar_.set( ... ('Goodbye,')), ... Star_greetedStar_.set( ... ('all!')), ... greet()) [-1] ... )) Goodbye, all! #> (greet) >>> greet() Hello, World!
See also:
defvar.
- hissp.macros._macro_.bnHash_(attr, /, *args, **kwargs)#
Aliases
builtins.asbn#.
- hissp.macros._macro_.case(key, default, *pairs)#
Switch case macro.
Precomputes a lookup table (dict), so must switch on a hashable key. Target keys are not evaluated, so donât quote them; they must be known at compile time.
The default case is first and required. The remainder are implicitly paired by position.
#> (any-map x '(1 2 spam |42| :eggs) #.. (case x (print "default") #.. (0 2 |42|) (print "even") #.. (1 3 spam) (print "odd"))) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda x: ... # case ... ( ... (lambda : ... print( ... ('odd')) ... ), ... (lambda : ... print( ... ('even')) ... ), ... (lambda : ... print( ... ('default')) ... ), ... ).__getitem__( ... {1: 0, 3: 0, 'spam': 0, 0: 1, 2: 1, '42': 1}.get( ... x, ... (-1)))() ... ), ... ((1), ... (2), ... 'spam', ... '42', ... ':eggs',))) odd even odd even default False
See also:
cond.
- hissp.macros._macro_.chainHash_(xss)#
chain#Abbreviation foritertools.chain.from_iterable.
- hissp.macros._macro_.colHash_(attr, /, *args, **kwargs)#
Aliases
collections.ascol#.
- hissp.macros._macro_.cond(*pairs)#
Multiple condition branching.
Pairs are implied by position. Default is
(). Use something always truthy to change it, like:elseorTrue. For example:#> (any-map x (@ -0.6 -0.0 42.0 math..nan) #.. (cond (op#lt x 0) (print :Negative) ;if-else cascade #.. (op#eq x 0) (print :Zero) #.. (op#gt x 0) (print :Positive) #.. :else (print :Not-a-Number))) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda x: ... # cond ... (lambda x0, x1, x2, x3, x4, x5, x6, x7: ... x1() if x0 ... else x3() if x2() ... else x5() if x4() ... else x7() if x6() ... else () ... )( ... __import__('operator').lt( ... x, ... (0)), ... (lambda : ... print( ... ':Negative') ... ), ... (lambda : ... __import__('operator').eq( ... x, ... (0)) ... ), ... (lambda : ... print( ... ':Zero') ... ), ... (lambda : ... __import__('operator').gt( ... x, ... (0)) ... ), ... (lambda : ... print( ... ':Positive') ... ), ... (lambda : ':else'), ... (lambda : ... print( ... ':Not-a-Number') ... )) ... ), ... # At_ ... (lambda *xs: [*xs])( ... (-0.6), ... (-0.0), ... (42.0), ... __import__('math').nan))) :Negative :Zero :Positive :Not-a-Number False
See also:
if-else,case,any-map,The if statement.
- hissp.macros._macro_.cxlHash_(attr, /, *args, **kwargs)#
Aliases
contextlib.ascxl#.
- hissp.macros._macro_.cxvHash_(attr, /, *args, **kwargs)#
Aliases
contextvars.ascxv#.
- hissp.macros._macro_.define(qualname, value)#
Assigns an attribute the value.
The qualname may be a
fully qualified identifieror start from a name in scope. Assigns an attribute of the current module (a global) if thereâs noqualifier.#> (define SPAM 'tomato) >>> # define ... __import__('builtins').globals().update( ... SPAM='tomato') #> SPAM >>> SPAM 'tomato'
See also:
globals,dict.update,setattr,defonce,Assignment statements,The global statement.
- hissp.macros._macro_.defmacro(name, parameters, *body)#
Creates a new
macro functionfor the current module.If thereâs no local
_macro_namespace (at compile time), adds code to create one if itâs still not there. 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.#> (defmacro p123 (sep) #.. <#;Prints 1 2 3 with the given separator #.. `(print 1 2 3 : sep ,sep)) >>> # defmacro ... __import__('builtins').setattr( ... __import__('builtins').globals().get( ... ('_macro_')), ... 'p123', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gNKUV4WZP__lambda=(lambda sep: ... ( ... 'builtins..print', ... (1), ... (2), ... (3), ... ':', ... '__main__..sep', ... sep, ... ) ... ): ... (( ... *__import__('itertools').starmap( ... _gNKUV4WZP__lambda.__setattr__, ... __import__('builtins').dict( ... __doc__='Prints 1 2 3 with the given separator', ... __name__='p123', ... __qualname__='_macro_.p123', ... __code__=_gNKUV4WZP__lambda.__code__.replace( ... co_name='p123')).items()), ... ), ... _gNKUV4WZP__lambda) [-1] ... )()) #> (p123 ::) >>> # p123 ... __import__('builtins').print( ... (1), ... (2), ... (3), ... sep='::') 1::2::3
- hissp.macros._macro_.defonce(qualname, value)#
Defines an attribute, unless it exists.
Like
define, but wonât overwrite an existing attribute. Useful when sending the whole file to theREPLrepeatedly or when usingimportlib.reload.#> (defonce CACHE (types..SimpleNamespace : x 1)) >>> # defonce ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'CACHE'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... CACHE=__import__('types').SimpleNamespace( ... x=(1))) ... )) #> (setattr CACHE 'x 42) >>> setattr( ... CACHE, ... 'x', ... (42)) #> (defonce CACHE (progn (print 'not 'evaluated) #.. (types..SimpleNamespace : x 1))) >>> # defonce ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'CACHE'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... CACHE=# progn ... (print( ... 'not', ... 'evaluated'), ... __import__('types').SimpleNamespace( ... x=(1))) [-1]) ... )) () #> CACHE ; The second defonce had no effect. >>> CACHE namespace(x=42)
See also:
deftypeonce,hissp.refresh.
- hissp.macros._macro_.deftupleonce(typename, *args)#
Defines a
collections.namedtupleunless it exists.#> (deftupleonce Vec3D '(x y z) : defaults '(0 0 0)) >>> # deftupleonce ... # hissp.macros.._macro_.defonce ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'Vec3D'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... Vec3D=__import__('collections').namedtuple( ... 'Vec3D', ... ('x', ... 'y', ... 'z',), ... defaults=((0), ... (0), ... (0),))) ... ))
Like
deftypeonce, methods can be attached afterward. On reload, the existing class is modified, affecting all of its instances, including those created before the reload.#> (define offset (Vec3D : z 1 x 2)) >>> # define ... __import__('builtins').globals().update( ... offset=Vec3D( ... z=(1), ... x=(2))) #> (defun Vec3D.__add__ (self other) #.. (._make Vec3D (map op#add self other))) >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').setattr( ... Vec3D, ... '__add__', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gB5WXG6ZL__lambda=(lambda self, other: ... Vec3D._make( ... map( ... __import__('operator').add, ... self, ... other)) ... ): ... (( ... *__import__('itertools').starmap( ... _gB5WXG6ZL__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='__add__', ... __qualname__='Vec3D.__add__', ... __code__=_gB5WXG6ZL__lambda.__code__.replace( ... co_name='__add__')).items()), ... ), ... _gB5WXG6ZL__lambda) [-1] ... )()) #> (op#add offset offset) >>> __import__('operator').add( ... offset, ... offset) Vec3D(x=4, y=0, z=2) #> (op#add _ (Vec3D 10 20 30)) >>> __import__('operator').add( ... _, ... Vec3D( ... (10), ... (20), ... (30))) Vec3D(x=14, y=20, z=32)
- hissp.macros._macro_.deftypeonce(qualname, bases=(), *once_decorators)#
Defines a
type(class), unless it exists.Add class attributes afterward using
defineordefun, and class decorators above with@##or afterward usingzap@. These run again on module reload, updating the existing class object, which can affect the behavior its instances defined before the reload.The
once_decoratorsapply before any external ones, in the order written (first applies first), unless the type exists (not reapplied on reloads). Beware that type attributes defined afterward will not be available for theonce_decoratorsto operate upon. A decorator can add attributes for subsequent decorators to operate upon, however, and a decorator may be a lambda defined in line. It is possible to add arbitrary attributes this way, but remember thatonce_decoratorsdonât run again on reloads, so changes here cannot simply be reloaded with the module the way attributes defined afterward can.#> (deftypeonce Point2D (tuple) #.. ;; Example of setting an attr with an internal decorator. #.. X#(attach X : __doc__ "Simple ordered pair.")) >>> # deftypeonce ... # hissp.macros.._macro_.defonce ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'Point2D'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... Point2D=(lambda X: ... # attach ... # hissp.macros.._macro_.let ... (lambda _gC6Z2ODBH__target=X: ... (__import__('builtins').setattr( ... _gC6Z2ODBH__target, ... '__doc__', ... ('Simple ordered pair.')), ... _gC6Z2ODBH__target) [-1] ... )() ... )( ... __import__('builtins').type( ... 'Point2D', ... ( ... tuple, ... ), ... {}))) ... )) #> Point2D.__doc__ >>> Point2D.__doc__ 'Simple ordered pair.' #> (define Point2D.__doc__ #.. "Attributes can also be defined afterwards.") >>> # define ... __import__('builtins').setattr( ... Point2D, ... '__doc__', ... ('Attributes can also be defined afterwards.')) #> Point2D.__doc__ >>> Point2D.__doc__ 'Attributes can also be defined afterwards.' #> (defun Point2D.__new__ (cls x y) #.. (.__new__ tuple cls `(,x ,y))) FULL COMPILATION: >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').setattr( ... Point2D, ... '__new__', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gHDCRUAXN__lambda=(lambda cls, x, y: ... tuple.__new__( ... cls, ... ( ... x, ... y, ... )) ... ): ... (( ... *__import__('itertools').starmap( ... _gHDCRUAXN__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='__new__', ... __qualname__='Point2D.__new__', ... __code__=_gHDCRUAXN__lambda.__code__.replace( ... co_name='__new__')).items()), ... ), ... _gHDCRUAXN__lambda) [-1] ... )()) #> (defun Point2D.__repr__ (self) #.. (.format "Point2D({!r}, {!r})" : :* self)) >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').setattr( ... Point2D, ... '__repr__', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gRCWY23WM__lambda=(lambda self: ... ('Point2D({!r}, {!r})').format( ... *self) ... ): ... (( ... *__import__('itertools').starmap( ... _gRCWY23WM__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='__repr__', ... __qualname__='Point2D.__repr__', ... __code__=_gRCWY23WM__lambda.__code__.replace( ... co_name='__repr__')).items()), ... ), ... _gRCWY23WM__lambda) [-1] ... )()) #> (Point2D 1 2) >>> Point2D( ... (1), ... (2)) Point2D(1, 2)
Also supports keyword arguments in the bases tuple for
object.__init_subclass__. Separate with a:.#> @##classmethod #..(defun Point2D.__init_subclass__ (cls :/ : :** kwargs) #.. "Just displays inputs" #.. (print kwargs)) >>> # hissp.macros.._macro_.define ... __import__('builtins').setattr( ... Point2D, ... '__init_subclass__', ... # hissp.macros.._macro_.progn ... (# defun ... # hissp.macros.._macro_.define ... __import__('builtins').setattr( ... Point2D, ... '__init_subclass__', ... # hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gXEVGDNH2__lambda=(lambda cls, /, **kwargs: ... print( ... kwargs) ... ): ... (( ... *__import__('itertools').starmap( ... _gXEVGDNH2__lambda.__setattr__, ... __import__('builtins').dict( ... __doc__=('Just displays inputs'), ... __name__='__init_subclass__', ... __qualname__='Point2D.__init_subclass__', ... __code__=_gXEVGDNH2__lambda.__code__.replace( ... co_name='__init_subclass__')).items()), ... ), ... _gXEVGDNH2__lambda) [-1] ... )()), ... classmethod( ... Point2D.__init_subclass__)) [-1]) #> (deftypeonce ASubclass (Point2D : a 1 b 2)) >>> # deftypeonce ... # hissp.macros.._macro_.defonce ... # hissp.macros.._macro_.unless ... (lambda b, a: ()if b else a())( ... __import__('operator').contains( ... __import__('builtins').globals(), ... 'ASubclass'), ... (lambda : ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... ASubclass=__import__('builtins').type( ... 'ASubclass', ... ( ... Point2D, ... ), ... {}, ... a=(1), ... b=(2))) ... )) {'a': 1, 'b': 2}
See also:
attach,types.new_class,defonce.
- hissp.macros._macro_.defun(qualname, params, *body)#
defineafunwith the same name.See
deftypeoncefor how to define methods.See also:
Function definitions,define,defmacro,@##.
- hissp.macros._macro_.defvar(name, default=<object object>)#
Creates a
contextvars.ContextVar, unless it exists.The default is optional, but cannot be altered once set, however, a new binding may be set for a
contextvars.Context.Intended for use at the top level only, because Python currently has no way of deleting a
ContextVaronce it has been added to the currentContext. (Although aContextVarcould be deleted from the globals and replaced with a new one with the same name and a different default value, the oldContextVarwill also be in theContext.)See
bindingfor usage examples.See also:
defonce.
- hissp.macros._macro_.destruct___Gt_(data, bindings, *body)#
destruct->âdestruct arrowâ Destructuring bindings.Bindings are pairs of a transform expression with either a name or (recursively) another bindings expression. Each transformation expression is applied to the data via a thread-first (
->). This setup allows a bindings form to mirror the data itâs destructuring:#> (% 10 1 'ns (types..SimpleNamespace : a-tuple '(a b c) spam 'eggs)) >>> # Pcent_ ... (lambda x0, x1, x2, x3: {x0:x1,x2:x3})( ... (10), ... (1), ... 'ns', ... __import__('types').SimpleNamespace( ... a___tuple=('a', ... 'b', ... 'c',), ... spam='eggs')) {10: 1, 'ns': namespace(a___tuple=('a', 'b', 'c'), spam='eggs')} #> (define nested-data _) >>> # define ... __import__('builtins').globals().update( ... nested___data=_) #> (destruct-> nested-data #.. (!#10 num !#'ns (@#'a-tuple (!#0 a !#1 b !#2 c) @#'spam spam)) #.. (locals)) >>> # destruct___Gt_ ... # hissp.macros.._macro_.let___call ... (lambda num, a, b, c, spam: locals())( ... *# hissp.macros.._macro_.let ... (lambda _g275ZTQAC__data=nested___data: ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (10))( ... _g275ZTQAC__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _g275ZTQAC__data=# hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... 'ns')( ... _g275ZTQAC__data): ... ( ... *# hissp.macros.._macro_.let ... ( ... lambda _g275ZTQAC__data=# hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'a___tuple')( ... _g275ZTQAC__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))( ... _g275ZTQAC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (1))( ... _g275ZTQAC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (2))( ... _g275ZTQAC__data), ... ) ... )(), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'spam')( ... _g275ZTQAC__data), ... ) ... )(), ... ) ... )()) {'num': 1, 'a': 'a', 'b': 'b', 'c': 'c', 'spam': 'eggs'}
But it doesnât have to. Transforms need not be simple lookups:
#> (destruct-> nested-data #.. (!#'ns (|| ns ; Identity transform. ->, progn, doto, etc. also work. #.. (getattr 'missing "a default for missing") missing #.. @#'spam inner ; attribute lookup #.. @#'a-tuple ([#:-1] ab [#:] abc ; slices with overlaps #.. iter (next A list rest) ; iterator destructuring #.. ;; Composed transform, method calls, defaults. #.. (-> enumerate dict) ((.get 2 ()) two #.. (.get 3 ()) three) #.. ;; Throwaway names must be unique. (`,$#_ always works). #.. iter (next _0 (next :b) B next _1 (next :d) D))) #.. (.get 'quux "default for quux") myquux) #.. (pprint..pp (locals))) >>> # destruct___Gt_ ... # hissp.macros.._macro_.let___call ... (lambda ns, missing, inner, ab, abc, A, rest, two, three, _0, B, _1, D, myquux: ... __import__('pprint').pp( ... locals()) ... )( ... *# hissp.macros.._macro_.let ... (lambda _gU3TLRBXC__data=nested___data: ... ( ... *# hissp.macros.._macro_.let ... ( ... lambda _gU3TLRBXC__data=# hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... 'ns')( ... _gU3TLRBXC__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... ( ... _gU3TLRBXC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... getattr( ... _gU3TLRBXC__data, ... 'missing', ... ('a default for missing')), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'spam')( ... _gU3TLRBXC__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _gU3TLRBXC__data=# hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').attrgetter( ... 'a___tuple')( ... _gU3TLRBXC__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... (lambda _gX4M4GEV6__table: (_gX4M4GEV6__table[:-1]))( ... _gU3TLRBXC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... (lambda _gX4M4GEV6__table: (_gX4M4GEV6__table[:]))( ... _gU3TLRBXC__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _gU3TLRBXC__data=# hissp.macros.._macro_.Dash_Gt_ ... iter( ... _gU3TLRBXC__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... next( ... _gU3TLRBXC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... list( ... _gU3TLRBXC__data), ... ) ... )(), ... *# hissp.macros.._macro_.let ... ( ... lambda _gU3TLRBXC__data=# hissp.macros.._macro_.Dash_Gt_ ... # Dash_Gt_ ... dict( ... enumerate( ... _gU3TLRBXC__data)): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... _gU3TLRBXC__data.get( ... (2), ... ()), ... # hissp.macros.._macro_.Dash_Gt_ ... _gU3TLRBXC__data.get( ... (3), ... ()), ... ) ... )(), ... *# hissp.macros.._macro_.let ... ( ... lambda _gU3TLRBXC__data=# hissp.macros.._macro_.Dash_Gt_ ... iter( ... _gU3TLRBXC__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... next( ... _gU3TLRBXC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... next( ... _gU3TLRBXC__data, ... ':b'), ... # hissp.macros.._macro_.Dash_Gt_ ... next( ... _gU3TLRBXC__data), ... # hissp.macros.._macro_.Dash_Gt_ ... next( ... _gU3TLRBXC__data, ... ':d'), ... ) ... )(), ... ) ... )(), ... ) ... )(), ... # hissp.macros.._macro_.Dash_Gt_ ... _gU3TLRBXC__data.get( ... 'quux', ... ('default for quux')), ... ) ... )()) {'ns': namespace(a___tuple=('a', 'b', 'c'), spam='eggs'), 'missing': 'a default for missing', 'inner': 'eggs', 'ab': ('a', 'b'), 'abc': ('a', 'b', 'c'), 'A': 'a', 'rest': ['b', 'c'], 'two': 'c', 'three': (), '_0': 'a', 'B': 'b', '_1': 'c', 'D': ':d', 'myquux': 'default for quux'}
- 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. Returnsself.#> (doto (list) #.. (.extend 'bar) #.. .sort #.. (.append 'foo)) >>> # doto ... (lambda _gBBU6XSAT__self=list(): ... (_gBBU6XSAT__self.extend( ... 'bar'), ... _gBBU6XSAT__self.sort(), ... _gBBU6XSAT__self.append( ... 'foo'), ... _gBBU6XSAT__self) [-1] ... )() ['a', 'b', 'r', 'foo']
- hissp.macros._macro_.dtHash_(attr, /, *args, **kwargs)#
Aliases
datetime.asdt#.
- hissp.macros._macro_.enHash_(f)#
en#tag. Wrap a function applicable to a tuple as a function of its elements.#> (en#list 1 2 3) >>> (lambda *_g4TYWBSNP__xs: ... list( ... _g4TYWBSNP__xs) ... )( ... (1), ... (2), ... (3)) [1, 2, 3] #> (en#.extend _ 4 5 6) ; Methods too. #.. >>> (lambda _gB3AJD2PD__self, *_gB3AJD2PD__xs: ... _gB3AJD2PD__self.extend( ... _gB3AJD2PD__xs) ... )( ... _, ... (4), ... (5), ... (6)) #> _ >>> _ [1, 2, 3, 4, 5, 6] #> (define enjoin en#X#(.join "" (map str X))) >>> # define ... __import__('builtins').globals().update( ... enjoin=(lambda *_gEEXENIDY__xs: ... (lambda X: ... ('').join( ... map( ... str, ... X)) ... )( ... _gEEXENIDY__xs) ... )) #> (enjoin "Sum: "(op#add 2 3)". Product: "(op#mul 2 3)".") >>> enjoin( ... ('Sum: '), ... __import__('operator').add( ... (2), ... (3)), ... ('. Product: '), ... __import__('operator').mul( ... (2), ... (3)), ... ('.')) 'Sum: 5. Product: 6.'
There are no bundled tags for a quinary, senary, etc. but the
en#X#variadic or a normal lambda form can be used instead.
- hissp.macros._macro_.fiHash_(attr, /, *args, **kwargs)#
Aliases
fileinput.asfi#.
- hissp.macros._macro_.ftHash_(attr, /, *args, **kwargs)#
Aliases
functools.asft#.
- hissp.macros._macro_.fun(qualname, params, maybe___docstring=(), *body)#
A lambda enhanced with a
qualified nameand optionally a docstring.Hisspâs (and Pythonâs) lambda syntax do not have docstrings. Named lambdas improve
REPLtransparency and error messages, at the cost of some configuration overhead to set the name in the three places Python requires.Used by
defmacroanddefun. Not recommended for otherwise anonymous functions due to the additional overhead.
- hissp.macros._macro_.hshHash_(attr, /, *args, **kwargs)#
Aliases
hashlib.ashsh#.
- hissp.macros._macro_.iHash_(attr, /, *args, **kwargs)#
Aliases
itertools.asi#.
- hissp.macros._macro_.if___else(test, consequent, alternate)#
if-elseBasic ternary branching construct.Like Pythonâs conditional expressions, the âelseâ clause is required.
#> (any-map c 'ab #.. (if-else (op#eq c 'b) ;ternary conditional #.. (print 'Yes) #.. (print 'No))) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda c: ... # if___else ... (lambda b, c, a: c()if b else a())( ... __import__('operator').eq( ... c, ... 'b'), ... (lambda : ... print( ... 'Yes') ... ), ... (lambda : ... print( ... 'No') ... )) ... ), ... 'ab')) No Yes False
See also:
when,cond,any-map,Conditional expressions.
- hissp.macros._macro_.impHash_(attr, /, *args, **kwargs)#
Aliases
importlib.asimp#.
- hissp.macros._macro_.impStop_rHash_(attr, /, *args, **kwargs)#
Aliases
importlib.resources.asimp.r#.
- hissp.macros._macro_.instHash_(date_string)#
inst#instant tag.Abbreviation for
datetime.datetime.fromisoformat, with ademungefor symbols.#> inst#2024-10-07T11:30:07+00:00 >>> # datetime.datetime(2024, 10, 7, 11, 30, 7, tzinfo=datetime.timezone.utc) ... __import__('pickle').loads(b'cdatetime\ndatetime\n(c_codecs\nencode\n(V\x07\xe8\\u000a\x07\x0b\x1e\x07\\u0000\\u0000\\u0000\nVlatin1\ntRcdatetime\ntimezone\n(cdatetime\ntimedelta\n(I0\nI0\nI0\ntRtRtR.') datetime.datetime(2024, 10, 7, 11, 30, 7, tzinfo=datetime.timezone.utc)
See also:
uuid#.
- hissp.macros._macro_.let(pairs, *body)#
Creates local variables. Pairs are implied by position.
Created locals are not in scope until the body.
#> (let (x 'a ;Create locals. #.. y 'b) ;Any number of pairs. #.. (print x y) #.. (let (x 'x #.. y (op#concat x x)) ;Not in scope until body. #.. (print x y)) ;Outer variables shadowed. #.. (print x y)) ;Inner went out of scope. >>> # let ... ( ... lambda x='a', ... y='b': ... (print( ... x, ... y), ... # let ... ( ... lambda x='x', ... y=__import__('operator').concat( ... x, ... x): ... print( ... x, ... y) ... )(), ... print( ... x, ... y)) [-1] ... )() a b x aa a b
- hissp.macros._macro_.letStar_call(pairs, *body)#
let*callâlet star callâ Nestedlet-call.Can unpack nested data by using multiple stages.
#> (let*call ((abcs) (:? 'abcdef) ; whole thing #.. (a b : :* cs) (:* abcs) ; rest (tuple packing) #.. (: d () e () f ()) (:* 'de) ; defaults #.. (g h i) (:* 'ghi) ; positional unpacking #.. (: :** jkls) (j 'J k 'K l 'L) ; kwargs (dict packing) #.. (j k l : m None n '|N?|) (:** jkls)) ; dict unpacking with defaults #.. (print a b cs abcs d e f g h i j k l m n jkls)) >>> # letStar_call ... # hissp.macros.._macro_.let___call ... (lambda abcs: ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.let___call ... (lambda a, b, *cs: ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.let___call ... ( ... lambda d=(), ... e=(), ... f=(): ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.let___call ... (lambda g, h, i: ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.let___call ... (lambda **jkls: ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.let___call ... ( ... lambda j, ... k, ... l, ... m=None, ... n='N?': ... # hissp.macros..letStar_call ... # hissp.macros.._macro_.progn ... print( ... a, ... b, ... cs, ... abcs, ... d, ... e, ... f, ... g, ... h, ... i, ... j, ... k, ... l, ... m, ... n, ... jkls) ... )( ... **jkls) ... )( ... j='J', ... k='K', ... l='L') ... )( ... *'ghi') ... )( ... *'de') ... )( ... *abcs) ... )( ... 'abcdef') a b ('c', 'd', 'e', 'f') abcdef d e () g h i J K L None N? {'j': 'J', 'k': 'K', 'l': 'L'}
See also:
my#,destruct->.
- hissp.macros._macro_.let___again(pairs, *body)#
let-againLoop/recur with trampoline.Creates a stack to schedule future loops. Call the
again-withanaphor with an iterable of values for the locals to push another loop to the schedule.(again-with None)will abort any remaining schedule.Returns the value of the final loop.
#> (let-again (x 3 y 0) #.. (when x (again-with (|| |x-1| |y+1|))) #.. (print x y)) >>> # let___again ... # hissp.macros.._macro_.let ... (lambda _gY44MBROP__stack=[None, None, ()]: ... # hissp.macros.._macro_.let ... (lambda again___with=_gY44MBROP__stack.append: ... (# hissp.macros.._macro_.anyStar_map ... __import__('builtins').any( ... __import__('itertools').starmap( ... ( ... lambda x=(3), ... y=(0): ... (_gY44MBROP__stack.__setitem__( ... (0), ... # hissp.macros.._macro_.progn ... (# when ... (lambda b, c: c()if b else())( ... x, ... (lambda : ... again___with( ... ( ... x-1, ... y+1)) ... )), ... print( ... x, ... y)) [-1]), ... None) [-1] ... ), ... __import__('builtins').iter( ... _gY44MBROP__stack.pop, ... None))), ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))( ... _gY44MBROP__stack)) [-1] ... )() ... )() 3 0 2 1 1 2 0 3
See also:
any*map, Ensue,The while statement.
- hissp.macros._macro_.let___call(params, pairs, *body)#
let-callCreate parameters from call arg pairs.#> (let-call (a b : :* cs g :? h 'H) (:* 'ABCD :? 'EF g 'G) #.. (print cs b a g h)) >>> # let___call ... ( ... lambda a, ... b, ... *cs, ... g, ... h='H': ... print( ... cs, ... b, ... a, ... g, ... h) ... )( ... *'ABCD', ... 'EF', ... g='G') ('C', 'D', 'EF') B A G H
See also:
let,let*call,Assignment statements.
- hissp.macros._macro_.mix(*args)#
Injection. Compiles each arg to Python and concatenates the fragments.
Lissp features like munging and fully qualified identifiers can be freely mixed with Python expressions like slicing, infix operators and list comprehensions by using
fragment tokens:#> (mix |[|%|+|(.lower %)| for |%| in |string..ascii_uppercase|[:10]]|) >>> # mix ... [Pcent_+Pcent_.lower() for Pcent_ in __import__('string').ascii_uppercase[:10]] ['Aa', 'Bb', 'Cc', 'Dd', 'Ee', 'Ff', 'Gg', 'Hh', 'Ii', 'Jj']
Beware that a
str atomlike|:|is still acontrol word, and like|foo.|is still amodule handle, even when made with afragment token. However, Python allows whitespace in many areas where it is not conventional to do so, making fragments like| :|or|foo .|viable workarounds in such cases.
- hissp.macros._macro_.mkHash_(attr, /, *args, **kwargs)#
Aliases
unittest.mock.asmk#.
- hissp.macros._macro_.mpHash_(attr, /, *args, **kwargs)#
Aliases
multiprocessing.asmp#.
- hissp.macros._macro_.mpStop_smHash_(attr, /, *args, **kwargs)#
Aliases
multiprocessing.shared_memory.asmp.sm#.
- hissp.macros._macro_.myHash_(targets_or_scope, expr=None, scope=(), **kwargs)#
my#Anaphoric. Injection.letmybe a freshtypes.SimpleNamespacein a lexical scope.Creates a local namespace for imperative-style (re)assignments.
Kwarg tokens in scope translate toset@.Often combined with branching macros to reuse the results of an expression, with uses similar to Pythonâs âwalrusâ operator
:=. Seepython-grammar:assignment_expression.#> my#(print x=(op#add 1 1) my.x) >>> # hissp.macros.._macro_.let ... (lambda my=__import__('types').SimpleNamespace(): ... print( ... # hissp.macros.._macro_.setAt_ ... # hissp.macros.._macro_.let ... ( ... lambda _gUJATU5TX__value=__import__('operator').add( ... (1), ... (1)): ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... my, ... 'x', ... _gUJATU5TX__value), ... _gUJATU5TX__value) [-1] ... )(), ... my.x) ... )() 2 2 #> my#my ; Empty namespace shorthand. >>> # hissp.macros.._macro_.let ... (lambda my=__import__('types').SimpleNamespace(): my)() namespace() #> my##foo=2 my ; Initial content from read-time kwarg. >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... foo=(2)): ... my)() namespace(foo=2) #> my##outer=2 my###inner=1 bridge=my (@ my.bridge.outer my.inner) >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... outer=(2)): ... # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... inner=(1), ... bridge=my): ... # At_ ... (lambda *xs: [*xs])( ... my.bridge.outer, ... my.inner) ... )() ... )() [2, 1]
With at least two positional arguments, the first is an injected Python assignment target, and the second its value:
#> my### a,b,[c,*xs] '(1 2 |spam|) my ; Nested unpacking. >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... **# hissp.macros.._macro_.let ... ( ... lambda _gEZHZ5K77__expr=((1), ... (2), ... 'spam',): ... [__import__('builtins').locals() ... for (a,b,[c,*xs]) ... in [_gEZHZ5K77__expr]] [0] ... )()): ... (my.__dict__.pop( ... '_gEZHZ5K77__expr', ... None), ... my.__dict__.pop( ... ('.0'), ... None), ... my) [-1] ... )() namespace(a=1, b=2, c='s', xs=['p', 'a', 'm'])
Use
zap@for augmented assignments:#> my###a,b 'AB (@ (zap@ my.a iadd c='C) my) >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... **# hissp.macros.._macro_.let ... (lambda _gH2ASYXGG__expr='AB': ... [__import__('builtins').locals() ... for (a,b) ... in [_gH2ASYXGG__expr]] [0] ... )()): ... (my.__dict__.pop( ... '_gH2ASYXGG__expr', ... None), ... my.__dict__.pop( ... ('.0'), ... None), ... # At_ ... (lambda *xs: [*xs])( ... # zapAt_ ... # hissp.macros.._macro_.setAt_ ... # hissp.macros.._macro_.let ... ( ... lambda _gE2CNKVL4__value=iadd( ... my.a, ... # hissp.macros.._macro_.setAt_ ... # hissp.macros.._macro_.let ... (lambda _gE2CNKVL4__value='C': ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... my, ... 'c', ... _gE2CNKVL4__value), ... _gE2CNKVL4__value) [-1] ... )()): ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... my, ... 'a', ... _gE2CNKVL4__value), ... _gE2CNKVL4__value) [-1] ... )(), ... my)) [-1] ... )() ['AC', namespace(a='AC', b='B', c='C')]
Assignment targets need not be locals, so a scope argument is optional:
#> my## |globals()['spam'], spam.eggs| (|| my#my (list 'abcdefg) ||) >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... **# hissp.macros.._macro_.let ... ( ... lambda _g2MBLMLUY__expr=( ... # hissp.macros.._macro_.let ... (lambda my=__import__('types').SimpleNamespace(): my)(), ... list( ... 'abcdefg'), ... ): ... [__import__('builtins').locals() ... for (globals()['spam'], spam.eggs) ... in [_g2MBLMLUY__expr]] [0] ... )()): ... (my.__dict__.pop( ... '_g2MBLMLUY__expr', ... None), ... my.__dict__.pop( ... ('.0'), ... None), ... ()) [-1] ... )() () #> my#### spam.eggs[2::2] 'XYZ tomato=spam my ; Assign a global's slice. >>> # hissp.macros.._macro_.let ... ( ... lambda my=__import__('types').SimpleNamespace( ... **# hissp.macros.._macro_.let ... (lambda _gMMP53OIO__expr='XYZ': ... [__import__('builtins').locals() ... for (spam.eggs[2::2]) ... in [_gMMP53OIO__expr]] [0] ... )(), ... tomato=spam): ... (my.__dict__.pop( ... '_gMMP53OIO__expr', ... None), ... my.__dict__.pop( ... ('.0'), ... None), ... my) [-1] ... )() namespace(tomato=namespace(eggs=['a', 'b', 'X', 'd', 'Y', 'f', 'Z']))
See also:
attach,set[###,destruct->.
- hissp.macros._macro_.nilHash_(x)#
nil#evaluates asx or (). Adapter for ânil punningâ.
- hissp.macros._macro_.nspHash_(attr, /, *args, **kwargs)#
Aliases
inspect.asnsp#.
- hissp.macros._macro_.opHash_(attr, /, *args, **kwargs)#
Aliases
operator.asop#.
- hissp.macros._macro_.ors(*exprs)#
Variadic shortcutting logical OR.
Returns the first true value, otherwise the last value. There is an implicit initial value of
().#> (ors True (print 'oops)) ; Shortcutting. >>> # ors ... (lambda x0, x1: x0 or x1())( ... True, ... (lambda : ... print( ... 'oops') ... )) True #> (ors 42 False) >>> # ors ... (lambda x0, x1: x0 or x1())( ... (42), ... (lambda : False)) 42 #> (ors () False 0 1) ; or seeks the truth >>> # ors ... (lambda x0, x1, x2, x3: x0 or x1()or x2()or x3())( ... (), ... (lambda : False), ... (lambda : (0)), ... (lambda : (1))) 1 #> (ors False) >>> # ors ... False False #> (ors) >>> # ors ... () ()
See also:
ands,bool,Boolean operations,any.
- hissp.macros._macro_.plHash_(attr, /, *args, **kwargs)#
Aliases
pathlib.aspl#.
- hissp.macros._macro_.posHash_(bindings)#
pos#âposition bindingsâdestruct->helper shorthand. Destructures a sequence using each binding formâs position index.#> (destruct-> '(ABC XYZ) #.. (|| whole || pos#(abc pos#(x y))) #.. (print whole abc x y)) >>> # destruct___Gt_ ... # hissp.macros.._macro_.let___call ... (lambda whole, abc, x, y: ... print( ... whole, ... abc, ... x, ... y) ... )( ... *# hissp.macros.._macro_.let ... ( ... lambda _gFS4QYTZL__data=('ABC', ... 'XYZ',): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... ( ... _gFS4QYTZL__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _gFS4QYTZL__data=# hissp.macros.._macro_.Dash_Gt_ ... ( ... _gFS4QYTZL__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))( ... _gFS4QYTZL__data), ... *# hissp.macros.._macro_.let ... ( ... lambda _gFS4QYTZL__data=# hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (1))( ... _gFS4QYTZL__data): ... ( ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (0))( ... _gFS4QYTZL__data), ... # hissp.macros.._macro_.Dash_Gt_ ... # hissp.macros.._macro_._backapply ... __import__('operator').itemgetter( ... (1))( ... _gFS4QYTZL__data), ... ) ... )(), ... ) ... )(), ... ) ... )()) ('ABC', 'XYZ') ABC X Y
- hissp.macros._macro_.prelude(env=('builtins..globals',))#
Hisspâs bundled micro prelude.
Brings Hissp up to a minimal standard of usability without adding any dependencies in the compiled output.
Mainly intended for single-file scripts that canât have dependencies, or similarly constrained environments (e.g., embedded,
readerless mode). There, the first form should be(hissp..prelude), which is also implied in$ lissp -ccommands.Larger projects with access to functional and macro libraries need not use this prelude at all.
The prelude has several effects:
Defines
engarde, which calls a function with exception handler:def engarde(xs,h,f,/,*a,**kw): try:return f(*a,**kw) except xs as e:return h(e)
engardewith handlers can stack above in a single tuple.See engarde examples below.
Defines
enter, which calls a function with context manager:def enter(c,f,/,*a): with c as C:return f(*a,C)
enterwith context managers can stack above in a single tuple.See enter examples below.
Defines the
Ensueclass; trampolined continuation generators:class Ensue(__import__('collections.abc').abc.Generator): send=lambda s,v:s.g.send(v);throw=lambda s,*x:s.g.throw(*x);F=0;X=();Y=[] def __init__(s,p):s.p,s.g,s.n=p,s._(s),s.Y def _(s,k,v=None): while isinstance(s:=k,__class__) and not setattr(s,'sent',v): try:k,y=s.p(s),s.Y;v=(yield from y)if s.F or y is s.n else(yield y) except s.X as e:v=e return k
Ensuetakes a step function and returns a generator. The step function receives the previous Ensue step and must return the next one to continue. Returning a different type raises aStopIterationwith that object. Set theYattribute on the current step to [Y]ield a value this step. Set theFattribute to a true value to yield values [F]rom theYiterable instead. Set theXattribute to an e[X]ception class or tuple to catch any targeted exceptions on the next step. Each step keeps asentattribute, which is the value sent to the generator this step, or the exception caught this step instead.See Ensue examples and enter examples below.
See also:
types.coroutine,collections.abc.Generator,let-again.Adds the bundled macros, but only if available (macros are typically only used at compile time), so its compiled expansion does not require Hissp to be installed. (This replaces
_macro_if you already had one.):class _macro_(*engarde(ModuleNotFoundError,lambda _:'', lambda:[__import__('hissp')._macro_])):0
Prelude Usage#
The
REPLhas the bundled macros loaded by default, but not the prelude. Invoke(prelude)to get the rest.#> (prelude) >>> # prelude ... __import__('builtins').exec( ... ('from itertools import *;from operator import *\n' ... 'def engarde(xs,h,f,/,*a,**kw):\n' ... ' try:return f(*a,**kw)\n' ... ' except xs as e:return h(e)\n' ... 'def enter(c,f,/,*a):\n' ... ' with c as C:return f(*a,C)\n' ... "class Ensue(__import__('collections.abc').abc.Generator):\n" ... ' send=lambda s,v:s.g.send(v);throw=lambda s,*x:s.g.throw(*x);F=0;X=();Y=[]\n' ... ' def __init__(s,p):s.p,s.g,s.n=p,s._(s),s.Y\n' ... ' def _(s,k,v=None):\n' ... " while isinstance(s:=k,__class__) and not setattr(s,'sent',v):\n" ... ' try:k,y=s.p(s),s.Y;v=(yield from y)if s.F or y is s.n else(yield y)\n' ... ' except s.X as e:v=e\n' ... ' return k\n' ... "class _macro_(*engarde(ModuleNotFoundError,lambda _:'',\n" ... "lambda:[__import__('hissp')._macro_])):0\n"), ... __import__('builtins').globals())
See also,
alias.engarde examples#
#> (engarde `(,FloatingPointError ,ZeroDivisionError) ;two targets #.. (lambda e (print "Oops!") e) ;handler (returns exception) #.. truediv 6 0) ;calls it on your behalf >>> engarde( ... ( ... FloatingPointError, ... ZeroDivisionError, ... ), ... (lambda e: ... (print( ... ('Oops!')), ... e) [-1] ... ), ... truediv, ... (6), ... (0)) Oops! ZeroDivisionError('division by zero') #> (engarde ArithmeticError repr truediv 6 0) ;superclass target >>> engarde( ... ArithmeticError, ... repr, ... truediv, ... (6), ... (0)) "ZeroDivisionError('division by zero')" #> (engarde ArithmeticError repr truediv 6 2) ;returned answer >>> engarde( ... ArithmeticError, ... repr, ... truediv, ... (6), ... (2)) 3.0 #> (engarde Exception ;The stacked outer engarde #.. print #.. engarde ZeroDivisionError ; calls the inner. #.. (lambda e (print "It means what you want it to mean.")) #.. truediv "6" 0) ;Try variations. >>> engarde( ... Exception, ... print, ... engarde, ... ZeroDivisionError, ... (lambda e: ... print( ... ('It means what you want it to mean.')) ... ), ... truediv, ... ('6'), ... (0)) unsupported operand type(s) for /: 'str' and 'int' #> (engarde Exception #.. (lambda x x.__cause__) #.. (lambda : (throw-from Exception (Exception "msg")))) >>> engarde( ... Exception, ... (lambda x: x.__cause__), ... (lambda : ... # throw___from ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... # hissp.macros.._macro_.let ... ( ... lambda _g6Q6NJSTQ__G=(lambda _g6Q6NJSTQ__x: ... # hissp.macros.._macro_.if___else ... (lambda b, c, a: c()if b else a())( ... __import__('builtins').isinstance( ... _g6Q6NJSTQ__x, ... __import__('builtins').BaseException), ... (lambda : _g6Q6NJSTQ__x), ... (lambda : _g6Q6NJSTQ__x())) ... ): ... # hissp.macros.._macro_.attach ... # hissp.macros.._macro_.let ... ( ... lambda _gPQUNU63T__target=_g6Q6NJSTQ__G( ... Exception): ... (__import__('builtins').setattr( ... _gPQUNU63T__target, ... '__cause__', ... _g6Q6NJSTQ__G( ... Exception( ... ('msg')))), ... _gPQUNU63T__target) [-1] ... )() ... )()) ... )) Exception('msg')
Ensue examples#
#> (.update (globals) #.. : fibonacci #.. (lambda (: a 1 b 1) #.. (Ensue (lambda (step) #.. (setattr step 'Y a) ;Y for yield. #.. (fibonacci b (add a b)))))) >>> globals().update( ... fibonacci=( ... lambda a=(1), ... b=(1): ... Ensue( ... (lambda step: ... (setattr( ... step, ... 'Y', ... a), ... fibonacci( ... b, ... add( ... a, ... b))) [-1] ... )) ... )) #> (list (islice (fibonacci) 7)) >>> list( ... islice( ... fibonacci(), ... (7))) [1, 1, 2, 3, 5, 8, 13] #> (.update (globals) ; Terminate by not returning an Ensue. #.. : my-range #.. (lambda in #.. (Ensue (lambda (step) #.. (when (lt i n) ;Acts like a while loop. #.. (setattr step 'Y i) #.. (my-range (add i 1) n)))))) ;Conditional recursion. #.. >>> globals().update( ... my___range=(lambda i, n: ... Ensue( ... (lambda step: ... # when ... (lambda b, c: c()if b else())( ... lt( ... i, ... n), ... (lambda : ... (setattr( ... step, ... 'Y', ... i), ... my___range( ... add( ... i, ... (1)), ... n)) [-1] ... )) ... )) ... )) #> (list (my-range 1 6)) >>> list( ... my___range( ... (1), ... (6))) [1, 2, 3, 4, 5] #> (Ensue (lambda (step) #.. (attach step : #.. F True ; Set F for yield-From mode. #.. Y '(1 2 3 4 5)) #.. None)) >>> Ensue( ... (lambda step: ... (# attach ... # hissp.macros.._macro_.let ... (lambda _gG4YAHWYA__target=step: ... (__import__('builtins').setattr( ... _gG4YAHWYA__target, ... 'F', ... True), ... __import__('builtins').setattr( ... _gG4YAHWYA__target, ... 'Y', ... ((1), ... (2), ... (3), ... (4), ... (5),)), ... _gG4YAHWYA__target) [-1] ... )(), ... None) [-1] ... )) <...Ensue object at ...> #> (list _) >>> list( ... _) [1, 2, 3, 4, 5] #> (define recycle #.. (lambda (itr) #.. (Ensue (lambda (step) #.. ;; Implicit continuation; step is an Ensue. #.. (attach step : Y itr F 1))))) >>> # define ... __import__('builtins').globals().update( ... recycle=(lambda itr: ... Ensue( ... (lambda step: ... # attach ... # hissp.macros.._macro_.let ... (lambda _gGB6P3557__target=step: ... (__import__('builtins').setattr( ... _gGB6P3557__target, ... 'Y', ... itr), ... __import__('builtins').setattr( ... _gGB6P3557__target, ... 'F', ... (1)), ... _gGB6P3557__target) [-1] ... )() ... )) ... )) #> (-> '(1 2 3) recycle (islice 7) list) >>> # Dash_Gt_ ... list( ... islice( ... recycle( ... ((1), ... (2), ... (3),)), ... (7))) [1, 2, 3, 1, 2, 3, 1] #> (.update (globals) #.. : echo #.. (Ensue (lambda (step) #.. (setattr step 'Y step.sent) #.. step))) >>> globals().update( ... echo=Ensue( ... (lambda step: ... (setattr( ... step, ... 'Y', ... step.sent), ... step) [-1] ... ))) #> (.send echo None) ; Always send a None first. Same as Python. >>> echo.send( ... None) #> (.send echo "Yodel!") ; Generators are two-way. >>> echo.send( ... ('Yodel!')) 'Yodel!' #> (.send echo 42) >>> echo.send( ... (42)) 42
enter examples#
#> @##cxl#contextmanager #..(defun wrap (msg) #.. (print "enter" msg) #.. (Ensue (lambda (step) #.. (setattr step 'Y msg) #.. (Ensue (lambda (step) #.. (print "exit" msg)))))) >>> # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... wrap=# hissp.macros.._macro_.progn ... (# defun ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... wrap=# hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gGVVLJLUM__lambda=(lambda msg: ... (print( ... ('enter'), ... msg), ... Ensue( ... (lambda step: ... (setattr( ... step, ... 'Y', ... msg), ... Ensue( ... (lambda step: ... print( ... ('exit'), ... msg) ... ))) [-1] ... ))) [-1] ... ): ... (( ... *__import__('itertools').starmap( ... _gGVVLJLUM__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='wrap', ... __qualname__='wrap', ... __code__=_gGVVLJLUM__lambda.__code__.replace( ... co_name='wrap')).items()), ... ), ... _gGVVLJLUM__lambda) [-1] ... )()), ... __import__('contextlib').contextmanager( ... wrap)) [-1]) #> (enter (wrap 'A) #.. (lambda a (print a))) >>> enter( ... wrap( ... 'A'), ... (lambda a: ... print( ... a) ... )) enter A A exit A #> (enter (wrap 'A) #.. enter (wrap 'B) #.. enter (wrap 'C) ; You can stack them. #.. (lambda abc (print a b c))) >>> enter( ... wrap( ... 'A'), ... enter, ... wrap( ... 'B'), ... enter, ... wrap( ... 'C'), ... (lambda a, b, c: ... print( ... a, ... b, ... c) ... )) enter A enter B enter C A B C exit C exit B exit A #> (define suppress-zde #.. (cxl#contextmanager #.. (lambda : #.. (Ensue (lambda (step) #.. (attach step : #.. Y None #.. X ZeroDivisionError) ; X for eXcept (can be a tuple). #.. (Ensue (lambda (step) #.. (print "Caught a" step.sent)))))))) >>> # define ... __import__('builtins').globals().update( ... suppress___zde=__import__('contextlib').contextmanager( ... (lambda : ... Ensue( ... (lambda step: ... (# attach ... # hissp.macros.._macro_.let ... (lambda _gWXSTHSTC__target=step: ... (__import__('builtins').setattr( ... _gWXSTHSTC__target, ... 'Y', ... None), ... __import__('builtins').setattr( ... _gWXSTHSTC__target, ... 'X', ... ZeroDivisionError), ... _gWXSTHSTC__target) [-1] ... )(), ... Ensue( ... (lambda step: ... print( ... ('Caught a'), ... step.sent) ... ))) [-1] ... )) ... ))) #> (enter (suppress-zde) #.. (lambda _ (truediv 1 0))) >>> enter( ... suppress___zde(), ... (lambda _: ... truediv( ... (1), ... (0)) ... )) Caught a division by zero #> (enter (suppress-zde) ; No exception, so step.sent was .send() value. #.. (lambda _ (truediv 4 2))) >>> enter( ... suppress___zde(), ... (lambda _: ... truediv( ... (4), ... (2)) ... )) Caught a None 2.0 #> (enter (suppress-zde) #.. (lambda _ (throw Exception))) >>> enter( ... suppress___zde(), ... (lambda _: ... # throw ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... Exception) ... )) Traceback (most recent call last): ... Exception
- hissp.macros._macro_.prog1(expr1, *body)#
Evaluates sequentially (for side effects). Returns value of
expr1.#> (print (prog1 0 ;Side effects in sequence. Eval to first. #.. (print 1) #.. (print 2))) >>> print( ... # prog1 ... # hissp.macros.._macro_.let ... (lambda _gP2FSZYVE__value1=(0): ... (print( ... (1)), ... print( ... (2)), ... _gP2FSZYVE__value1) [-1] ... )()) 1 2 0
Combine with
prognfor a value in the middle of the sequence:#> (prog1 ;Side effects in sequence. Eval to first. #.. (progn (print 1) ;Side effects in sequence. Eval to last. #.. 3) #.. (print 2)) >>> # prog1 ... # hissp.macros.._macro_.let ... ( ... lambda _gKTCZ2AQB__value1=# progn ... (print( ... (1)), ... (3)) [-1]: ... (print( ... (2)), ... _gKTCZ2AQB__value1) [-1] ... )() 1 2 3
See also:
doto.
- hissp.macros._macro_.progn(*body)#
Evaluates each body expression in sequence (for side effects), resulting in the value of the last (or
()if empty).#> (print (progn (print 1) ;Sequence for side effects, eval to last. #.. (print 2) #.. 3)) >>> print( ... # progn ... (print( ... (1)), ... print( ... (2)), ... (3)) [-1]) 1 2 3
See also:
prog1,Expression statements.
- hissp.macros._macro_.proxyHash_(f)#
proxy#wrapper to make a stored callable reloadable.For this to work, it should be applied to a lookup expression such as a global variable name or module attribute. This will be written into the wrapper body.
#> (defun greet () #.. (print "Hello, World!")) >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... greet=# hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gROR2V2G5__lambda=(lambda : ... print( ... ('Hello, World!')) ... ): ... (( ... *__import__('itertools').starmap( ... _gROR2V2G5__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='greet', ... __qualname__='greet', ... __code__=_gROR2V2G5__lambda.__code__.replace( ... co_name='greet')).items()), ... ), ... _gROR2V2G5__lambda) [-1] ... )()) #> proxy#greet >>> __import__('functools').update_wrapper( ... (lambda *_g3XJMPIBW__args, **_g3XJMPIBW__kwargs: ... greet( ... *_g3XJMPIBW__args, ... **_g3XJMPIBW__kwargs) ... ), ... greet) <function greet at 0x...> #> (define greet-handlers (types..SimpleNamespace : direct greet proxied _)) >>> # define ... __import__('builtins').globals().update( ... greet___handlers=__import__('types').SimpleNamespace( ... direct=greet, ... proxied=_))
Now suppose
greetis reloaded with a new definition, butgreet-handlersis not (perhaps due to being in separate modules or ifgreet-handlershad useddefonce):#> (defun greet () #.. (print "Wassup?")) >>> # defun ... # hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... greet=# hissp.macros.._macro_.fun ... # hissp.macros.._macro_.let ... ( ... lambda _gPAWCWJOD__lambda=(lambda : ... print( ... ('Wassup?')) ... ): ... (( ... *__import__('itertools').starmap( ... _gPAWCWJOD__lambda.__setattr__, ... __import__('builtins').dict( ... __name__='greet', ... __qualname__='greet', ... __code__=_gPAWCWJOD__lambda.__code__.replace( ... co_name='greet')).items()), ... ), ... _gPAWCWJOD__lambda) [-1] ... )()) #> (greet-handlers.direct) ; Still the original function object. >>> greet___handlers.direct() Hello, World! #> (greet-handlers.proxied) ; Proxy does the lookup again. >>> greet___handlers.proxied() Wassup?
- hissp.macros._macro_.sentinelHash_(f)#
sentinel#Anaphoric.Let
_sentinelbe a unique sentinel object in a lexical scope surroundingf.
- hissp.macros._macro_.setAt_(qualname, value)#
set@âsetatâ Assigns an attribute, returns the value.The namespace part of the
qualnamemay be fully qualified or start from a name in scope. An empty namespace part sets an attribute of the current module (a global).Mnemonic: set @tribute.
#> (set@ eggs (set@ spam (types..SimpleNamespace))) ; define can't do this. >>> # setAt_ ... # hissp.macros.._macro_.let ... ( ... lambda _gYZ2LLOWW__value=# setAt_ ... # hissp.macros.._macro_.let ... (lambda _gYZ2LLOWW__value=__import__('types').SimpleNamespace(): ... (# hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... spam=_gYZ2LLOWW__value), ... _gYZ2LLOWW__value) [-1] ... )(): ... (# hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... eggs=_gYZ2LLOWW__value), ... _gYZ2LLOWW__value) [-1] ... )() namespace() #> (set@ spam.foo (types..SimpleNamespace)) >>> # setAt_ ... # hissp.macros.._macro_.let ... (lambda _gOJ7YYIRC__value=__import__('types').SimpleNamespace(): ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... spam, ... 'foo', ... _gOJ7YYIRC__value), ... _gOJ7YYIRC__value) [-1] ... )() namespace() #> (set@ spam.foo.bar 4) >>> # setAt_ ... # hissp.macros.._macro_.let ... (lambda _g4MKUDCHX__value=(4): ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... spam.foo, ... 'bar', ... _g4MKUDCHX__value), ... _g4MKUDCHX__value) [-1] ... )() 4 #> spam >>> spam namespace(foo=namespace(bar=4))
- hissp.macros._macro_.setBang_(table, key, value)#
set!âsetbangâ Assigns an item, returns the value.Mnemonic: set !tem.
#> (define spam (dict)) >>> # define ... __import__('builtins').globals().update( ... spam=dict()) #> (set! spam 1 (set! spam 2 10)) ; setitem can't do this. #.. >>> # setBang_ ... # hissp.macros.._macro_.let ... ( ... lambda _gOR6DYBDV__value=# setBang_ ... # hissp.macros.._macro_.let ... (lambda _gOR6DYBDV__value=(10): ... (__import__('operator').setitem( ... spam, ... (2), ... _gOR6DYBDV__value), ... _gOR6DYBDV__value) [-1] ... )(): ... (__import__('operator').setitem( ... spam, ... (1), ... _gOR6DYBDV__value), ... _gOR6DYBDV__value) [-1] ... )() 10 #> spam >>> spam {2: 10, 1: 10}
See also:
operator.setitem,operator.delitem,zap!.
- hissp.macros._macro_.setLsqb_Hash_(lookup, table_or_value, *value)#
set[###âsetsubâ Injection. Subscription with assignment.Returns the value assigned (not the collection updated).
#> (define spam (list "0000")) >>> # define ... __import__('builtins').globals().update( ... spam=list( ... ('0000'))) #> set[###-1] spam set[###::2] spam "ab" ; Chained assignment. >>> # hissp.macros.._macro_._backapply ... ( ... lambda _g3TTXFOWE__table, ... _g3TTXFOWE__value=# hissp.macros.._macro_._backapply ... ( ... lambda _g3TTXFOWE__table, ... _g3TTXFOWE__value=('ab'): ... [_g3TTXFOWE__value ... for(_g3TTXFOWE__table[::2])in[_g3TTXFOWE__value]][0] ... )( ... spam): ... [_g3TTXFOWE__value ... for(_g3TTXFOWE__table[-1])in[_g3TTXFOWE__value]][0] ... )( ... spam) 'ab' #> spam >>> spam ['a', '0', 'b', 'ab']
set[##form returns a partial setter function which takes a table:#> (doto (dict) set[##1] 2) >>> # doto ... (lambda _gOFBSTZ6J__self=dict(): ... (# hissp.macros.._macro_._backapply ... ( ... lambda _gZEOID6JH__table, ... _gZEOID6JH__value=(2): ... [_gZEOID6JH__value ... for(_gZEOID6JH__table[1])in[_gZEOID6JH__value]][0] ... )( ... _gOFBSTZ6J__self), ... _gOFBSTZ6J__self) [-1] ... )() {1: 2}
- hissp.macros._macro_.spHash_(attr, /, *args, **kwargs)#
Aliases
subprocess.assp#.
- hissp.macros._macro_.spyHash_(expr, file='sys..stderr')#
spy#Printexpr=>its value, to the file. Return the value.Typically used to debug a Lissp expression.
#> (op#add 5 spy##file=sys..stdout(op#mul 7 3)) >>> __import__('operator').add( ... (5), ... # hissp.._macro_._spy ... # hissp.macros.._macro_.let ... ( ... lambda _gJTVHKNI3__e=__import__('operator').mul( ... (7), ... (3)): ... (__import__('builtins').print( ... __import__('pprint').pformat( ... ('operator..mul', ... (7), ... (3),), ... sort_dicts=(0)), ... ('=>'), ... __import__('builtins').repr( ... _gJTVHKNI3__e), ... file=__import__('sys').stdout), ... _gJTVHKNI3__e) [-1] ... )()) ('operator..mul', 7, 3) => 21 26
- hissp.macros._macro_.tbHash_(attr, /, *args, **kwargs)#
Aliases
traceback.astb#.
- hissp.macros._macro_.tfHash_(attr, /, *args, **kwargs)#
Aliases
tempfile.astf#.
- hissp.macros._macro_.thrHash_(attr, /, *args, **kwargs)#
Aliases
threading.asthr#.
- hissp.macros._macro_.throw(exception)#
Raise an exception.
#> (throw Exception) ;Raise exception objects or classes. >>> # throw ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... Exception) Traceback (most recent call last): ... Exception #> (throw (TypeError 'message)) >>> # throw ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... TypeError( ... 'message')) Traceback (most recent call last): ... TypeError: message
See also:
throw-from, engarde,The raise statement.
- hissp.macros._macro_.throwStar_(*exception)#
throw*âthrow starâ Creates a closed generator and calls.throw.Despite PEP 3109,
.throwstill seems to accept multiple arguments. Avoid using this form except when implementing throw method overrides. Preferthrowinstead.The 3-arg form is deprecated as of Python 3.12.
- hissp.macros._macro_.throw___from(exception, cause)#
throw-fromRaise an exception with a cause, which can be None.If
exceptionis not an instance ofBaseException, it will be presumed an exception class and called with no arguments before attaching the cause to the resulting instance.#> (throw-from Exception (Exception 'message)) ; Explicit chaining. #.. >>> # throw___from ... # hissp.macros.._macro_.throwStar_ ... (lambda g:g.close()or g.throw)(c for c in'')( ... # hissp.macros.._macro_.let ... ( ... lambda _gP46TIEQT__G=(lambda _gP46TIEQT__x: ... # hissp.macros.._macro_.if___else ... (lambda b, c, a: c()if b else a())( ... __import__('builtins').isinstance( ... _gP46TIEQT__x, ... __import__('builtins').BaseException), ... (lambda : _gP46TIEQT__x), ... (lambda : _gP46TIEQT__x())) ... ): ... # hissp.macros.._macro_.attach ... # hissp.macros.._macro_.let ... ( ... lambda _gXPD76NRZ__target=_gP46TIEQT__G( ... Exception): ... (__import__('builtins').setattr( ... _gXPD76NRZ__target, ... '__cause__', ... _gP46TIEQT__G( ... Exception( ... 'message'))), ... _gXPD76NRZ__target) [-1] ... )() ... )()) Traceback (most recent call last): ... Exception
- hissp.macros._macro_.timeHash_(expr, file='sys..stderr')#
time#Print ms elapsed runningexprto the file. Return its value.Typically used when optimizing a Lissp expression.
#> time##file=sys..stdout(time..sleep .05) >>> # hissp.macros.._macro_.let ... (lambda _g72AOZNBR__time=__import__('time').time_ns: ... # hissp.macros.._macro_.let ... ( ... lambda _g72AOZNBR__start=_g72AOZNBR__time(), ... _g72AOZNBR__val=__import__('time').sleep( ... (0.05)), ... _g72AOZNBR__end=_g72AOZNBR__time(): ... (__import__('builtins').print( ... ('time# ran'), ... __import__('pprint').pformat( ... ('time..sleep', ... (0.05),), ... sort_dicts=(0)), ... ('in'), ... __import__('operator').truediv( ... __import__('operator').sub( ... _g72AOZNBR__end, ... _g72AOZNBR__start), ... # Decimal('1E+6') ... __import__('pickle').loads(b'cdecimal\nDecimal\n(V1E+6\ntR.')), ... ('ms'), ... file=__import__('sys').stdout), ... _g72AOZNBR__val) [-1] ... )() ... )() time# ran ('time..sleep', 0.05) in ... ms
See also:
timeit.
- hissp.macros._macro_.twHash_(attr, /, *args, **kwargs)#
Aliases
textwrap.astw#.
- 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
().#> (any-map c 'abcd #.. (unless (op#eq c 'b) #.. (print c))) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda c: ... # unless ... (lambda b, a: ()if b else a())( ... __import__('operator').eq( ... c, ... 'b'), ... (lambda : ... print( ... c) ... )) ... ), ... 'abcd')) a c d False
See also:
when.
- hissp.macros._macro_.utHash_(attr, /, *args, **kwargs)#
Aliases
unittest.asut#.
- hissp.macros._macro_.uuidHash_(hex)#
uuid#Universally Unique Identifier tag.Abbreviation for
uuid.UUID, with ademungefor symbols. Curly braces, hyphens, and a URN prefix are optional, but the argument must be a read-timestr, not anint.#> uuid#{urn:uuid:12345678-1234-5678-1234-567812345678} >>> # UUID('12345678-1234-5678-1234-567812345678') ... __import__('pickle').loads(b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nNtR(dVint\nL24197857161011715162171839636988778104L\nsb.') UUID('12345678-1234-5678-1234-567812345678')
See also:
inst#.
- 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
().#> (any-map c 'abcd #.. (print c) #.. (when (op#eq c 'b) #.. (print 'found) #.. :break)) >>> # any___map ... __import__('builtins').any( ... __import__('builtins').map( ... (lambda c: ... (print( ... c), ... # when ... (lambda b, c: c()if b else())( ... __import__('operator').eq( ... c, ... 'b'), ... (lambda : ... (print( ... 'found'), ... ':break') [-1] ... ))) [-1] ... ), ... 'abcd')) a b found True
See also:
if-else,unless,The if statement.
- hissp.macros._macro_.wrnHash_(attr, /, *args, **kwargs)#
Aliases
warnings.aswrn#.
- hissp.macros._macro_.zapAt_(qualname, f, *args)#
zap@âzapatâ Augmented attribute assignment operator.The current attribute value becomes the first argument. Returns the value assigned (not the collection updated).
Mnemonic: zap @tribute.
#> (define spam (types..SimpleNamespace : foo 10)) >>> # define ... __import__('builtins').globals().update( ... spam=__import__('types').SimpleNamespace( ... foo=(10))) #> (zap@ spam.foo operator..iadd 1) >>> # zapAt_ ... # hissp.macros.._macro_.setAt_ ... # hissp.macros.._macro_.let ... ( ... lambda _gOESTXDRX__value=__import__('operator').iadd( ... spam.foo, ... (1)): ... (# hissp.macros.._macro_.define ... __import__('builtins').setattr( ... spam, ... 'foo', ... _gOESTXDRX__value), ... _gOESTXDRX__value) [-1] ... )() 11 #> spam >>> spam namespace(foo=11) #> (zap@ spam getattr 'foo) >>> # zapAt_ ... # hissp.macros.._macro_.setAt_ ... # hissp.macros.._macro_.let ... ( ... lambda _gFLL6SH2F__value=getattr( ... __import__('builtins').globals().__getitem__( ... 'spam'), ... 'foo'): ... (# hissp.macros.._macro_.define ... __import__('builtins').globals().update( ... spam=_gFLL6SH2F__value), ... _gFLL6SH2F__value) [-1] ... )() 11 #> spam >>> spam 11
See also:
set@,zap!,operator.iadd,Augmented assignment statements,@##.
- hissp.macros._macro_.zapBang_(table, key, f, *args)#
zap!âzapbangâ Augmented item assignment operator.The current item value becomes the first argument. Returns the value assigned (not the collection updated).
Mnemonic: zap !tem.
#> (define spam (dict : b 10)) >>> # define ... __import__('builtins').globals().update( ... spam=dict( ... b=(10))) #> (zap! spam 'b op#iadd 1) ; Augmented item assignment, like +=. #.. >>> # zapBang_ ... # hissp.macros.._macro_.let ... ( ... lambda _gITEIW3OF__table=spam, ... _gITEIW3OF__key='b': ... # hissp.macros.._macro_.setBang_ ... # hissp.macros.._macro_.let ... ( ... lambda _gI2PHTEDN__value=__import__('operator').iadd( ... _gITEIW3OF__table.__getitem__( ... _gITEIW3OF__key), ... (1)): ... (__import__('operator').setitem( ... _gITEIW3OF__table, ... _gITEIW3OF__key, ... _gI2PHTEDN__value), ... _gI2PHTEDN__value) [-1] ... )() ... )() 11 #> spam >>> spam {'b': 11}
See also:
set!,zap@,Augmented assignment statements.
- hissp.macros._macro_.zapLsqb_Hash_(lookup, table_or_call, *call)#
zap[###âzapsubâ Injection. Augmented subscription assignment.The current item value becomes the first argument. Returns the value assigned (not the collection updated).
#> (define spam (list "abcd")) >>> # define ... __import__('builtins').globals().update( ... spam=list( ... ('abcd'))) #> zap[###:2] spam (op#iadd "XY") ; spam[:2]+="XY", but an expression >>> # hissp.macros.._macro_._backapply ... (lambda _gQGBD7VBT__table: ... # hissp.macros.._macro_.let ... ( ... lambda _gQGBD7VBT__value=# hissp.macros..Dash_Gt_ ... __import__('operator').iadd( ... (_gQGBD7VBT__table[:2]), ... ('XY')): ... [_gQGBD7VBT__value ... for(_gQGBD7VBT__table[:2])in[_gQGBD7VBT__value]][0] ... )() ... )( ... spam) ['a', 'b', 'X', 'Y'] #> spam >>> spam ['a', 'b', 'X', 'Y', 'c', 'd']
zap[##returns a partial function taking a table:#> (doto |[2]| zap[##0] (op#iadd 1)) >>> # doto ... (lambda _gDK7SIMRN__self=[2]: ... (# hissp.macros.._macro_._backapply ... (lambda _gC45JENYH__table: ... # hissp.macros.._macro_.let ... ( ... lambda _gC45JENYH__value=# hissp.macros..Dash_Gt_ ... __import__('operator').iadd( ... (_gC45JENYH__table[0]), ... (1)): ... [_gC45JENYH__value ... for(_gC45JENYH__table[0])in[_gC45JENYH__value]][0] ... )() ... )( ... _gDK7SIMRN__self), ... _gDK7SIMRN__self) [-1] ... )() [3]