kachayev / fn.py Goto Github PK
View Code? Open in Web Editor NEWFunctional programming in Python: implementation of missing features to enjoy FP
License: Other
Functional programming in Python: implementation of missing features to enjoy FP
License: Other
"Return" misspelled as "rerurn" ar func.py, line 37.
It just doesn't work. It expects Iterable from collections but this is not available.
This log is from building python310Packages.fn
with nix but should be reproducible on any python 3.10 out there
Sourcing python-remove-tests-dir-hook
Sourcing python-catch-conflicts-hook.sh
Sourcing python-remove-bin-bytecode-hook.sh
Sourcing setuptools-build-hook
Using setuptoolsBuildPhase
Using setuptoolsShellHook
Sourcing pip-install-hook
Using pipInstallPhase
Sourcing python-imports-check-hook.sh
Using pythonImportsCheckPhase
Sourcing python-namespaces-hook
Sourcing setuptools-check-hook
Using setuptoolsCheckPhase
@nix { "action": "setPhase", "phase": "unpackPhase" }
unpacking sources
unpacking source archive /nix/store/bhfhqwy9y6x63h4dq2lpimzkl0b2b29i-fn-0.4.3.tar.gz
source root is fn-0.4.3
setting SOURCE_DATE_EPOCH to timestamp 1407495729 of file fn-0.4.3/setup.cfg
@nix { "action": "setPhase", "phase": "patchPhase" }
patching sources
@nix { "action": "setPhase", "phase": "configurePhase" }
configuring
no configure script, doing nothing
@nix { "action": "setPhase", "phase": "buildPhase" }
building
Executing setuptoolsBuildPhase
Traceback (most recent call last):
File "/build/fn-0.4.3/nix_run_setup", line 8, in <module>
exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
File "setup.py", line 6, in <module>
import fn
File "/build/fn-0.4.3/fn/__init__.py", line 1, in <module>
from .stream import Stream
File "/build/fn-0.4.3/fn/stream.py", line 9, in <module>
from .iters import map, range
File "/build/fn-0.4.3/fn/iters.py", line 2, in <module>
from collections import deque, Iterable
ImportError: cannot import name 'Iterable' from 'collections' (/nix/store/443qk9752l44kfp8pzsrp0m9jyq6jz2p-python3-3.10.3/lib/python3.10/collections/__init__.py)
Backlinks: NixOS/nixpkgs#167402
Similar to FingerTree.from_iterable.
I currently have an iterable_to_linkedlist function, but it would be easier if that feature was part of LinkedList.
def iterable_to_linkedlist(it):
''' iterable -> LinkedList
produces LinkedList with the contents of the consumed iterable
'''
return foldr(lambda x, y: y.cons(x), LinkedList())(tuple(it))
foldr so it preserves order, tuple(it) in case "it" is an iterator (otherwise the reversed() in foldr complains).
Suggestions for improved implementation? Otherwise I'm happy to make a pull-request.
Hi, interesting library!
Do you have a function to use-case reference?
Something similar to https://ramdajs.com/docs
Coming back to Python from javascript and it's a difficulty curve for new users if they have to dig through the source to find use cases.
If you don't have one, perhaps we could setup a Github action to generate the docs using pydoc or other, whenever a merge to master happens?
This would exclude strings as the implementation already does (so we don't yield each char of the string).
Hi, It's quite misleading that flatten does not ignore dictionaries.
For instance, the following snippet is not expected for most flatten arounds.
In: list(iters.flatten([{'a':1}]))
Out: ['a']
It seems more useful to have it return [{'a': 1}] in this case.
HAMT dicts have been implemented in Python, at least twice as far as I know:
https://github.com/jml/perfidy/tree/master/perfidy
https://github.com/alex/optimizer-model/blob/master/optimizer/utils/persistent_dict.py
so you may not have to implement it yourself to include them in fn.py (or at least not start from scratch).
The implementations are under the MIT and BSD licenses, respectively. The authors may be willing to relicense to ASL.
Looks like comments in code are missing.
Random strings in repr builder definitely was quick and dirty hack.
class F(object):
def __rshift__(self, g):
"""Overload << operator for F instances"""
return self.__class__.__compose(self.__ensure_callable(g), self.f)
def __lshift__(self, g):
"""Overload >> operator for F instances"""
return self.__class__.__compose(self.f, self.__ensure_callable(g))
the operator >>
is right shift and <<
is left shift respectively
I haven't found memoise
function implementation. I suggest to have at least two implementations with weakref and regular dictionary.
Hey, I get recursion errors on Python 2.7 while executing the following code:
list(flatten([ ['a', u'c'], ['a', 'b'] ]))
I think the issue is here (https://github.com/kachayev/fn.py/blob/master/fn/iters.py#L224), but as I couldn't take a deeper look at it yet, I'm just creating the issue to let you guys know.
I've try :
print math.sin(_)
it turn out to be wrong, but it works for:
lambda x: math.sin(x)
Does _ always be same as lambda caluse?
any limitation?
thx ~~
Easy to reproduce using fn.op.foldr
(cause it's initially flip given function in order to work with c-level reducing).
>>> from fn import _ as XXX
>>> from fn.op import flip, foldr
>>>
>>> flip(XXX + XXX)
getattr((_ + _), __flipback__)
>>>
>>> foldr(XXX + XXX)([1,2,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "fn/op.py", line 70, in fold
return iters.reduce(*args)
File "fn/underscore.py", line 85, in __call__
return self._callback(*args)
File "fn/func.py", line 51, in __call__
return self.f(*args, **kwargs)
File "fn/func.py", line 32, in <lambda>
return cls(lambda *args, **kwargs: f(g(*args, **kwargs)))
AttributeError: 'int' object has no attribute '__flipback__'
Hi!
I ran your example and got this:
In [1]: from fn.iters import map
In [2]: from fn import _
In [3]: list(map(_ * 2, range(5)))
Out[3]: [0, 2, 4, 6, 8]
In [4]: list(map(_ * 2, range(5)))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-448bfa47eeda> in <module>()
----> 1 list(map(_ * 2, range(5)))
TypeError: 'list' object is not callable
python 2.7.3 windows 7 x64
Currently, the test fails for PyPy as shown below.
======================================================================
FAIL: test_iterator (__main__.FingerTreeDequeTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 1083, in test_iterator
self.assertEqual([], list(Deque()))
AssertionError: Lists differ: [] != [<function <lambda> at 0x00007...
Second list contains 1 additional elements.
First extra element 0:
<function <lambda> at 0x00007fe2f940b9e8>
- []
+ [<function <lambda> at 0x00007fe2f940b9e8>]
----------------------------------------------------------------------
Ran 123 tests in 1.195s
FAILED (failures=1)
nested options can arise in reasonable APIs.
Collapsing options can be done with a separately defined join
operation.
Implement every
and some
in fn.iters
that are influenced by Clojure's every?
and some
respectively.
to use _ in functions. wait is a class with gt,or use some other name/operator.
from fn.func import curried
@curried
def sum5(a, b, c, d, e):
return a + b + c + d +e
sum5(1)(2)(3)(4)(5)
Out[6]: 15
@curried
def sum5(a: int, b: int, c: int, d: int, e: int):
return a + b + c + d +e
sum5(1)(2)(3)(4)(5)
Traceback (most recent call last):
File "/home/sphelps/mambaforge/envs/symbiotica-fund/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3505, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-8-e80b0556d52b>", line 1, in <module>
sum5(1)(2)(3)(4)(5)
File "/home/sphelps/mambaforge/envs/symbiotica-fund/lib/python3.10/site-packages/fn/func.py", line 78, in _curried
spec = getargspec(f)
File "/home/sphelps/mambaforge/envs/symbiotica-fund/lib/python3.10/inspect.py", line 1237, in getargspec
raise ValueError("Function has keyword-only parameters or annotations"
ValueError: Function has keyword-only parameters or annotations, use inspect.signature() API which can support them
I often find myself in the situation where I want to create a filter and, if using the underscore syntax, _
is a sequence. For instance:
my_filter = F() >> (filter, _[1] in TYPE_MAP)
In this situation, _
will be an item from a dict.items()
and will, therefore, be a 2-tuple. I want my_filter
to return only the items for which the value (the second item in the 2-tuple) is in TYPE_MAP
.
However, when run, the above code results in TypeError: "'bool' object is not callable"
. It looks as if it's trying to evaluate _[1] in TYPE_MAP
at the time of partial function creation, rather than when actually calling the resulting function.
Is there a way to achieve this with the underscore syntax, or do I just have to use the lambda
syntax?
Thanks
Otherwise pylint complains (fairly) that Option does not have, for example, "map".
Just add these lines at monad.py:72
def map(self, callback):
raise NotImplementedError()
def filter(self, callback):
raise NotImplementedError()
def get_or(self, default):
raise NotImplementedError()
def get_or_call(self, callback, *args, **kwargs):
raise NotImplementedError()
def or_else(self, default):
raise NotImplementedError()
def or_call(self, callback, *args, **kwargs):
raise NotImplementedError()
This is a pretty minor issue and somewhat stylistic, so feel free to ignore :) Thanks for the nice library!
There is a small typo in fn/immutable/heap.py.
Should read pairing
rather than pairingi
.
op.py: def curry(f, arg, *rest):
Is it more appropriate to call it uncurry
?
I want use fn._ in a spark program. e.g.
num = rdd.filter('00:00:00' <= _[0] <= '12:00:00')
but I got serialize error, can any one give me some advice to solve this problem.
As per http://legacy.python.org/dev/peps/pep-0008. Just to make the codebase look more organised and consistent.
I'm not sure how mature packages like 'autopep8' are at present, but worth having a look if we are going with this. There is no harm doing it manually though. Optionally, we can also add 'flake8' testing to CI for future commits.
What are your thoughts on this, @kachayev?
Has anyone considered starting an active fork of this repo? I see it has been forked a number of times, but no forks are being actively maintained.
I don't feel qualified to maintain a project like this, but it is such a great library I don't want it to die! If no one else steps up within a month I'll create a fork and pledge to provide active updates. The fork will have to be deployed on PyPi as well.
Often, when I chain functions, I find myself using the following pattern:
(F() >> foo >> bar >> baz)(x)
If this were clojure, I could write:
(-> x foo bar baz)
Notice the input on the left. Is there any to way to do this in python/fn?
Hi,
I'm not sure whether this is supposed to work:
from fn import _ as X
X.endswith('tif')('image.tif')
This prints "False".
Looking at the tests I see this form:
from fn import _ as X
X.call('endswith', '.tif')('image.tif')
This correctly evaluates to True, but is significantly uglier. What's happening in the first form?
I.e.
>>> print (_ * 2)
"(x1) => x1 * 2"
>>> print (_ + _)
"(x1, x2) => x1 + x2"
I tried this code for function currying
from fn.func import curried
@curried
def sum5(a, b, c, d, e):
return a + b + c + d + e
sum5(1)(2)(3)(4)(5)
15
sum5(1, 2, 3)(4, 5)
15
but when I call the function I get the following error
Traceback (most recent call last):
File "", line 1, in
File "fn/func.py", line 83, in _curried
return curried(partial(func, _args, *_kwargs))
File "fn/func.py", line 69, in curried
@wraps(func)
File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'functools.partial' object has no attribute 'module'
Special @composable
decorator to bring new functionality to function:
I want to add foldl and foldr tomorrow, but I feel like this needs some discussion. CPython's builtin reduce() is a left-fold. Can/should we rely on this or should it be replaced with a custom left-fold implementation? reduce() should be faster, but the actual result of it is up to the implementation if I understand correctly.
There is an interesting implementation of tail-call optimisation decorator, which could be provided as an alternative to fn.recur.tco
:
http://code.activestate.com/recipes/474088-tail-call-optimization-decorator/
It allows for more readable code, but has a speed penalty because it is implemented by raising exception on each recursion.
Could fn.py do something like this functional concatenation?
def f1(a):
return a
def f2(b):
return b
def f3(a, b):
return a+b
([f1, f2] >> f3) (3, 2) = 5
map('%d' % _, range(10))
TypeError: %d format: a number is required, not _Callable
Currently, the test fails for Python 3.x due to reduce
not being defined.
======================================================================
ERROR: test_iterator (__main__.FingerTreeDequeTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 1086, in test_iterator
self.assertEqual(sum(range(1,20)), sum(Deque.from_iterable(range(1,20))))
File "/home/microamp/devel/projs/fn.py/fn/immutable/finger.py", line 138, in from_iterable
return FingerTree.from_iterable(lambda x: x, it)
File "/home/microamp/devel/projs/fn.py/fn/immutable/finger.py", line 122, in from_iterable
return reduce(lambda acc, curr: acc.push_front(curr), it, tree)
NameError: global name 'reduce' is not defined
----------------------------------------------------------------------
Ran 123 tests in 0.110s
FAILED (errors=1)
@tail_call_optimized
def even(x):
if x == 0: return True
return odd(x-1)
@tail_call_optimized
def odd(x):
if x == 0: return False
return even(x-1)
print even(100000)
can recur.tco resolve rock tail recursion?
>>> from fn import _ as XXX
>>> from fn.op import flip
>>> print flip(XXX + XXX)
(x1, x2, x3, x4, x5, x6) => getattr((x1 + x2), x3x4flipbackx5x6)
Will there by a version of map
/filter
/reduce
for returning persistent (and hopefully lazy) data structures?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.