Version 0.14.2.1
0.14.2.1 just fixes that I forgot the include the final release date for 0.14.2 in CHANGELOG.md
. Real release below.
0.14.2 7 August 2020 - "Greenspun" edition:
With the arrival of conditions and restarts, and a REPL server, I think it is now fair to say unpythonic
contains an ad-hoc, informally-specified, slow implementation of half of Common Lisp. To avoid bug-ridden, we have tests - but it's not entirely impossible for some to have slipped through. If you find one, please file an issue in the tracker.
This release welcomes the first external contribution! Thanks to @aisha-w for the much improved organization and presentation of the documentation!
Language version:
We target Python 3.6. Now we test on both CPython and PyPy3.
Rumors of the demise of Python 3.4 support are exaggerated. While the testing of unpythonic
has moved to 3.6, there neither is nor will there be any active effort to intentionally drop 3.4 support until unpythonic
reaches 0.15.0.
That is, support for 3.4 will likely be dropped with the arrival of the next batch of breaking changes. The current plan is visible in the roadmap as the 0.15.0 milestone.
If you're still stuck on 3.4 and find something in the latest unpythonic
0.14.x doesn't work there, please file an issue. (Support for 0.14.x will end once 0.15 is released, but not before.)
New:
- Improve organization and presentation of documentation (#28).
- Macro README: Emacs syntax highlighting for
unpythonic.syntax
and MacroPy. - Resumable exceptions, a.k.a. conditions and restarts. One of the famous killer features of Common Lisp. Drawing inspiration from python-cl-conditions by Alexander Artemenko. See
with restarts
(Common Lisp equivalent:RESTART-CASE
),with handlers
(HANDLER-BIND
),signal
(SIGNAL
),invoke
(INVOKE-RESTART
). Many convenience forms are also exported; seeunpythonic.conditions
for a full list. For an introduction to conditions, see Chapter 19 in Practical Common Lisp by Peter Seibel. - REPL server and client. Interactively hot-patch your running Python program! Another of the famous killer features of Common Lisp. The server is daemonic, listening for connections in a background thread. (Don't worry, it's strictly opt-in.) See
unpythonic.net.server
andunpythonic.net.client
. - Batteries for network programming:
unpythonic.net.msg
: A simplistic message protocol for sending message data over a stream-based transport (such as TCP).unpythonic.net.ptyproxy
: Proxy between a Linux PTY and a network socket. Useful for serving terminal utilities over the network. This doesn't usepty.spawn
, so Python libraries that expect to run in a terminal are also welcome. Seeunpythonic.net.server
for a usage example.unpythonic.net.util
: Miscellaneous small utilities.
fix
: Break infinite recursion cycles (for pure functions). Drawing inspiration from original implementations by Matthew Might and Per Vognsen.- More batteries for itertools:
fixpoint
: Arithmetic fixed-point finder (not to be confused withfix
).within
: Yield items from iterable until successive iterates are close enough (useful with Cauchy sequences).chunked
: Split an iterable into constant-length chunks.lastn
: Yield the lastn
items from an iterable.pad
: Extend iterable to lengthn
with afillvalue
.interleave
: For example,interleave(['a', 'b', 'c'], ['+', '*']) --> ['a', '+', 'b', '*', 'c']
. Interleave items from several iterables, slightly differently fromzip
.find
: From an iterable, get the first item matching a given predicate. Convenience function.powerset
: Compute the power set (set of all subsets) of an iterable. Works also for infinite iterables.CountingIterator
: Count how many items have been yielded, as a side effect.slurp
: Extract all items from aqueue.Queue
(until it is empty) into a list, returning that list.map
: Curry-friendly thin wrapper for the builtinmap
, making it mandatory to specify at least one iterable.running_minmax
,minmax
: Extract both min and max in one pass over an iterable. Therunning_
variant is a scan and returns a generator; the just-give-me-the-final-result variant is a fold.
ulp
: Given a floatx
, return the value of the unit in the last place (the "least significant bit"). Atx = 1.0
, this is the machine epsilon, by definition of the machine epsilon.partition_int
: split a small positive integer, in all possible ways, into smaller integers that sum to it.dyn
now supports rebinding, using the assignment syntaxdyn.x = 42
. To mass-update atomically, seedyn.update
.box
now supports.set(newvalue)
to rebind (returns the new value as a convenience), andunbox(b)
to extract contents. Syntactic sugar for rebinding isb << newvalue
(whereb
is a box).ThreadLocalBox
: A box with thread-local contents. It also holds a default object, which is used when a particular thread has not placed any object into the box.Some
: An immutable box. Useful for optional fields; tell apart the presence of aNone
value (Some(None)
) from the absence of a value (None
).Shim
: A shim holds abox
or aThreadLocalBox
, and redirects attribute accesses to whatever object is currently in the box. The point is that the object in the box can be replaced with a different one later, while keeping the attribute proxy in place. One use case is to redirect standard output only in particular threads.islice
now supports negative start and stop. (Caution: no negative step; and it must consume the whole iterable to determine where it ends, if at all.)async_raise
: Inject KeyboardInterrupt into an arbitrary thread. (CPython only.)resolve_bindings
: Get the parameter bindings a given callable would establish if it was called with the given args and kwargs. This is mainly of interest for implementing memoizers, since this allows them to see (e.g.)f(1)
andf(a=1)
as the same thing fordef f(a): pass
.Singleton
: a base class for singletons that interacts properly withpickle
. The pattern is slightly pythonified; instead of silently returning the same instance, attempting to invoke the constructor while an instance already exists raisesTypeError
. This solution separates concerns better; see #22.sym
: a lispy symbol type; or in plain English: a lightweight, human-readable, process-wide unique marker, that can be quickly compared to another such marker by object identity (is
). These named symbols are interned. Supplying the same name to the constructor results in receiving the same object instance. Symbols survive apickle
roundtrip.gensym
: a utility to create a new, unique uninterned symbol. Like the pythonic idiomnonce = object()
, but with a human-readable label, and withpickle
support. Object identity of gensyms is determined by an UUID, generated when the symbol is created. Gensyms also survive apickle
roundtrip.
Experimental features:
Each experimental feature is a provisional proof-of-concept, usually lacking battle-testing and polish. Details may still change in a backwards-incompatible way, or the whole feature may still be removed. Do not depend on it in production!
- Multiple dispatch. The
generic
decorator makes a generic function with multiple dispatch. Arity and type annotations determine which method of the generic function a specific call of the function is dispatched to.- This essentially allows replacing the
if
/elif
dynamic type checking boilerplate of polymorphic functions with type annotations on the function parameters, with support for features from thetyping
stdlib module. - Inspired by the multi-methods of CLOS (the Common Lisp Object System), and the generic functions of Julia.
- This essentially allows replacing the
typed
: The little sister of thegeneric
decorator. Restrict allowed argument types to one specific combination only.isoftype
: The big sister ofisinstance
. Type check a value against a type specification at run time, with support for many (but not all) features from thetyping
module. This is the machinery that powers@generic
and@typed
.- If you need a run-time type checker for serious general use, consider the
typeguard
library.
- If you need a run-time type checker for serious general use, consider the
Non-breaking changes:
setescape
/escape
have been renamedcatch
/throw
, to match the standard terminology in the Lisp family. The old nonstandard names are now deprecated, and will be removed in 0.15.0.- The parameters of
raisef
are now more pythonic, just the objectexc
and an optional keyword-onlycause
. Old-style parameters are now deprecated, and will be removed in 0.15.0. See #30. runpipe
andgetvalue
are now both replaced by a single unified nameexitpipe
. This is just a rename, with no functionality changes. The old names are now deprecated, and will be removed in 0.15.0.- Accessing the
.x
attribute of abox
directly is now deprecated. It does not work withThreadLocalBox
, which must handle things differently due to implementation reasons. Instead, use the API, which works for both types of boxes.b << newvalue
(syntactic sugar) orb.set(newvalue)
sends a different object into the box, andunbox(b)
(syntactic sugar) orb.get()
retrieves the current value. - The
dbg[]
macro now works in the REPL, too. See #12. - The
namedlambda
block macro now also names lambdas that are:- Passed as a named argument of a function call, as in
foo(f=lambda ...: ...)
; or - Inside a dictionary literal, with a literal string key, as in
{"f": lambda ...: ...}
. See #40.
- Passed as a named argument of a function call, as in
- Move macro documentation to
doc/macros.md
. (Wasmacro_extras/README.md
.) - Add contribution guidelines,
HACKING.md
.
Fixed:
- Fix initialization crash in
lazyutil
if MacroPy is not installed. - Fix bug in
identity
andconst
with zero args (#7). - Use standard Python semantics for negative indices (#6).
- Escape continuation analysis in
unpythonic.syntax.util
now interprets also the literal namethrow
as invoking an escape continuation. - Fix pickling of
frozendict
(#55). - Fix spurious cache misses in memoizers (#26). The bug affected
memoize
,gmemoize
,fix
andfixtco
.