[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