coconut-develop 3.0.4.post0.dev7__tar.gz → 3.0.4.post0.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/DOCS.md +55 -4
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/PKG-INFO +2 -2
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/__coconut__/__init__.pyi +25 -3
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/command.py +0 -1
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/grammar.py +7 -3
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/header.py +5 -4
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/templates/header.py_template +66 -45
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/constants.py +2 -1
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/root.py +1 -1
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/terminal.py +3 -1
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/suite.coco +3 -1
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/util.coco +18 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/extras.coco +3 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/CONTRIBUTING.md +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/FAQ.md +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/HELP.md +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/LICENSE.txt +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/MANIFEST.in +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/README.rst +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/__coconut__/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/__coconut__/py.typed +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/_coconut/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/_coconut/__init__.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/_coconut/py.typed +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__coconut__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__coconut__.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__init__.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__main__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/_pyparsing.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/api.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/api.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/__init__.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/cli.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/command.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/mypy.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/resources/zcoconut.pth +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/util.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/watch.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/compiler.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/matching.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/util.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/convenience.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/convenience.pyi +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/exceptions.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/highlighter.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/__main__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/coconut/kernel.json +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/coconut_py/kernel.json +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/coconut_py2/kernel.json +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/coconut_py3/kernel.json +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/embed.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/root.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/integrations.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/main.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/py.typed +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/requirements.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/__init__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/__main__.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/constants_test.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/main_test.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/__init__.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/__main__.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/main.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/primary_1.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/primary_2.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/specific.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/agnostic/tutorial.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/non_strict/non_strict_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_2/py2_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_3/py3_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_311/py311_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_35/py35_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_36/py36_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_38/py38_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/cocotest/target_sys/target_sys_test.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/importable.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/runnable.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/runner.coco +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/util.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut_develop.egg-info/SOURCES.txt +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/conf.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/pyproject.toml +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/setup.cfg +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/setup.py +0 -0
- {coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/xontrib/coconut.py +0 -0
|
@@ -3505,11 +3505,11 @@ def flip(f, nargs=None) =
|
|
|
3505
3505
|
)
|
|
3506
3506
|
```
|
|
3507
3507
|
|
|
3508
|
-
#### `lift`
|
|
3508
|
+
#### `lift` and `lift_apart`
|
|
3509
3509
|
|
|
3510
|
-
**lift**(_func_)
|
|
3510
|
+
##### **lift**(_func_)
|
|
3511
3511
|
|
|
3512
|
-
**lift**(_func_, *_func\_args_, **_func\_kwargs_)
|
|
3512
|
+
##### **lift**(_func_, *_func\_args_, **_func\_kwargs_)
|
|
3513
3513
|
|
|
3514
3514
|
Coconut's `lift` built-in is a higher-order function that takes in a function and “lifts” it up so that all of its arguments are functions.
|
|
3515
3515
|
|
|
@@ -3533,7 +3533,33 @@ def lift(f) = (
|
|
|
3533
3533
|
|
|
3534
3534
|
`lift` also supports a shortcut form such that `lift(f, *func_args, **func_kwargs)` is equivalent to `lift(f)(*func_args, **func_kwargs)`.
|
|
3535
3535
|
|
|
3536
|
-
#####
|
|
3536
|
+
##### **lift\_apart**(_func_)
|
|
3537
|
+
|
|
3538
|
+
##### **lift\_apart**(_func_, *_func\_args_, **_func\_kwargs_)
|
|
3539
|
+
|
|
3540
|
+
Coconut's `lift_apart` built-in is very similar to `lift`, except instead of duplicating the final arguments to each function, it separates them out.
|
|
3541
|
+
|
|
3542
|
+
For a binary function `f(x, y)` and two unary functions `g(z)` and `h(z)`, `lift_apart` works as
|
|
3543
|
+
```coconut
|
|
3544
|
+
lift_apart(f)(g, h)(z, w) == f(g(z), h(w))
|
|
3545
|
+
```
|
|
3546
|
+
such that in this case `lift_apart` implements the `D2` combinator.
|
|
3547
|
+
|
|
3548
|
+
In the general case, `lift_apart` is equivalent to a pickleable version of
|
|
3549
|
+
```coconut
|
|
3550
|
+
def lift_apart(f) = (
|
|
3551
|
+
(*func_args, **func_kwargs) =>
|
|
3552
|
+
(*args, **kwargs) =>
|
|
3553
|
+
f(
|
|
3554
|
+
*(f(x) for f, x in zip(func_args, args, strict=True)),
|
|
3555
|
+
**{k: func_kwargs[k](kwargs[k]) for k in func_kwargs.keys() | kwargs.keys()},
|
|
3556
|
+
)
|
|
3557
|
+
)
|
|
3558
|
+
```
|
|
3559
|
+
|
|
3560
|
+
`lift_apart` supports the same shortcut form as `lift`.
|
|
3561
|
+
|
|
3562
|
+
##### Examples
|
|
3537
3563
|
|
|
3538
3564
|
**Coconut:**
|
|
3539
3565
|
```coconut
|
|
@@ -3552,8 +3578,33 @@ def plus_and_times(x, y):
|
|
|
3552
3578
|
return x + y, x * y
|
|
3553
3579
|
```
|
|
3554
3580
|
|
|
3581
|
+
**Coconut:**
|
|
3582
|
+
```coconut
|
|
3583
|
+
first_false_and_last_true = (
|
|
3584
|
+
lift(,)(ident, reversed)
|
|
3585
|
+
..*> lift_apart(,)(dropwhile$(bool), dropwhile$(not))
|
|
3586
|
+
..*> lift_apart(,)(.$[0], .$[0])
|
|
3587
|
+
)
|
|
3588
|
+
```
|
|
3589
|
+
|
|
3590
|
+
**Python:**
|
|
3591
|
+
```coconut_python
|
|
3592
|
+
from itertools import dropwhile
|
|
3593
|
+
|
|
3594
|
+
def first_false_and_last_true(xs):
|
|
3595
|
+
rev_xs = reversed(xs)
|
|
3596
|
+
return (
|
|
3597
|
+
next(dropwhile(bool, xs)),
|
|
3598
|
+
next(dropwhile(lambda x: not x, rev_xs)),
|
|
3599
|
+
)
|
|
3600
|
+
```
|
|
3601
|
+
|
|
3555
3602
|
#### `and_then` and `and_then_await`
|
|
3556
3603
|
|
|
3604
|
+
**and\_then**(_first\_async\_func_, _second\_func_)
|
|
3605
|
+
|
|
3606
|
+
**and\_then\_await**(_first\_async\_func_, _second\_async\_func_)
|
|
3607
|
+
|
|
3557
3608
|
Coconut provides the `and_then` and `and_then_await` built-ins for composing `async` functions. Specifically:
|
|
3558
3609
|
* To forwards compose an async function `async_f` with a normal function `g` (such that `g` is called on the result of `await`ing `async_f`), write ``async_f `and_then` g``.
|
|
3559
3610
|
* To forwards compose an async function `async_f` with another async function `async_g` (such that `async_g` is called on the result of `await`ing `async_f`, and then `async_g` is itself awaited), write ``async_f `and_then_await` async_g``.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: coconut-develop
|
|
3
|
-
Version: 3.0.4.post0.
|
|
3
|
+
Version: 3.0.4.post0.dev8
|
|
4
4
|
Summary: Simple, elegant, Pythonic functional programming.
|
|
5
5
|
Home-page: http://coconut-lang.org
|
|
6
6
|
Author: Evan Hubinger
|
|
@@ -89,7 +89,7 @@ Description: |logo| Coconut
|
|
|
89
89
|
__ Sponsor_
|
|
90
90
|
.. _Sponsor: https://opencollective.com/coconut#sponsor
|
|
91
91
|
|
|
92
|
-
Keywords: functional,programming,language,compiler,pattern,pattern-matching,algebraic,data type,data types,lambda,lambdas,lazy,evaluation,lazy list,lazy lists,tail,recursion,call,recursive,recursive_iterator,infix,function,composition,compose,partial,application,currying,curry,pipeline,pipe,unicode,operator,operators,frozenset,literal,syntax,destructuring,assignment,fold,datamaker,prepattern,iterator,generator,none,coalesce,coalescing,statement,lru_cache,memoization,backport,typing,embed,PEP 622,overrides,islice,itertools,functools,TYPE_CHECKING,Expected,breakpoint,help,reduce,takewhile,dropwhile,tee,count,makedata,consume,process_map,thread_map,addpattern,recursive_generator,fmap,starmap,reiterable,scan,groupsof,memoize,zip_longest,override,flatten,ident,call,safe_call,flip,const,lift,all_equal,collectby,mapreduce,multi_enumerate,cartesian_product,multiset,cycle,windowsof,and_then,and_then_await,async_map,py_chr,py_dict,py_hex,py_input,py_int,py_map,py_object,py_oct,py_open,py_print,py_range,py_str,py_super,py_zip,py_filter,py_reversed,py_enumerate,py_raw_input,py_xrange,py_repr,py_breakpoint,_namedtuple_of,reveal_type,reveal_locals,MatchError,ExceptionGroup,BaseExceptionGroup,__fmap__,__iter_getitem__,data,match,case,cases,where,addpattern,then,operator,type,copyclosure,λ
|
|
92
|
+
Keywords: functional,programming,language,compiler,pattern,pattern-matching,algebraic,data type,data types,lambda,lambdas,lazy,evaluation,lazy list,lazy lists,tail,recursion,call,recursive,recursive_iterator,infix,function,composition,compose,partial,application,currying,curry,pipeline,pipe,unicode,operator,operators,frozenset,literal,syntax,destructuring,assignment,fold,datamaker,prepattern,iterator,generator,none,coalesce,coalescing,statement,lru_cache,memoization,backport,typing,embed,PEP 622,overrides,islice,itertools,functools,TYPE_CHECKING,Expected,breakpoint,help,reduce,takewhile,dropwhile,tee,count,makedata,consume,process_map,thread_map,addpattern,recursive_generator,fmap,starmap,reiterable,scan,groupsof,memoize,zip_longest,override,flatten,ident,call,safe_call,flip,const,lift,lift_apart,all_equal,collectby,mapreduce,multi_enumerate,cartesian_product,multiset,cycle,windowsof,and_then,and_then_await,async_map,py_chr,py_dict,py_hex,py_input,py_int,py_map,py_object,py_oct,py_open,py_print,py_range,py_str,py_super,py_zip,py_filter,py_reversed,py_enumerate,py_raw_input,py_xrange,py_repr,py_breakpoint,_namedtuple_of,reveal_type,reveal_locals,MatchError,ExceptionGroup,BaseExceptionGroup,__fmap__,__iter_getitem__,data,match,case,cases,where,addpattern,then,operator,type,copyclosure,λ
|
|
93
93
|
Platform: UNKNOWN
|
|
94
94
|
Classifier: Development Status :: 5 - Production/Stable
|
|
95
95
|
Classifier: License :: OSI Approved :: Apache Software License
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/__coconut__/__init__.pyi
RENAMED
|
@@ -1636,20 +1636,42 @@ def lift(func: _t.Callable[[_T, _U], _W]) -> _coconut_lifted_2[_T, _U, _W]: ...
|
|
|
1636
1636
|
def lift(func: _t.Callable[[_T, _U, _V], _W]) -> _coconut_lifted_3[_T, _U, _V, _W]: ...
|
|
1637
1637
|
@_t.overload
|
|
1638
1638
|
def lift(func: _t.Callable[..., _W]) -> _t.Callable[..., _t.Callable[..., _W]]:
|
|
1639
|
-
"""Lift a function up so that all of its arguments are functions.
|
|
1639
|
+
"""Lift a function up so that all of its arguments are functions that all take the same arguments.
|
|
1640
1640
|
|
|
1641
1641
|
For a binary function f(x, y) and two unary functions g(z) and h(z), lift works as the S' combinator:
|
|
1642
1642
|
lift(f)(g, h)(z) == f(g(z), h(z))
|
|
1643
1643
|
|
|
1644
1644
|
In general, lift is equivalent to:
|
|
1645
|
-
def lift(f) = ((*func_args, **func_kwargs)
|
|
1646
|
-
f(*(g(*args, **kwargs) for g in func_args), **{
|
|
1645
|
+
def lift(f) = ((*func_args, **func_kwargs) => (*args, **kwargs) => (
|
|
1646
|
+
f(*(g(*args, **kwargs) for g in func_args), **{k: h(*args, **kwargs) for k, h in func_kwargs.items()}))
|
|
1647
|
+
)
|
|
1647
1648
|
|
|
1648
1649
|
lift also supports a shortcut form such that lift(f, *func_args, **func_kwargs) is equivalent to lift(f)(*func_args, **func_kwargs).
|
|
1649
1650
|
"""
|
|
1650
1651
|
...
|
|
1651
1652
|
_coconut_lift = lift
|
|
1652
1653
|
|
|
1654
|
+
@_t.overload
|
|
1655
|
+
def lift_apart(func: _t.Callable[[_T], _W]) -> _t.Callable[[_t.Callable[[_U], _T]], _t.Callable[[_U], _W]]: ...
|
|
1656
|
+
@_t.overload
|
|
1657
|
+
def lift_apart(func: _t.Callable[[_T, _X], _W]) -> _t.Callable[[_t.Callable[[_U], _T], _t.Callable[[_Y], _X]], _t.Callable[[_U, _Y], _W]]: ...
|
|
1658
|
+
@_t.overload
|
|
1659
|
+
def lift_apart(func: _t.Callable[..., _W]) -> _t.Callable[..., _t.Callable[..., _W]]:
|
|
1660
|
+
"""Lift a function up so that all of its arguments are functions that each take separate arguments.
|
|
1661
|
+
|
|
1662
|
+
For a binary function f(x, y) and two unary functions g(z) and h(z), lift_apart works as the D2 combinator:
|
|
1663
|
+
lift_apart(f)(g, h)(z, w) == f(g(z), h(w))
|
|
1664
|
+
|
|
1665
|
+
In general, lift_apart is equivalent to:
|
|
1666
|
+
def lift_apart(func) = (*func_args, **func_kwargs) => (*args, **kwargs) => func(
|
|
1667
|
+
*map(call, func_args, args, strict=True),
|
|
1668
|
+
**{k: func_kwargs[k](kwargs[k]) for k in func_kwargs.keys() | kwargs.keys()},
|
|
1669
|
+
)
|
|
1670
|
+
|
|
1671
|
+
lift_apart also supports a shortcut form such that lift_apart(f, *func_args, **func_kwargs) is equivalent to lift_apart(f)(*func_args, **func_kwargs).
|
|
1672
|
+
"""
|
|
1673
|
+
...
|
|
1674
|
+
|
|
1653
1675
|
|
|
1654
1676
|
def all_equal(iterable: _Iterable) -> bool:
|
|
1655
1677
|
"""For a given iterable, check whether all elements in that iterable are equal to each other.
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/grammar.py
RENAMED
|
@@ -1381,9 +1381,13 @@ class Grammar(object):
|
|
|
1381
1381
|
simple_assign = Forward()
|
|
1382
1382
|
simple_assign_ref = maybeparens(
|
|
1383
1383
|
lparen,
|
|
1384
|
-
(
|
|
1385
|
-
|
|
1386
|
-
|
|
1384
|
+
(
|
|
1385
|
+
# refname if there's a trailer, setname if not
|
|
1386
|
+
(refname | passthrough_atom) + OneOrMore(ZeroOrMore(complex_trailer) + OneOrMore(simple_trailer))
|
|
1387
|
+
| setname
|
|
1388
|
+
| passthrough_atom
|
|
1389
|
+
),
|
|
1390
|
+
rparen
|
|
1387
1391
|
)
|
|
1388
1392
|
simple_assignlist = maybeparens(lparen, itemlist(simple_assign, comma, suppress_trailing=False), rparen)
|
|
1389
1393
|
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/header.py
RENAMED
|
@@ -290,11 +290,15 @@ def process_header_args(which, use_hash, target, no_tco, strict, no_wrap):
|
|
|
290
290
|
report_this_text=report_this_text,
|
|
291
291
|
from_None=" from None" if target.startswith("3") else "",
|
|
292
292
|
process_="process_" if target_info >= (3, 13) else "",
|
|
293
|
-
|
|
294
293
|
numpy_modules=tuple_str_of(numpy_modules, add_quotes=True),
|
|
295
294
|
pandas_numpy_modules=tuple_str_of(pandas_numpy_modules, add_quotes=True),
|
|
296
295
|
jax_numpy_modules=tuple_str_of(jax_numpy_modules, add_quotes=True),
|
|
297
296
|
self_match_types=tuple_str_of(self_match_types),
|
|
297
|
+
comma_bytearray=", bytearray" if not target.startswith("3") else "",
|
|
298
|
+
lstatic="staticmethod(" if not target.startswith("3") else "",
|
|
299
|
+
rstatic=")" if not target.startswith("3") else "",
|
|
300
|
+
all_keys="self.func_kwargs.keys() | kwargs.keys()" if target_info >= (3,) else "_coconut.set(self.func_kwargs.keys()) | _coconut.set(kwargs.keys())",
|
|
301
|
+
|
|
298
302
|
set_super=(
|
|
299
303
|
# we have to use _coconut_super even on the universal target, since once we set __class__ it becomes a local variable
|
|
300
304
|
"super = py_super" if target.startswith("3") else "super = _coconut_super"
|
|
@@ -335,9 +339,6 @@ zip_longest = itertools.zip_longest if _coconut_sys.version_info >= (3,) else it
|
|
|
335
339
|
else "zip_longest = itertools.izip_longest",
|
|
336
340
|
indent=1,
|
|
337
341
|
),
|
|
338
|
-
comma_bytearray=", bytearray" if not target.startswith("3") else "",
|
|
339
|
-
lstatic="staticmethod(" if not target.startswith("3") else "",
|
|
340
|
-
rstatic=")" if not target.startswith("3") else "",
|
|
341
342
|
zip_iter=prepare(
|
|
342
343
|
r'''
|
|
343
344
|
for items in _coconut.iter(_coconut.zip(*self.iters, strict=self.strict) if _coconut_sys.version_info >= (3, 10) else _coconut.zip_longest(*self.iters, fillvalue=_coconut_sentinel) if self.strict else _coconut.zip(*self.iters)):
|
|
@@ -432,7 +432,7 @@ def and_then(first_async_func, second_func):
|
|
|
432
432
|
first_async_func: async (**T) -> U,
|
|
433
433
|
second_func: U -> V,
|
|
434
434
|
) -> async (**T) -> V =
|
|
435
|
-
async def (*args, **kwargs)
|
|
435
|
+
async def (*args, **kwargs) => (
|
|
436
436
|
first_async_func(*args, **kwargs)
|
|
437
437
|
|> await
|
|
438
438
|
|> second_func
|
|
@@ -447,7 +447,7 @@ def and_then_await(first_async_func, second_async_func):
|
|
|
447
447
|
first_async_func: async (**T) -> U,
|
|
448
448
|
second_async_func: async U -> V,
|
|
449
449
|
) -> async (**T) -> V =
|
|
450
|
-
async def (*args, **kwargs)
|
|
450
|
+
async def (*args, **kwargs) => (
|
|
451
451
|
first_async_func(*args, **kwargs)
|
|
452
452
|
|> await
|
|
453
453
|
|> second_async_func
|
|
@@ -458,98 +458,98 @@ def and_then_await(first_async_func, second_async_func):
|
|
|
458
458
|
def _coconut_forward_compose(func, *funcs):
|
|
459
459
|
"""Forward composition operator (..>).
|
|
460
460
|
|
|
461
|
-
(..>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
461
|
+
(..>)(f, g) is effectively equivalent to (*args, **kwargs) => g(f(*args, **kwargs))."""
|
|
462
462
|
return _coconut_base_compose(func, *((f, 0, False) for f in funcs))
|
|
463
463
|
def _coconut_back_compose(*funcs):
|
|
464
464
|
"""Backward composition operator (<..).
|
|
465
465
|
|
|
466
|
-
(<..)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
466
|
+
(<..)(f, g) is effectively equivalent to (*args, **kwargs) => f(g(*args, **kwargs))."""
|
|
467
467
|
return _coconut_forward_compose(*_coconut.reversed(funcs))
|
|
468
468
|
def _coconut_forward_none_compose(func, *funcs):
|
|
469
469
|
"""Forward none-aware composition operator (..?>).
|
|
470
470
|
|
|
471
|
-
(..?>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
471
|
+
(..?>)(f, g) is effectively equivalent to (*args, **kwargs) => g?(f(*args, **kwargs))."""
|
|
472
472
|
return _coconut_base_compose(func, *((f, 0, True) for f in funcs))
|
|
473
473
|
def _coconut_back_none_compose(*funcs):
|
|
474
474
|
"""Backward none-aware composition operator (<..?).
|
|
475
475
|
|
|
476
|
-
(<..?)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
476
|
+
(<..?)(f, g) is effectively equivalent to (*args, **kwargs) => f?(g(*args, **kwargs))."""
|
|
477
477
|
return _coconut_forward_none_compose(*_coconut.reversed(funcs))
|
|
478
478
|
def _coconut_forward_star_compose(func, *funcs):
|
|
479
479
|
"""Forward star composition operator (..*>).
|
|
480
480
|
|
|
481
|
-
(..*>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
481
|
+
(..*>)(f, g) is effectively equivalent to (*args, **kwargs) => g(*f(*args, **kwargs))."""
|
|
482
482
|
return _coconut_base_compose(func, *((f, 1, False) for f in funcs))
|
|
483
483
|
def _coconut_back_star_compose(*funcs):
|
|
484
484
|
"""Backward star composition operator (<*..).
|
|
485
485
|
|
|
486
|
-
(<*..)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
486
|
+
(<*..)(f, g) is effectively equivalent to (*args, **kwargs) => f(*g(*args, **kwargs))."""
|
|
487
487
|
return _coconut_forward_star_compose(*_coconut.reversed(funcs))
|
|
488
488
|
def _coconut_forward_none_star_compose(func, *funcs):
|
|
489
489
|
"""Forward none-aware star composition operator (..?*>).
|
|
490
490
|
|
|
491
|
-
(..?*>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
491
|
+
(..?*>)(f, g) is effectively equivalent to (*args, **kwargs) => g?(*f(*args, **kwargs))."""
|
|
492
492
|
return _coconut_base_compose(func, *((f, 1, True) for f in funcs))
|
|
493
493
|
def _coconut_back_none_star_compose(*funcs):
|
|
494
494
|
"""Backward none-aware star composition operator (<*?..).
|
|
495
495
|
|
|
496
|
-
(<*?..)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
496
|
+
(<*?..)(f, g) is effectively equivalent to (*args, **kwargs) => f?(*g(*args, **kwargs))."""
|
|
497
497
|
return _coconut_forward_none_star_compose(*_coconut.reversed(funcs))
|
|
498
498
|
def _coconut_forward_dubstar_compose(func, *funcs):
|
|
499
499
|
"""Forward double star composition operator (..**>).
|
|
500
500
|
|
|
501
|
-
(..**>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
501
|
+
(..**>)(f, g) is effectively equivalent to (*args, **kwargs) => g(**f(*args, **kwargs))."""
|
|
502
502
|
return _coconut_base_compose(func, *((f, 2, False) for f in funcs))
|
|
503
503
|
def _coconut_back_dubstar_compose(*funcs):
|
|
504
504
|
"""Backward double star composition operator (<**..).
|
|
505
505
|
|
|
506
|
-
(<**..)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
506
|
+
(<**..)(f, g) is effectively equivalent to (*args, **kwargs) => f(**g(*args, **kwargs))."""
|
|
507
507
|
return _coconut_forward_dubstar_compose(*_coconut.reversed(funcs))
|
|
508
508
|
def _coconut_forward_none_dubstar_compose(func, *funcs):
|
|
509
509
|
"""Forward none-aware double star composition operator (..?**>).
|
|
510
510
|
|
|
511
|
-
(..?**>)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
511
|
+
(..?**>)(f, g) is effectively equivalent to (*args, **kwargs) => g?(**f(*args, **kwargs))."""
|
|
512
512
|
return _coconut_base_compose(func, *((f, 2, True) for f in funcs))
|
|
513
513
|
def _coconut_back_none_dubstar_compose(*funcs):
|
|
514
514
|
"""Backward none-aware double star composition operator (<**?..).
|
|
515
515
|
|
|
516
|
-
(<**?..)(f, g) is effectively equivalent to (*args, **kwargs)
|
|
516
|
+
(<**?..)(f, g) is effectively equivalent to (*args, **kwargs) => f?(**g(*args, **kwargs))."""
|
|
517
517
|
return _coconut_forward_none_dubstar_compose(*_coconut.reversed(funcs))
|
|
518
518
|
def _coconut_pipe(x, f):
|
|
519
|
-
"""Pipe operator (|>). Equivalent to (x, f)
|
|
519
|
+
"""Pipe operator (|>). Equivalent to (x, f) => f(x)."""
|
|
520
520
|
return f(x)
|
|
521
521
|
def _coconut_star_pipe(xs, f):
|
|
522
|
-
"""Star pipe operator (*|>). Equivalent to (xs, f)
|
|
522
|
+
"""Star pipe operator (*|>). Equivalent to (xs, f) => f(*xs)."""
|
|
523
523
|
return f(*xs)
|
|
524
524
|
def _coconut_dubstar_pipe(kws, f):
|
|
525
|
-
"""Double star pipe operator (**|>). Equivalent to (kws, f)
|
|
525
|
+
"""Double star pipe operator (**|>). Equivalent to (kws, f) => f(**kws)."""
|
|
526
526
|
return f(**kws)
|
|
527
527
|
def _coconut_back_pipe(f, x):
|
|
528
|
-
"""Backward pipe operator (<|). Equivalent to (f, x)
|
|
528
|
+
"""Backward pipe operator (<|). Equivalent to (f, x) => f(x)."""
|
|
529
529
|
return f(x)
|
|
530
530
|
def _coconut_back_star_pipe(f, xs):
|
|
531
|
-
"""Backward star pipe operator (<*|). Equivalent to (f, xs)
|
|
531
|
+
"""Backward star pipe operator (<*|). Equivalent to (f, xs) => f(*xs)."""
|
|
532
532
|
return f(*xs)
|
|
533
533
|
def _coconut_back_dubstar_pipe(f, kws):
|
|
534
|
-
"""Backward double star pipe operator (<**|). Equivalent to (f, kws)
|
|
534
|
+
"""Backward double star pipe operator (<**|). Equivalent to (f, kws) => f(**kws)."""
|
|
535
535
|
return f(**kws)
|
|
536
536
|
def _coconut_none_pipe(x, f):
|
|
537
|
-
"""Nullable pipe operator (|?>). Equivalent to (x, f)
|
|
537
|
+
"""Nullable pipe operator (|?>). Equivalent to (x, f) => f(x) if x is not None else None."""
|
|
538
538
|
return None if x is None else f(x)
|
|
539
539
|
def _coconut_none_star_pipe(xs, f):
|
|
540
|
-
"""Nullable star pipe operator (|?*>). Equivalent to (xs, f)
|
|
540
|
+
"""Nullable star pipe operator (|?*>). Equivalent to (xs, f) => f(*xs) if xs is not None else None."""
|
|
541
541
|
return None if xs is None else f(*xs)
|
|
542
542
|
def _coconut_none_dubstar_pipe(kws, f):
|
|
543
|
-
"""Nullable double star pipe operator (|?**>). Equivalent to (kws, f)
|
|
543
|
+
"""Nullable double star pipe operator (|?**>). Equivalent to (kws, f) => f(**kws) if kws is not None else None."""
|
|
544
544
|
return None if kws is None else f(**kws)
|
|
545
545
|
def _coconut_back_none_pipe(f, x):
|
|
546
|
-
"""Nullable backward pipe operator (<?|). Equivalent to (f, x)
|
|
546
|
+
"""Nullable backward pipe operator (<?|). Equivalent to (f, x) => f(x) if x is not None else None."""
|
|
547
547
|
return None if x is None else f(x)
|
|
548
548
|
def _coconut_back_none_star_pipe(f, xs):
|
|
549
|
-
"""Nullable backward star pipe operator (<*?|). Equivalent to (f, xs)
|
|
549
|
+
"""Nullable backward star pipe operator (<*?|). Equivalent to (f, xs) => f(*xs) if xs is not None else None."""
|
|
550
550
|
return None if xs is None else f(*xs)
|
|
551
551
|
def _coconut_back_none_dubstar_pipe(f, kws):
|
|
552
|
-
"""Nullable backward double star pipe operator (<**?|). Equivalent to (kws, f)
|
|
552
|
+
"""Nullable backward double star pipe operator (<**?|). Equivalent to (kws, f) => f(**kws) if kws is not None else None."""
|
|
553
553
|
return None if kws is None else f(**kws)
|
|
554
554
|
def _coconut_assert(cond, msg=None):
|
|
555
555
|
"""Assert operator (assert). Asserts condition with optional message."""
|
|
@@ -563,27 +563,27 @@ def _coconut_raise(exc=None, from_exc=None):
|
|
|
563
563
|
exc.__cause__ = from_exc
|
|
564
564
|
raise exc
|
|
565
565
|
def _coconut_bool_and(a, b):
|
|
566
|
-
"""Boolean and operator (and). Equivalent to (a, b)
|
|
566
|
+
"""Boolean and operator (and). Equivalent to (a, b) => a and b."""
|
|
567
567
|
return a and b
|
|
568
568
|
def _coconut_bool_or(a, b):
|
|
569
|
-
"""Boolean or operator (or). Equivalent to (a, b)
|
|
569
|
+
"""Boolean or operator (or). Equivalent to (a, b) => a or b."""
|
|
570
570
|
return a or b
|
|
571
571
|
def _coconut_in(a, b):
|
|
572
|
-
"""Containment operator (in). Equivalent to (a, b)
|
|
572
|
+
"""Containment operator (in). Equivalent to (a, b) => a in b."""
|
|
573
573
|
return a in b
|
|
574
574
|
def _coconut_not_in(a, b):
|
|
575
|
-
"""Negative containment operator (not in). Equivalent to (a, b)
|
|
575
|
+
"""Negative containment operator (not in). Equivalent to (a, b) => a not in b."""
|
|
576
576
|
return a not in b
|
|
577
577
|
def _coconut_none_coalesce(a, b):
|
|
578
|
-
"""None coalescing operator (??). Equivalent to (a, b)
|
|
578
|
+
"""None coalescing operator (??). Equivalent to (a, b) => a if a is not None else b."""
|
|
579
579
|
return b if a is None else a
|
|
580
580
|
def _coconut_minus(a, b=_coconut_sentinel):
|
|
581
|
-
"""Minus operator (-). Effectively equivalent to (a, b=None)
|
|
581
|
+
"""Minus operator (-). Effectively equivalent to (a, b=None) => a - b if b is not None else -a."""
|
|
582
582
|
if b is _coconut_sentinel:
|
|
583
583
|
return -a
|
|
584
584
|
return a - b
|
|
585
585
|
def _coconut_comma_op(*args):
|
|
586
|
-
"""Comma operator (,). Equivalent to (*args)
|
|
586
|
+
"""Comma operator (,). Equivalent to (*args) => args."""
|
|
587
587
|
return args
|
|
588
588
|
{def_coconut_matmul}
|
|
589
589
|
class scan(_coconut_has_iter):
|
|
@@ -1678,7 +1678,7 @@ def _coconut_dict_merge(*dicts, **kwargs):
|
|
|
1678
1678
|
prevlen = _coconut.len(newdict)
|
|
1679
1679
|
return newdict
|
|
1680
1680
|
def ident(x, **kwargs):
|
|
1681
|
-
"""The identity function. Generally equivalent to x
|
|
1681
|
+
"""The identity function. Generally equivalent to x => x. Useful in point-free programming.
|
|
1682
1682
|
Accepts one keyword-only argument, side_effect, which specifies a function to call on the argument before it is returned."""
|
|
1683
1683
|
side_effect = kwargs.pop("side_effect", None)
|
|
1684
1684
|
if kwargs:
|
|
@@ -1874,30 +1874,36 @@ class const(_coconut_base_callable):
|
|
|
1874
1874
|
def __repr__(self):
|
|
1875
1875
|
return "const(%s)" % (_coconut.repr(self.value),)
|
|
1876
1876
|
class _coconut_lifted(_coconut_base_callable):
|
|
1877
|
-
__slots__ = ("func", "func_args", "func_kwargs")
|
|
1878
|
-
def __init__(self,
|
|
1879
|
-
self.
|
|
1877
|
+
__slots__ = ("apart", "func", "func_args", "func_kwargs")
|
|
1878
|
+
def __init__(self, apart, func, func_args, func_kwargs):
|
|
1879
|
+
self.apart = apart
|
|
1880
|
+
self.func = func
|
|
1880
1881
|
self.func_args = func_args
|
|
1881
1882
|
self.func_kwargs = func_kwargs
|
|
1882
1883
|
def __reduce__(self):
|
|
1883
|
-
return (self.__class__, (self.func,
|
|
1884
|
+
return (self.__class__, (self.apart, self.func, self.func_args, self.func_kwargs))
|
|
1884
1885
|
def __call__(self, *args, **kwargs):
|
|
1885
|
-
|
|
1886
|
+
if self.apart:
|
|
1887
|
+
return self.func(*(f(x) for f, x in {_coconut_}zip(self.func_args, args, strict=True)), **_coconut_py_dict((k, self.func_kwargs[k](kwargs[k])) for k in {all_keys}))
|
|
1888
|
+
else:
|
|
1889
|
+
return self.func(*(g(*args, **kwargs) for g in self.func_args), **_coconut_py_dict((k, h(*args, **kwargs)) for k, h in self.func_kwargs.items()))
|
|
1886
1890
|
def __repr__(self):
|
|
1887
|
-
return "lift(%r)(%s%s)" % (self.func, ", ".join(_coconut.repr(g) for g in self.func_args), ", ".join(k + "=" + _coconut.repr(h) for k, h in self.func_kwargs.items()))
|
|
1891
|
+
return "lift%s(%r)(%s%s)" % (self.func, ("_apart" if self.apart else ""), ", ".join(_coconut.repr(g) for g in self.func_args), ", ".join(k + "=" + _coconut.repr(h) for k, h in self.func_kwargs.items()))
|
|
1888
1892
|
class lift(_coconut_base_callable):
|
|
1889
|
-
"""Lift a function up so that all of its arguments are functions.
|
|
1893
|
+
"""Lift a function up so that all of its arguments are functions that all take the same arguments.
|
|
1890
1894
|
|
|
1891
1895
|
For a binary function f(x, y) and two unary functions g(z) and h(z), lift works as the S' combinator:
|
|
1892
1896
|
lift(f)(g, h)(z) == f(g(z), h(z))
|
|
1893
1897
|
|
|
1894
1898
|
In general, lift is equivalent to:
|
|
1895
|
-
def lift(f) = ((*func_args, **func_kwargs)
|
|
1899
|
+
def lift(f) = ((*func_args, **func_kwargs) => (*args, **kwargs) => (
|
|
1896
1900
|
f(*(g(*args, **kwargs) for g in func_args), **{lbrace}k: h(*args, **kwargs) for k, h in func_kwargs.items(){rbrace}))
|
|
1901
|
+
)
|
|
1897
1902
|
|
|
1898
1903
|
lift also supports a shortcut form such that lift(f, *func_args, **func_kwargs) is equivalent to lift(f)(*func_args, **func_kwargs).
|
|
1899
1904
|
"""
|
|
1900
1905
|
__slots__ = ("func",)
|
|
1906
|
+
_apart = False
|
|
1901
1907
|
def __new__(cls, func, *func_args, **func_kwargs):
|
|
1902
1908
|
self = _coconut.super({_coconut_}lift, cls).__new__(cls)
|
|
1903
1909
|
self.func = func
|
|
@@ -1907,9 +1913,24 @@ class lift(_coconut_base_callable):
|
|
|
1907
1913
|
def __reduce__(self):
|
|
1908
1914
|
return (self.__class__, (self.func,))
|
|
1909
1915
|
def __repr__(self):
|
|
1910
|
-
return "lift(%r)" % (self.func
|
|
1916
|
+
return "lift%s(%r)" % (("_apart" if self._apart else ""), self.func)
|
|
1911
1917
|
def __call__(self, *func_args, **func_kwargs):
|
|
1912
|
-
return _coconut_lifted(self.func,
|
|
1918
|
+
return _coconut_lifted(self._apart, self.func, func_args, func_kwargs)
|
|
1919
|
+
class lift_apart(lift):
|
|
1920
|
+
"""Lift a function up so that all of its arguments are functions that each take separate arguments.
|
|
1921
|
+
|
|
1922
|
+
For a binary function f(x, y) and two unary functions g(z) and h(z), lift_apart works as the D2 combinator:
|
|
1923
|
+
lift_apart(f)(g, h)(z, w) == f(g(z), h(w))
|
|
1924
|
+
|
|
1925
|
+
In general, lift_apart is equivalent to:
|
|
1926
|
+
def lift_apart(func) = (*func_args, **func_kwargs) => (*args, **kwargs) => func(
|
|
1927
|
+
*(f(x) for f, x in zip(func_args, args, strict=True)),
|
|
1928
|
+
**{lbrace}k: func_kwargs[k](kwargs[k]) for k in func_kwargs.keys() | kwargs.keys(){rbrace},
|
|
1929
|
+
)
|
|
1930
|
+
|
|
1931
|
+
lift_apart also supports a shortcut form such that lift_apart(f, *func_args, **func_kwargs) is equivalent to lift_apart(f)(*func_args, **func_kwargs).
|
|
1932
|
+
"""
|
|
1933
|
+
_apart = True
|
|
1913
1934
|
def all_equal(iterable):
|
|
1914
1935
|
"""For a given iterable, check whether all elements in that iterable are equal to each other.
|
|
1915
1936
|
|
|
@@ -1974,7 +1995,7 @@ def collectby(key_func, iterable, value_func=None, **kwargs):
|
|
|
1974
1995
|
If map_using is passed, calculate key_func and value_func by mapping them over
|
|
1975
1996
|
the iterable using map_using as map. Useful with process_map/thread_map.
|
|
1976
1997
|
"""
|
|
1977
|
-
return {_coconut_}mapreduce(_coconut_lifted(_coconut_comma_op, key_func, {_coconut_}ident if value_func is None else value_func), iterable, **kwargs)
|
|
1998
|
+
return {_coconut_}mapreduce(_coconut_lifted(False, _coconut_comma_op, (key_func, {_coconut_}ident if value_func is None else value_func), {empty_dict}), iterable, **kwargs)
|
|
1978
1999
|
collectby.using_processes = _coconut_partial(_coconut_parallel_mapreduce, collectby, process_map)
|
|
1979
2000
|
collectby.using_threads = _coconut_partial(_coconut_parallel_mapreduce, collectby, thread_map)
|
|
1980
2001
|
def _namedtuple_of(**kwargs):
|
|
@@ -639,7 +639,7 @@ force_verbose_logger = get_bool_env_var("COCONUT_FORCE_VERBOSE", False)
|
|
|
639
639
|
|
|
640
640
|
coconut_home = get_path_env_var(home_env_var, "~")
|
|
641
641
|
|
|
642
|
-
|
|
642
|
+
use_color_env_var = "COCONUT_USE_COLOR"
|
|
643
643
|
error_color_code = "31"
|
|
644
644
|
log_color_code = "93"
|
|
645
645
|
|
|
@@ -794,6 +794,7 @@ coconut_specific_builtins = (
|
|
|
794
794
|
"flip",
|
|
795
795
|
"const",
|
|
796
796
|
"lift",
|
|
797
|
+
"lift_apart",
|
|
797
798
|
"all_equal",
|
|
798
799
|
"collectby",
|
|
799
800
|
"mapreduce",
|
|
@@ -26,7 +26,7 @@ import sys as _coconut_sys
|
|
|
26
26
|
VERSION = "3.0.4"
|
|
27
27
|
VERSION_NAME = None
|
|
28
28
|
# False for release, int >= 1 for develop
|
|
29
|
-
DEVELOP =
|
|
29
|
+
DEVELOP = 8
|
|
30
30
|
ALPHA = False # for pre releases rather than post releases
|
|
31
31
|
|
|
32
32
|
assert DEVELOP is False or DEVELOP >= 1, "DEVELOP must be False or an int >= 1"
|
|
@@ -47,7 +47,8 @@ from coconut.constants import (
|
|
|
47
47
|
taberrfmt,
|
|
48
48
|
use_packrat_parser,
|
|
49
49
|
embed_on_internal_exc,
|
|
50
|
-
|
|
50
|
+
use_color_env_var,
|
|
51
|
+
get_bool_env_var,
|
|
51
52
|
error_color_code,
|
|
52
53
|
log_color_code,
|
|
53
54
|
ansii_escape,
|
|
@@ -209,6 +210,7 @@ class Logger(object):
|
|
|
209
210
|
@classmethod
|
|
210
211
|
def enable_colors(cls, file=None):
|
|
211
212
|
"""Attempt to enable CLI colors."""
|
|
213
|
+
use_color = get_bool_env_var(use_color_env_var)
|
|
212
214
|
if (
|
|
213
215
|
use_color is False
|
|
214
216
|
or use_color is None and file is not None and not isatty(file)
|
|
@@ -1029,7 +1029,7 @@ forward 2""") == 900
|
|
|
1029
1029
|
assert Phi((,), (.+1), (.-1)) <| 5 == (6, 4)
|
|
1030
1030
|
assert Psi((,), (.+1), 3) <| 4 == (4, 5)
|
|
1031
1031
|
assert D1((,), 0, 1, (.+1)) <| 1 == (0, 1, 2)
|
|
1032
|
-
assert D2((+), (.*2), 3, (.+1)) <| 4 == 11
|
|
1032
|
+
assert D2((+), (.*2), 3, (.+1)) <| 4 == 11 == D2_((+), (.*2), (.+1))(3, 4)
|
|
1033
1033
|
assert E((+), 10, (*), 2) <| 3 == 16
|
|
1034
1034
|
assert Phi1((,), (+), (*), 2) <| 3 == (5, 6)
|
|
1035
1035
|
assert BE((,), (+), 10, 2, (*), 2) <| 3 == (12, 6)
|
|
@@ -1075,6 +1075,8 @@ forward 2""") == 900
|
|
|
1075
1075
|
assert pickle_round_trip(.loc[0]) <| (loc=[10]) == 10
|
|
1076
1076
|
assert pickle_round_trip(.method(0)) <| (method=const 10) == 10
|
|
1077
1077
|
assert pickle_round_trip(.method(x=10)) <| (method=x -> x) == 10
|
|
1078
|
+
assert sq_and_t2p1(10) == (100, 21)
|
|
1079
|
+
assert first_false_and_last_true([3, 2, 1, 0, "11", "1", ""]) == (0, "1")
|
|
1078
1080
|
|
|
1079
1081
|
with process_map.multiple_sequential_calls(): # type: ignore
|
|
1080
1082
|
assert process_map(tuple <.. (|>)$(to_sort), qsorts) |> list == [to_sort |> sorted |> tuple] * len(qsorts)
|
|
@@ -1544,6 +1544,24 @@ def BE(f, g, x, y, h, z) = lift(f)(const(g x y), h$(z))
|
|
|
1544
1544
|
|
|
1545
1545
|
def on(b, u) = (,) ..> map$(u) ..*> b
|
|
1546
1546
|
|
|
1547
|
+
def D2_(f, g, h) = lift_apart(f)(g, h)
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
# branching
|
|
1551
|
+
branch = lift(,)
|
|
1552
|
+
branched = lift_apart(,)
|
|
1553
|
+
|
|
1554
|
+
sq_and_t2p1 = (
|
|
1555
|
+
branch(ident, (.*2))
|
|
1556
|
+
..*> branched((.**2), (.+1)) # type: ignore
|
|
1557
|
+
)
|
|
1558
|
+
|
|
1559
|
+
first_false_and_last_true = (
|
|
1560
|
+
lift(,)(ident, reversed)
|
|
1561
|
+
..*> lift_apart(,)(dropwhile$(bool), dropwhile$(not)) # type: ignore
|
|
1562
|
+
..*> lift_apart(,)(.$[0], .$[0]) # type: ignore
|
|
1563
|
+
)
|
|
1564
|
+
|
|
1547
1565
|
|
|
1548
1566
|
# maximum difference
|
|
1549
1567
|
def maxdiff1(ns) = (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/__coconut__/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__coconut__.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/__coconut__.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/__init__.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/__init__.pyi
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/cli.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/command.pyi
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/mypy.py
RENAMED
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/util.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/command/watch.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/__init__.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/compiler.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/matching.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/compiler/util.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/convenience.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/convenience.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/highlighter.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/__init__.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/embed.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/icoconut/root.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/integrations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/requirements.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/__init__.py
RENAMED
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/main_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coconut-develop-3.0.4.post0.dev7 → coconut-develop-3.0.4.post0.dev8}/coconut/tests/src/runner.coco
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|