<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Fri, Feb 1, 2019 at 5:00 PM David Mertz <<a href="mailto:mertz@gnosis.cx">mertz@gnosis.cx</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div class="gmail_quote" dir="auto"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div>is is certainly doable. But why would it be better than:<br></div></div></div></blockquote></div><div dir="auto"><br></div><div dir="auto">map(str.lower, my_string_vector)</div><div dir="auto">map(compute_grad, my_student_vector)</div></div></blockquote><div><br></div><div>or [s.lower() for s in my_string_vector]</div><div><br></div><div>Side note: It's really interesting to me that Python introduced comprehension sytax some years ago, and even "hid" reduce(), and now there seems to be a big interest / revival of "map".</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Even numpy supports inhomogeneous data:<br>py> a = np.array([1, 'spam'])<br>py> a<br>array(['1', 'spam'],<br>      dtype='|S4')</blockquote><div><br></div><div>well, no -- it doesn't -- look carefully, that is an array or type '!S4' -- i,e, a 4 element long string --every element in that array is that same type. Also note that numpy's support for strings a not very complete.</div><div><br></div><div>numpy does support an "object" type, that can be inhomogeneous -- it's still a single type, but that type is a python object (under the hood it's an array fo pointers to pyobjects):</div><div><br></div><div><div>In [3]: a = np.array([1, 'spam'], dtype=np.object)                              </div><div>In [4]: a                                                                       <br></div><div>Out[4]: array([1, 'spam'], dtype=object)</div></div><div><br></div><div>And it does support vectorization to some extent:</div><div>In  [5]: a * 5                                                                   <br>Out [5]: array([5, 'spamspamspamspamspam'], dtype=object)<br></div><div><br></div><div>But not with any performance benefits.</div><div><br></div><div>I think there are good reasons to have a "string_vector" that is known to be homogenous:</div><div><br></div><div>Performance -- it could be significantly optimized (are there many use cases for that? I don't know.</div><div><br></div><div>Clear API: a string_vector would have all the relevant string methods. </div><div><br></div><div>You could easily write a list subclass that passed on method calls to the enclosed objects, but then you'd have a fair bit of confusion as to what might be a vector method vs a method on the objects.</div><div><br></div><div>which I suppose leaves us with something like:</div><div><br></div><div>list.elements.upper()</div><div><br></div><div>list.elements * 5</div><div><br></div><div>hmm -- not sure how much I like this, but it's pretty doable.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I still haven't seen any examples that aren't already spelled 'map(fun, it)'</blockquote><div><br></div><div>and I don't think you will -- I *think* get credit for starting this part of the the thread, and I started by saying I have often longed for essentially a more concise way to spell map() or comprehensions. performance asside, I use numpy because:</div><div><br></div><div>c = np.sqrt(a**2 + b**2)</div><div><br></div><div>is a heck of a lot easer to read, write, and get correct than:</div><div><br></div><div><div><font face="monospace, monospace">c = list(map(math.sqrt, map(lambda x, y: x + y, map(lambda x: x**2, a),</font></div><div><font face="monospace, monospace">                                                map(lambda x: x**2, b)</font></div><div><font face="monospace, monospace">                              )))</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">or:</font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">[math.sqrt(x) for x in (a + b for a, b in zip((x**2 for x in a),</font></div><div><font face="monospace, monospace">                                              (x**2 for x in b)</font></div><div><font face="monospace, monospace">                                              ))]</font></div></div></div><div><br></div><div>Note: it took me quite a while to get those right! (and I know I could have used the operator module to get the map version maybe a bit cleaner, but the point stands)</div><div><br></div><div>Does this apply to string processing? I'm not sure, though I do a fair bit of chaining of string operations:</div><div><br></div><div>my_string.strip().lower().title()</div><div><br></div><div>if you wanted to do that to a list of strings:</div><div><br></div><div>a_list_of_strings.strip().lower().title()</div><div><br></div><div>is a lot nicer than:</div><div><br></div><div>[s.title() for s in (s.lower() for s in [s.strip(s) for s in a_list_of_strings])]</div><div><br></div><div>or </div><div><br></div><div>list(map(str.title, (map(str.lower, (map(str.strip, a_list_of_strings)))) # untested</div><div><br></div><div>How common is that use case? not common enough for me to go any further with this.</div><div><br></div><div>-CHB</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>-CHB<br></div><div><br></div><div><br></div><div><br></div><div>-- <br></div></div><div dir="ltr" class="gmail_signature">Christopher Barker, PhD<br><br> Python Language Consulting<br>  - Teaching<br>  - Scientific Software Development<br>  - Desktop GUI and Web Development<br>  - wxPython, numpy, scipy, Cython<br></div></div></div></div></div></div>