[Python-ideas] (no subject)
Ron Adam
ron3200 at gmail.com
Fri May 8 18:05:54 CEST 2015
On 05/08/2015 01:19 AM, Rustom Mody wrote:
> On Wed, May 6, 2015 at 6:45 PM, Ivan Levkivskyi
> <levkivskyi at gmail.com
> <mailto:levkivskyi at gmail.com>> wrote:
>
> Dear all,
>
> The matrix multiplication operator @ is going to be introduced in
> Python 3.5 and I am thinking about the following idea:
>
> The semantics of matrix multiplication is the composition of the
> corresponding linear transformations.
> A linear transformation is a particular example of a more general
> concept - functions.
> The latter are frequently composed with ("wrap") each other. For example:
>
> plot(real(sqrt(data)))
>
> However, it is not very readable in case of many wrapping layers.
> Therefore, it could be useful to employ
> the matrix multiplication operator @ for indication of function
> composition. This could be done by such (simplified) decorator:
>
> class composable:
>
> def __init__(self, func):
> self.func = func
>
> def __call__(self, arg):
> return self.func(arg)
>
> def __matmul__(self, other):
> def composition(*args, **kwargs):
> return self.func(other(*args, **kwargs))
> return composable(composition)
>
> I think using such decorator with functions that are going to be deeply
> wrapped
> could improve readability.
> You could compare (note that only the outermost function should be
> decorated):
>
> plot(sorted(sqrt(real(data_array)))) vs. (plot @ sorted @ sqrt @ real)
> (data_array)
>
> I think the latter is more readable, also compare
>
> def sunique(lst):
> return sorted(list(set(lst)))
>
> vs.
>
> sunique = sorted @ list @ set
>
>
> I would like to suggest that if composition is in fact added to python its
> order is 'corrected'
> ie in math there are two alternative definitions of composition
>
> [1] f o g = λ x • g(f(x))
> [2] f o g = λ x • f(g(x))
>
> [2] is more common but [1] is also used
>
> And IMHO [1] is much better for left-to-right reading so your example becomes
> sunique = set @ list @ sorted
> which reads as smoothly as a classic Unix pipeline:
>
> "Unnamed parameter input to set; output inputted to list; output inputted
> to sort"
Here's how I would do it as a function.
>>> def apply(data, *fns):
... for f in fns:
... data = f(data)
... return data
...
>>> apply((8, 9, 8, 4, 5), set, list, sorted)
[4, 5, 8, 9]
This is a variation of reduce except, it's applying many functions to a
single data item rather than applying a single function to many data items.
result = apply(data, f, g, e)
Which would be the same as...
result = e(g(f(data)))
Having the order be in alignment with object methods calls is a consistency
which can help with learning how to use it.
I don't think special syntax has an advantage over a function for this. It
may even be a disadvantage. The problem with special syntax is it can't be
represented as data easily. That would be counter to a functional style of
programming, which seems at odds with the desired feature. (IMO)
fns = (set, list, sorted)
result = apply(data, *fns)
Also having this right next to reduce in functools would work nicely, both
for usability and documentation.
Cheers,
Ron
More information about the Python-ideas
mailing list