These are chat archives for evhub/coconut

17th
Jan 2017
Eric Anderson
@Nexus6
Jan 17 2017 00:41
That's not a general solution though because it will first reverse the input_data tuple then filter it. Probably not what you had in mind.
Evan Hubinger
@evhub
Jan 17 2017 21:30
@plasmashadow I did some testing with it in Yelp's codebase while I was working there, and it worked pretty well.
@Nexus6 Compiler speed should be much better in the next release, which will be coming up very soon. As for maintenance, it's true that I'm currently the only major maintainer, but everything is open source and I'm planning on putting out a contribution guide with details on how the project is architected with the next release as well.
@Slepice1 The fact that reversed doesn't work on filter or map applied to a sequence in Python is a problem I would be willing to try and solve in Coconut's implementation of filter and map (in fact I think it already should work in Coconut for map). I'll raise an issue for it. In the meantime, I would recommend just doing reversed before filter (or map) instead of after.
Evan Hubinger
@evhub
Jan 17 2017 21:43
@Slepice1 Just opened #207. Should be able to get it done pretty quickly, and it should make it into the next release. In the meantime, you can just do filter then reversed like @Nexus6 and I said above (it shouldn't matter whether you reverse before or after, since filter (and map) don't care about order).
Eric Anderson
@Nexus6
Jan 17 2017 21:50
@evhub reversed() and len() want concrete sequences as parameters, but filter and reversed both return iterators IIRC. So you couldn't feed the filter() output into reversed() or the reversed() output into len(). Curious what the fix will be ...
Evan Hubinger
@evhub
Jan 17 2017 22:09
@Nexus6 Actually, Coconut already replaces the built-in Python map class to add support for operations such as indexing (__getitem__) and reversing (__reversed__), simply by not actually doing the operation. Instead, Coconut remembers that the operation needs to be done next time something is retrieved from the map, and does it then. In functional programming, this technique is called lazy evaluation. In fact, I just pushed a commit that should add similar support to filter as well. Unfortunately, the above example still won't work, since len can't be applied lazily to a filter, since unlike map, you can't infer what the length will be without doing any calculations. However, the specific error @Slepice1 was encountering, for doing reversed after filter, should disappear.
(Coconut also already does the same thing for zip.)
Eric Anderson
@Nexus6
Jan 17 2017 22:18
@evhub I understand lazy evaluation. Correct me if I'm wrong, but it doesn't seem that you can apply reversed() to a filter (or to any iterable) either. How would reversed() find the end of the iterator without fully evaluating it? So assuming filter returns an iterator, how will you make that acceptable as an input for reversed()? For example, how to get around reversed((x for x in [1,2,3])) throwing an error?
Evan Hubinger
@evhub
Jan 17 2017 22:20
@Nexus6 At some point, you need to bottom out in an actual sequence (tuple, list, or range), that's true. But you can stack an arbitrary number of map, filter, and zip operations on top of any sequence and you'll still be able to reverse it.
So, reversed((x for x in [1,2,3])) will still fail, but something like the example in #207 won't anymore.
(And the explanation of lazy evaluation, even if you already know it, is nice to have here in case anyone else reading over this who doesn't already know lazy evaluation wants to be able to understand as well.)
Evan Hubinger
@evhub
Jan 17 2017 22:26
@Slepice1 reversed should now work on filter in the latest coconut-develop, and will be released in the next version. In the meantime, just pip install coconut-develop.
Eric Anderson
@Nexus6
Jan 17 2017 22:29
@evhub Maybe I'm being a bit thick in the head today, but it your #207 example, are you saying you're going to fully iterate through the filter object returned from filter in order to come up with a concrete sequence to pass into reversed()? In the simple example I posted above, Python complains "TypeError: argument to reversed() must be a sequence" Sequence not iterator. @Slepice1 was having to convert the filter output into a tuple in order to make reversed() happy with it. Wouldn't your #207 example have to do the same?
Evan Hubinger
@evhub
Jan 17 2017 22:32
@Nexus6 The key is that I've changed filter so that instead of returning a plain iterator, it returns a more complex lazily-evaluated object with a __reversed__ method that just reverses the object that filter is filtering. That way, if the object you pass into filter supports reversed, then the object returned by filter does as well. You can see the actual code I added in this commit: evhub/coconut@9067feb
(Coconut's map and zip objects already worked this way, it just seems I forgot to do the same for filter until now.)
Eric Anderson
@Nexus6
Jan 17 2017 22:38
@evhub Oh, I see, you're going to return your own custom object, I wasn't following that. Is all reversed() complaining about then is that (in my example) it's not getting fed an object that has a reversed() function?
Evan Hubinger
@evhub
Jan 17 2017 22:40
@Nexus6 Yep, that's correct!
Eric Anderson
@Nexus6
Jan 17 2017 22:42
@evhub I didn't know that - didn't know that the input param was supposed to be able to reverse itself, I figured reversed() would do the heavy lifting.
Evan Hubinger
@evhub
Jan 17 2017 22:43
@Nexus6 Yup, that's how Python implements reversed. Sorry if I wasn't being clear about that!
Eric Anderson
@Nexus6
Jan 17 2017 22:47
@evhub While you're here I want to make a plea for #190 being a priority. I can imagine it will be a lot of work/tricky though. I've been meaning to suggest that, IMO, #201 ought to be a "won'tfix". The examples you posted are perfectly elegant ways to achieve the desired effect without overloading the pipe operator to mean more than taking data from the LHS and feeding it into a function on the RHS.
@evhub Re: reversed I should have known that about Python but didn't so wasn't following your prior explanation. My bad.
Evan Hubinger
@evhub
Jan 17 2017 23:36

@Nexus6 I agree #201 should probably be closed as a won't fix--I'll likely do that soon. #190 is definitely something I would like to implement, but it's true that it's going to be a lot of work. I'm also not yet entirely convinced that it would be superior to the alternative of using addpattern or return. For example, in #190 you provide the example of

def new_assign(foo) = 
    if foo == 0:
        "Zero"
    elif foo == 1:
        "One"
    else:
        "Dunno"

which can be rewritten using addpattern to be

def new_assign(0) = "Zero"

@addpattern(new_assign)
def new_assign(1) = "One"

@addpattern(new_assign)
def new_assign(foo) = "Dunno"