вс, 3 февр. 2019 г. в 21:23, David Mertz <mertz@gnosis.cx>:

I think the principled thing to do here is add the minimal number of methods to Vector itself, and have everything else pass through as vectorized calls.  Most of that minimal number are "magic method":  __len__(), __contains__(), __str__(), __repr__(), __iter__(), __reversed__().  I might have forgotten a couple.  All of those should not be called directly, normally, but act as magic for operators or built-in functions.

I think I should then create regular methods of the same name that perform the vectorized version.  So we would have:

len(v)   # -> 12
v.len()  # -> <Vector of [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]>
list(v)  # -> ["Jan", "Feb", "Mar", "Apr", "May", "Jul" ...]
v.list() # -> 
<Vector of [["J", "a", "n"], ["F", "e", "b"] ... >


Hi David! Thank you for taking the time to implement this idea. Sorry, I'm on a trip now and can't try it. From what I've read in this thread, I think I mostly agree with your perception how the vector should work: that `len(v)   # -> 12` and that `.some_method()` call must apply to elements (although pedants may argue that in this case there is not much difference). The only moment that I don’t like is `v.len(), v.list() and ...`, for the same reasons -  in general this will not work. I also don't like the option with `.apply` - what if `.apply` method is already defined for elements in a vector?
 
I can't implement every single constructor that users might conceivably want, of course, but I can do it for the basic types in builtins and common standard library.  E.g. I might do:

v.deque() # -> <Vector of [deque(["J", "a", "n"]), deque(["F", "e", "b"]) ... >

But I certainly won't manually add:

v.custom_linked_list()  # From my_inhouse_module.py

Hmm... maybe even I could look at names of maybe-constructors in the current namespace and try them.  That starts to feel too magic.  Falling back to this feels better:

map(custom_linked_list, v)  # From my_inhouse_module.py


Actually my thoughts on this. At first I thought that for these purposes it is possible to use __call__: 

len(v)   # -> 12
v(len)   # -> <Vector of [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]>

But it somehow this idea did not fit in my head. Then I found the next way and I think I even like it - to reuse the `__getitem__`, when its argument is a function it means that you apply this function to every element in the vector.

len(v)   # -> 12
v[len]   # -> <Vector of [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]>

In this case you can apply any function, even custom_linked_list from my_inhouse_module.py. From this stream I did not understand what desired behavior for unary operations like `vector + 1` and  the others. Also what is the desired behaviour for `vector[1:5]`? Considering the above, I would like to take this operation on the contrary:

>>> v
<Vector of ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']>
>>> v[1:]  
<Vector of ['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']>  
>>> v[i[1:]] # some helper class `i`
<Vector of ['an', 'eb', 'ar', 'pr', 'ay', 'un', 'ul', 'ug', 'ep', 'ct', 'ov', 'ec']>  

With kind regards,
-gdg