tasty feature extensions for python3(NO MAINTENANCE!).
This project is totally based on the entire CPython, so it is licensed under the terms of the PSF License Agreement.
See LICENSE for the details.
You now have to go to release page and download the binaries directly...
After downloading, just replace the original files with flowpython items.
Version : 0.2.3
See Flowpython project here.
Clone them and
./configure CC=clang
make
...
python
Python 3.5.4+ (heads/3.5-dirty:0a8ff1b, Oct 8 2017, 13:56:29)
[GCC 4.2.1 Compatible Clang 3.8.0 (tags/RELEASE_380/final)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> .x -> x+1
<function <lambda> at 0x7f159379aae8>
(P.S This is not available for CPython 3.5.x
fix if-expr
and add some new ways to define lambda
.
if-expr
you can write
ret = e1 if j1 else
e2 if j2 else
e3
instead of
ret = e1 if j1 else \
e2 if j2 else \
e3
lambda
.x -> x+1
as-with x def x+1
as-with x def as y def x+y
Parse:
where_stmt: 'where' ':' suite
compound_stmt
(NEWLINE | where_stmt)
Where(expr target, stmt* body)
AST:
ast_for_stmt
, ast_for_expr_stmt
,ast_for_flow_stmt
,ast_for_assert_stmt
, change it as what I did in flowpython/Python/ast.c. It tells the Python compiler how to get the data structure from the parsed codes.Compile&Interpret
change Python/compile.c
This part is kind of complicated to bring out, and I think that you'd better use version controller to detect out what's the differences between Flowpython and CPython 3.6.2.
change Python/symtable.c
Quite similar to compile.c.
P.S for Compile&Interpret
If your want to get a complete knowledge about how Python works, you should understand how the two C Module works firstly.
```python
from flowpython.composing import auto_logger, auto_compose, flow_map, flow_filter
auto_logger(__builtin__.__dict__)
>> sum.filter(.x->x,[0,1,2,3,0])
>> 6
```
as-with x def as y def as z def ret_value where:
ret_value = x + y +z
instead of:
as-with x def as y def as z def tmp(x+y+z) where:
def tmp(x,y,z):
return x +y +z
Does it seem to be currying?
.x->.y->.z-> ret where:
ret = x +y +z
fix-keyword
switch-case-otherwise -> condef-case-otherwise
Some new keywords brought by Flowpython, such as where, condef, case, otherwise, used to conflict with Standard Library and some important Libaraies from Third Party.
I fixed these conflictions with making the Parser module to ignore some grammar structures which would be checked in AST module.
So you can write these codes now:
# no confliction
where = 1
where += where where:
where += where
case = 1
otherwise = 2
condef 1:
case case => case
otherwise => otherwise
Take care that each syntax in [ where, case, otherwise ] are not real keywords, and condef is.
condef = 1
>>> SyntaxError: invalid syntax
pattern-matching
There are four kinds of matching rules in Flowpython:
condef [ == ] expr:
[>]
case test1 =>
<body1>
case test2 =>
<body2>
otherwise =>
<body3>
which equals to
if (expr > test1 )
<body1>
elif (expr == test2 )
<body2>
else:
<body3>
Each in [], (), +(), +[], {}
are called the operator comparing mode.
Giving a mode followed by condef keyword means giving a default mode.
The results are concluded here
for operator comparing mode "[<optional>]"
<optional> can be
==
>
<
>=
<=
in
not in
is
is not
condef (f) expr:
case test1 =>
<body1>
[!=]
case test2 =>
<body2>
equals
if (f(expr) == test1):
<body1>
elif expr != test2:
<body2>
condef {f} expr:
case test1 =>
<body1>
equals
if f(expr, test1):
<body1>
condef +[>] 1:
case a:2 =>
<body1>
+(type)
case a:int =>
<body2>
The codes above can be explained as following process:
if
we can do assignment a = 1
and expression a > 2
can be satisfied, then do <body1>
.else if
we can do assignment a = 1
and expression type(a) == int
can be satisfied, then do <body2>
.condef [1,2,3]:
...
condef {1,2,3}:
...
condef (1,2,3):
...
it will lead to syntax Error. But you can use this instead:
condef() [1,2,3]:
...
condef[] {1,2,3}:
...
condef{} (1,2,3):
...
Matching Method | Identity |
---|---|
comparing operator matching | [operator ] |
callable object matching | (callable ) |
dual callable comparing matching | {callable } |
python pattern matching(comparing) | +[operator ] |
python pattern matching(callable) | +(callable ) |
arrow transform
>> 1 -> _+1
>> 2
>> x = [1,2,3]
>> x -> map(.x->x+1, _) -> list(_)
>> [2,3,4]
lambda
>> .x -> x
>> _(1)
>> 1
>> var = [1,2,3]
>> .x -> map(.x->x+1, x) -> list(_)
>> _(var)
>> [2,3,4]
To conclude, lambda
is the lazy
form of arrow transform
..
means Take It As Lazy
```C
condef[] [1,2,3]:
+(type)
case (*a,b) -> a:list =>
print("just match 'a' with 'list' ")
otherwise =>
print("emmmmmm,,")
```
To support some basic operations in Functional Programming, here are methods implemented in flowpython.fp
.
from flowpython.fp import compose, andThen, foldr, foldl, flat_map, flatten
from flowpython.fp import strict, norecursion
strict_flatten = strict.flatten
strict_fastmap = strict.fastmap
strict_flat_map= strict.flat_map
norec_flatten = norecursion.lazy.flatten
# fastmap( use generator instead of map in original Python )
fastmap(.x -> x+1, [1,2,3]) -> list(_)
# -> [2,3,4]
strict_flat_map(.x->x+1, [1,2,3]) # -> [2,3,4]
# flatten
flatten([1,2,[3,4],[[5],[6]]]) -> list(_)
# -> [1,2,3,4,5,6]
# compose : Callable->Callable->Any
f1 -> compose(f2)(_)
# andThen : Callable->Callable->Any
f1 -> andThen(f2)(_)
# foreach : Callable->Callable->Any
range(20) -> foreach(print)(_)
# -> 0 \n 1 \n 2 ...
# fold : Dual Callable->(zero:Any)->Iterator->Any
foldr # (not recommended)
foldl # (not recommended)
range(20) -> foldr(. x,y -> print(x) or x+y)(0)(_)
range(20) -> foldr(. x,y -> print(y) or x+y)(0)(_)
# flat_map : Iterator -> Callable -> Iterator
# default lazy
flat_map(.x->x+1)([[1,2,[3,4],[5,6]],[7,8]]) -> list(_)
# -> [2,3,4,5,6,7,8,9]
# object in norecursion class use no recursive methods.
norec_flatten([[1,[2],[[3]],[[[4]]]]] -> list(_)
An easy way to define if-elif-else
statements:
( It's not guard
in Haskell ! )
otherwise = True
| x == 1 => x += 1
| type(x) is str => x = int(x)
| otherwise =>
x = 2*x
y = 1
def defined(key):
return key in globals()
print(x)
print(defined("y"))
func = .x -> ret where:
otherwise = True
| x is 0 => ret = 0.0
| type(x) in (str,int) => ret = float(x)
| otherwise => ret = x
Sorry for the shortage of documents for new grammar, and I'm busy with my new semester.
It would be completed as sooner as possible.
>> 1 ->> .x -> x*10 => .x-> x+1
>> 11
>> range(100) ->> f1 \
=> f2 \
=> groupby(.x->x) \
=> lambda Dict: map(.key->(key,len(Dict[key])), Dict) \
=> dict \
=> print where:
from flowpython.fp import groupby
f1 = . seq -> map(.x->x%2, seq)
f2 = . seq -> filter(.x -> x, seq)
>> {1:50}
closure
for where
syntax in case of Lambda Definition.switch syntax
.switch
syntax.switch-case-otherwise -> condef-case-otherwise
pattern matching
syntax.switch
syntax(which can be totally replaced by pattern matching
).pattern matching
.fp.py
.branches
grammar.pipeline
grammar.condic
to condef
.