On Sun, May 24, 2020 at 6:56 PM David Mertz <me...@gnosis.cx> wrote:

> On Sun, May 24, 2020 at 11:21 AM Steven D'Aprano <st...@pearwood.info>
> wrote:
>
>> > But how would you go about getting a .__matmul__ attribute onto all
>> > functions. For ones you write yourselves, you could decorate them at
>> > definition. What about all the other functions though.
>>
>> As a functional programming fan, you might not know about this, but we
>> object oriented programming people have this concept called
>> "inheritance" where we would add the attribute to FunctionType once, and
>> just like magic every function would support it!
>>
>
> I think I heard of that inheritance thing somewhere! :-)
>
> My thought is really that there's no way we're going to get .__matmul__
> added (with the meaning "compose") to FunctionType.  So I was thinking
> about what one could do with a separate module.  I.e. something that could
> live on PyPI... before, perhaps someday, being added to standard library.
>
> Is there an evil way to monkey patch FunctionType? I.e. without actually
> recompiling a fork of the interpreter.  Alex' forbiddenfruit.curse is
> pretty cool looking.  But it does require explicitly cursing each
> individual function that might be composed.
>

forbiddenfruit patches the type, look again. I used a loop because there
isn't just one FunctionType: `type(compose) != type(len)`.


> Alex Hall:
>
>> But seriously, I don't see that much point to this idea. It's just
>> slightly more concise while not being particularly readable or beginner
>> friendly.
>>
>> sorted(paths, key=len @ str)
>> sorted(paths, key=lambda p: len(str(p)))
>>
>
> I think once you compose three or more functions, lambda starts to look
> pretty bad.
>

It does? How? It sounds like the problem isn't the syntax for lambda, but
just function composition in general, maybe because of too many
parentheses. Maybe you'd like to change:

    foo = bar(len(str(path)))

into

    foo = (bar @ len @ str)(path)

In any case, it's rare to be able to simply compose three unary functions,
e.g. `sorted(paths, key=bar @ len @ str)`. Usually you need to do something
slightly more complicated, e.g. a second argument somewhere, and if you
throw in functools.partial I think that's easily worse.


> This is only slightly mitigated by one of those proposals for "a more
> concise lambda" that occur intermittently. And if you actually save a
> composed function under a meaningful name for later use, that much more so.
>

Why is:

    my_op = bar @ len @ str

even more of an improvement over:

    my_op = lambda p: bar(len(str(p)))

than @ is an improvement in the previous examples? If the answer is that
you're not supposed to assign lambdas, I think the same logic should
dictate not assigning compositions.

In fact, the reason to not assign lambdas is for better tracebacks, and now
that I think of it, function composition would completely destroy
tracebacks. For example:

```
for function in [
lambda p: str(len(p)),
str @ len,
]:
try:
function(3)
except:
traceback.print_exc()

```

Output:

```
Traceback (most recent call last):
  File "main.py", line 15, in <module>
    function(3)
  File "main.py", line 11, in <lambda>
    lambda p: str(len(p)),
TypeError: object of type 'int' has no len()
Traceback (most recent call last):
  File "main.py", line 15, in <module>
    function(3)
  File "main.py", line 5, in <lambda>
    return lambda *args, **kwargs: self(other(*args, **kwargs))
TypeError: object of type 'int' has no len()
```

https://repl.it/@alexmojaki/LeanEnergeticPublisher-1

So based on that I'm strongly against this kind of proposal without
syntactic support.

I've been playing more lately with R Tidyverse.  It's pipe with currying of
> first argument is actually really nice.  The pipe operator is god-awful
> ugly.  But other than that it works nicely.  For example:
>
> iris %>%  group_by(Species) %>%  summarize_if(is.numeric, mean) %>%  
> ungroup() %>%  gather(measure, value, -Species) %>%  arrange(value)
>
>
> It's not abstract composition since it always starts with a concrete
> object the several operations work on.  But it is some of the same feel.
>

https://github.com/0101/pipetools
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JURJ5YTZ2ESEBVZYNNJ4RDSCEMH5RPB3/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to