-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a short demo to main README #42
Comments
At least this snippet should go in: from unpythonic.syntax import macros, tco
with tco:
evenp = lambda x: (x == 0) or oddp(x - 1)
oddp = lambda x: (x != 0) and evenp(x - 1)
assert evenp(10000) is True Automatic TCO works also with lambdas, and analyzes the tail position from expressions. In a logical expression (even when nested) it's always the rightmost item, because short-circuiting depends on values, which are not available at macro expansion time. |
|
Unpythonic in 30 seconds - Pure PythonSmall, limited-space overview of the overall flavor. Click to expand examples. Mathematical sequences. Slice syntax for general iterables.from unpythonic import s, islice
seq = s(1, 2, 4, ...)
assert tuple(islice(seq)[:10]) == (1, 2, 4, 8, 16, 32, 64, 128, 256, 512) Self-referring lambdas.from unpythonic import withself
fact = withself(lambda self, n: n * self(n - 1) if n > 1 else 1)
assert fact(5) == 120 Memoizing generators.from itertools import count, takewhile
from unpythonic import gmemoize, islice
@gmemoize
def primes(): # FP sieve of Eratosthenes
yield 2
for n in count(start=3, step=2):
if not any(n % p == 0 for p in takewhile(lambda x: x*x <= n, primes())):
yield n
assert tuple(islice(primes())[:10]) == (2, 3, 5, 7, 11, 13, 17, 19, 23, 29) Functional updates.from itertools import repeat
from unpythonic import fup
t = (1, 2, 3, 4, 5)
s = fup(t)[0::2] << tuple(repeat(10, 3))
assert s == (10, 2, 10, 4, 10)
assert t == (1, 2, 3, 4, 5) Slicable read-write list view.from unpythonic import view
lst = list(range(10))
v = view(lst)[::2] # [0, 2, 4, 6, 8]
v[2:4] = (10, 20)
assert lst == [0, 1, 2, 3, 10, 5, 20, 7, 8, 9]
lst[2] = 42
assert v == [0, 42, 10, 20, 8] Data flow focused function composition.from unpythonic import piped, getvalue
double = lambda x: 2 * x
inc = lambda x: x + 1
x = piped(42) | double | inc | getvalue
assert x == 85 |
Unpythonic in 30 seconds - MacrosLanguage-level extensions, with MacroPy. Click to expand examples. Expression-local variables.from unpythonic.syntax import macros, let
x = let[((a, 1), (b, 2)) in a + b] Definition-local variables, a.k.a. let-over-lambda for Python.from unpythonic.syntax import macros, dlet
@dlet((x, 0))
def count():
return x << x + 1 # << rebinds in the let env
assert count() == 1
assert count() == 2 Imperative code as an expression, with local variables.from unpythonic.syntax import macros, do, local, delete
x = do[local[a << 21],
local[b << 2 * a],
print(b),
delete[b], # do[] local variables can be deleted, too
4 * a]
assert x == 84 Automatic tail call optimization (TCO), with tail-position analysis also for expressions.from unpythonic.syntax import macros, tco
with tco:
evenp = lambda x: (x == 0) or oddp(x - 1)
oddp = lambda x: (x != 0) and evenp(x - 1)
assert evenp(10000) is True Automatic currying, à la Haskell.from unpythonic.syntax import macros, curry
from unpythonic import foldr, composerc as compose, cons, nil, ll
with curry:
def add3(a, b, c):
return a + b + c
assert add3(1)(2)(3) == 6
mymap = lambda f: foldr(compose(cons, f), nil)
double = lambda x: 2 * x
assert mymap(double, (1, 2, 3)) == ll(2, 4, 6) Lazy functions, a.k.a. call-by-need.from unpythonic.syntax import macros, lazify
with lazify:
def my_if(p, a, b):
if p:
return a # b never evaluated in this code path
else:
return b # a never evaluated in this code path
assert my_if(True, 23, 1/0) == 23
assert my_if(False, 1/0, 42) == 42 Continuations (call/cc), also with automatic TCO.from unpythonic import macros, continuations, call_cc
with continuations:
# McCarthy's amb() operator
stack = []
def amb(lst, cc):
if not lst:
return fail()
first, *rest = tuple(lst)
if rest:
remaining_part_of_computation = cc
stack.append(lambda: amb(rest, cc=remaining_part_of_computation))
return first
def fail():
if stack:
f = stack.pop()
return f()
# Pythagorean triples using amb()
def pt():
z = call_cc[amb(range(1, 21))] # capture continuation, auto-populate cc arg
y = call_cc[amb(range(1, z+1)))]
x = call_cc[amb(range(1, y+1))]
if x*x + y*y != z*z:
return fail()
return x, y, z
t = pt()
while t:
print(t)
t = fail() # note pt() has already returned when we call this. |
Now just include a doc link for each item, and merge this into the README... |
To improve the first impression, provide a runnable demo of an appropriate subset of features right near the start of the main README.
Focus on short and impressive. It does not need to be a complete tour. But it must, quickly, answer the universal first question: why should I bother to read any further?
Things to consider:
continuations
)?foldl
orscanl
with multiple inputs,memoize
that caches also exceptions)?s
.let
orcontinuations
.unpythonic
is essentially a language framework, where (unless specifically otherwise stated) all of the features are designed to work together?See #8 (mention of executable tagline).
The text was updated successfully, but these errors were encountered: