https://github.com/kachayev/fn.py/blob/master/README.rst#scala-style-lambdas-definition
On Monday, August 21, 2017, Chris Barker <[email protected]> wrote: > > > On Sat, Aug 19, 2017 at 3:34 AM, ?? ? <[email protected] > <javascript:_e(%7B%7D,'cvml','[email protected]');>> wrote: > >> Could you please think this way to define a variable: >> >> >> var = expr() -> g1(_) if f(_) else g2(_) >> >> which equals >> >> >> test = f(expr()) >> >> var = g1(test) if f(test) else g2(test) >> > > OK, I do see this as a nice way to avoid as many "temp" variables, though > in this example, I am confused: > > in the above version, It seems to me that the equivelent wordy version is: > > temp = expr() > var = g1(temp) if f(temp) else g(temp) > > rather than the f(expr()) -- i.e. you seem to have called f() on expr and > extra time? Maybe just a typo. > > or, of course: > > var = g1(expr()) if f(expr()) else g(expr()) > > which I can see would be bad if expr() is expensive (or even worse, has > side effects) > > so I'm coming around this this, though you could currently write that as: > > _ = expr(); g1(_) if f(_) else g(_) > > not that different! > > Also, there is something to be said for giving a name to expr() -- it may > make the code more readable. > > > In another words,I can clearly state what I mean to say in order of my >> thinking. >> > > well, in the above case, particularly if you use a meaningful name, rather > than "temp" or "test", then you are still writing in in the order of > meaning. > > (though elsewhere in this thread there are better examples of how the > current nested function call syntax does reverse the logical order of > operations) > > >> For example, >> >> >> lambda x: f(g(x)) -> map(_, range(100)) >> >> The codes above means that I'm stressing on what(an action) I'm going to >> do on an object "range(100)". >> > > This is still putting the range(100) at the end of the expression, rather > than making it clear that you are starting with it. > > and putting that much logic in a lambda can be confusing -- in fact, I'm > still not sure what that does! (I guess I am still not sure of the order of > operations is the lambda expression (f(g(x))) or the whole thing? if not > the whole thing, then: > > is it the same as ?: > > (f(g(x)) for x in range(100)) > > I'm also seeing a nested function there -- f(g(x)) which is what I > thought you were trying to avoid -- maybe: > > lambda x: (g(x) -> f(_)) -> map(_, range(100)) > > ??? > > In general, much of this seems to be trying to make map cleaner or more > clear -- but python has comprehensions, which so far work better, and are > more compact and clear for the examples you have provided. > > granted, deeply nested comprehensions can be pretty ugly -- maybe this > will be clearer for those?? > > > However, sometimes the actions are not important, so if we want to stress >> on what we're going to do something on, we write this codes: >> >> >> range(100) -> map( lambda x:f(g(x)), _ ) >> > > OK, so THAT makes more sense to me -- start with the "source data", then > go to the action on it. > > but again, is that really clearer than the comprehension (generator > expression - why don't we call that a generator comprehension?): > > (f(g(x)) for x in range(100)) > > maybe this would be better: > > range(100) -> (f(g(x)) for x in _) > > it does put the source data up front -- and could be nicer for nested > comprehensions. > > Hmm, maybe this is an example of the kind of thing I've needed to do is > illustrative: > > > [s.upper() for s in > (s.replace('"','') for s in > (s.strip() for s in > line.split()))] > > would be better as: > > line.split() -> (s.strip() for s in _) -> (s.replace('"','') for s in _) > -> [s.upper() for s in _] > > though, actually, really best as: > > [s.strip().replace('"','').upper() for s in line.split()] > > (which only works for methods, not general functions) > > but for functions: > > [fun3(fun2(fun1(x))) for x in an_iterable] > > > so, backwards logic, but that's it for the benefit. > > So still having a hard time comeing up with an example that's notable > better... > > >> someone -> dosomething( _, options=options) \ >> -> is_meeting_some_conditions( _ ) \ >> -> result1() if _ else result2() where: >> options = ... >> result1 = lambda: ... >> result2 = lambda: ... >> def dosomething(obj, options) -> Any: >> ... >> >> def is_meeting_some_conditions( event : Any ) -> bool : >> ... >> > > again with the lambdas -- this is all making me think that this is about > making Python a better functional language, which I'm not sure is a goal of > Python... > > but anyway, the real extra there is the where: clause > > But that seems to be doing the opposite -- putting the definitions of what > you are actually doing AFTER the logic> > > I'm going to chain all this logic together > and by the way, this is what that logic is... > > If we really wanted to have a kind of context like that, maybe something > more like a context manager on the fly: > > with: > options = ... > result1 = lambda: ... > result2 = lambda: ... > def dosomething(obj, options) -> Any: > ... > > def is_meeting_some_conditions( event : Any ) -> bool : > ... > do: > (result1() if is_meeting_some_conditions( > dosomething( someone, options=options)) > else result2() > > > Also, we need to remember that functions can take *args, **kwargs, etc, >> > and can return a tuple of just about anything -- not sure how well that >> > maps to the "pipe" model. >> >> I think that using "pipe" model cannot be the right choice. >> >> We don't need to worry about this problem if we use the grammar I've >> implemented yet :) >> >> >> (lambda x: (x%5, x) ) -> max( range(99), key = _) >> >> 94 >> >> >> def max_from_seq(*args): return max(args) >> >> [1,2,3] -> max_from_seq(*_) >> >> 3 >> > > this gets uglier if we have both *args and **kwargs..... > > Which maybe is OK -- don't use it with complex structures like that. > > For example, sometimes we just need to know that surface area of a >> cylinder is >> >> 2*S_top + S_side >> >> If someone see the codes, he may not need to know how S_top and S_side >> are evaluated,getting >> a knowledge of what it means to is enough. >> And if you want to get more about how to evaluate S_side and S_top, just >> see >> the next "where syntax" and find the answers. >> > > how is that clearer than: > > S_topo = something > S_side = something else > surface_area = 2*S_top + S_side > > ??? > (Or, of course, defining a function) > > Sure, we see the: some expression..."where" some definitions structure a > lot in technical papers, but frankly: > > I'd probably rather see the definitions first > > and/or > > the definitions are often only there to support you if you don't already > know the nomenclature -- when you go back to read the paper again, you may > not need the where. Coding is different, I'd rather see stuff defined > BEFORE it is used. > > > >> Here is an example to use flowpython, which gives the permutations of a >> sequence. >> >> >> >> from copy import deepcopy >> >> permutations = .seq -> seq_seq where: >> >> condic+[] seq: >> >> case (a, ) => seq_seq = [a,] >> >> case (a, b) => seq_seq = [[a,b],[b,a]] >> >> case (a,*b) => >> >> seq_seq = permutations(b) -> map(.x -> insertAll(x, >> a), _) -> sum(_, []) where: >> >> insertAll = . x, a -> ret where: >> >> ret = [ deepcopy(x) -> _.insert(i, a) or _ >> for i in (len(x) -> range(_+1)) ] >> >> > I find that almost unreadable. >> > > me too. > > >> Too many new features all at once, it's >> > like trying to read a completely unfamiliar language. >> > > exactly -- this seems to be an effort to make Python a different language! > > This algorithm can be fixed a little because the second case is redundant. >> And here is the regular Python codes transformed >> from the codes above. >> > > looks like we lost indenting, so I'm going to try to fix that: > > from copy import deepcopy > > def permutations(seq): > try: > # the first case > (a, ) = seq > return [a ,] > except: > try: > # the third case (the second case is redundant) > def insertAll(x, a): > # insertAll([1,2,3], 0) -> [[0, 1, 2, 3], [1, 0, 2, 3], > [1, 2, 0, 3], [1, 2, 3, 0]] > ret = [] > for i in range( len(x) + 1 ): > tmp = deepcopy(x) > tmp.insert(i, a) > ret.append(tmp) > return ret > > (a, *b) = seq > tmp = permutations(b) > tmp = map(lambda x : insertAll(x, a) , tmp) > > return sum(tmp, []) # sum([[1,2,3], [-1,-2,-3]], []) -> > [1,2,3,-1,-2,-3] > except: > # no otherwise! > pass > > Have I got that right? but anyway, there has GOT to be a more pythonic way > to write that! And I say that because this feels to me like trying to write > functional code in Python in an unnatural-for-python way, then saying we > need to add features to python to make that natural. > > SoL I think the challenge is: > > find some nice compeling examples > write them in a nice pythonic way > show us that that these new features would allow a cleaner, more readable > solution. > > Steven did have a nice example of that: > > result = (myfile.readlines() > -> map(str.strip) > -> filter( lambda s: not s.startwith('#') ) > -> sorted > -> collapse # collapse runs of identical lines > -> extract_dates > -> map(date_to_seconds) > -> min > ) > > Though IIUC, the proposal would make that: > > result = (myfile.readlines() > -> map(str.strip, _) > -> filter( lambda s: not s.startwith('#'), _ ) > -> sorted( _ ) > -> collapse( _ ) # collapse runs of identical lines > -> extract_dates( _ ) > -> map(date_to_seconds, _) > -> min(_) > ) > > > The current Python for that might be: > > result = min((date_to_seconds(d) for d in > extract_dates( > collapse( > sorted([s for s in > (s.strip() for line in myfile.readlines) > if not s.startswith] > ))))) > > Which really does make the point that nesting comprehension gets ugly fast! > > So "don't do that": > > lines = collapse(sorted((l.strip().split("#")[0] for l in > myfile.readlines()))) > dates = min((date_to_seconds(extract_date(l)) for l in lines)) > > or any number of other ways -- clearer, less clear?? > > -CHB > > -- > > Christopher Barker, Ph.D. > Oceanographer > > Emergency Response Division > NOAA/NOS/OR&R (206) 526-6959 voice > 7600 Sand Point Way NE (206) 526-6329 fax > Seattle, WA 98115 (206) 526-6317 main reception > > [email protected] > <javascript:_e(%7B%7D,'cvml','[email protected]');> >
_______________________________________________ Python-ideas mailing list [email protected] https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
