Skip to content

Commit

Permalink
Improved documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
dwt committed Mar 4, 2021
1 parent 3c09e8b commit cc1c8c5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
20 changes: 19 additions & 1 deletion Todo.md
@@ -1,16 +1,34 @@
# Before next release

* look at https://toolz.readthedocs.io/en/latest/ as it seems to do similar thinigs to what I do
* travis and backport to pythons it's easy to backport
* 3.5 would be possible if I can go without f-strings (possible) and without the ordered dict on curry (or maybe without overpowered curry)

* integrate introspection methods better CallableWrapper.signature(), ...
* would really like to have a helper that gives me the type structure of someting, to make it easier to reason about
* i.e. {0: [[func1, func2], [func1,funce]]} -> dict[int, list[list[function]]]

* would be cool to have a way to get from _.each to _(_.each) to be able to chain from there. Not sure how that would / should be terminated though.
* Simplify curry, so it mostly only does what functools.partial does, and factor out the wild reordering stuff into it's own method `.adapt_signature` or something similar.
* Simplify curry, so it mostly only does what functools.partial does, and factor out the wild reordering stuff into it's own method `.adapt_signature` or something similar. This should also simplify / allow porting to python 3.5
* Ideally, curry will return a new wrapping function that knows what it wraps and still has most of the metadata
* consider to split curry into a straight functools.partial port and a more sophisticated curry / signature_adapter. Maybe foregoing too complicated signature adaption by just using a lambda for complicated adaptions. Not sure how to best express that fluently though

* consider if there is a way to make it easier to debug that you forgot to terminate an _.each expression before handing it of to one of the wrapped iteration methods

* consider to have something on _.each that allows to turn it into a Wrapper to chain off of (as this would allow to use .call() to call it as the argument of something)

# Bunch of Ideas

get mybinder tutorial going so users can more easily explore fluentpy

No problem. If you are curious about Spark, the high-level idea is that if you have a lot of data, you want to break your problem across multiple machines to speed up computation. I used Spark as an example as that's one of the most popular distributed computing frameworks. On a day to day basis, I actually use Apache Dask, which is basically the same thing as Spark. Both Spark and Dask are lazy (like a generator). I looked at the source code of FluentPy, and it seems some parts of lazy (ie uses yield) and some parts are eager (ie uses return). If you are curious, take a look at this Dask syntax. It looks very similar to fluentpy: https://github.com/dask/dask-tutorial/blob/master/02_bag.ipynb In Dask, all the transformations (map/filter/reduce/etc) are lazy until you use .compute(), which triggers actual computation. Also here's a neat tool: https://mybinder.org/ Mybinder gives you a Jupyter notebook to run in your browser for free--behind the scenes, it's just a container that clones a repo and installs the library. Hence, you can run the Dask tutorial by going to https://mybinder.org/v2/gh/dask/dask-tutorial/HEAD If you want, you can consider adding a tutorial notebook in your fluentpy repo, so then users can simply go to https://mybinder.org/v2/gh/dwt/fluent/HEAD to run the code all through the browser. I think the fluent interface is a very cool thing that most Python programmers are not aware about, so when I show them for the first time, they are amazed! I remember when I first saw it in Java (and it was just a quick screenshot since I actually don't program in Java), I was thinking, wow this is amazing. Hope that helps, Eugene

allow each._ or something similar to continue with a wrapped version of each

There should be a way to wrap and unwrap an object when chaining off of _.each

There should be a way to express negation when chaining off of _.each

can I have an `.assign(something)` method that treats self as an lvalue and assigns to it?

`python -m fluentpy` could invoke a repl with fluentpy premported?
Expand Down
4 changes: 3 additions & 1 deletion fluentpy/__main__.py
@@ -1,7 +1,9 @@
import sys
from fluentpy import wrap
assert len(sys.argv) == 2, \
"Usage: python -m fluentpy 'some code that can access fluent functions without having to import them'"
"""\
Usage: python -m fluentpy 'some code that can access fluent functions without having to import them'
See documentation section 'Easy Shell Filtering with Python' for inspiration."""

# __wrapper_is_sealed = True
exec(sys.argv[1], vars(wrap))
17 changes: 14 additions & 3 deletions fluentpy/wrapper.py
Expand Up @@ -250,6 +250,17 @@ def call(self, function, *args, **kwargs):
>>> _('foo').call(list)._ == list('foo')
>>> _('fnord').call(textwrap.indent, prefix=' ')._ == textwrap.indent('fnord', prefix=' ')
This also allows to quickly insert a normal method into a call chain like this, if you need
to express a multi line computation as statements.
>>> numbers = _(range(5))
>>> @numbers.call
>>> def items(numbers):
>>> for it in numbers:
>>> yield it
>>> yield it
>>> items.call(list).print()
Note the difference from ``.__call__()``. This applies ``function(self, …)`` instead of ``self(…)``.
"""
return function(self, *args, **kwargs)
Expand Down Expand Up @@ -318,8 +329,8 @@ def reload(self):
Is equivalent to
>>> import importlib
>>> wrap(importlib.import_module('sys').stdin).read().map(print)
>>> import sys
>>> wrap(sys).stdin.read().map(print)
But of course without creating the intermediate symbol 'stdin' in the current namespace.
Expand Down Expand Up @@ -358,7 +369,7 @@ def curry(self, *default_args, **default_kwargs):
There is also ``_._args`` which is the placeholder for the ``*args`` variable argument list specifier.
(Note that it is only supported in the last position of the positional argument list.)
>>> _(operator.add).curry(_.args)('foo', 'bar)._ == 'foobar'
>>> _(lambda x: x[0] + x[1]).curry(_.args)('foo', 'bar)._ == 'foobar'
"""
# REFACT consider, would it be easier to actually generate a wrapper function that has an argspec
# according to the given spec?
Expand Down

0 comments on commit cc1c8c5

Please sign in to comment.