Author hynek
Recipients hynek, lukasz.langa, ncoghlan, rhettinger
Date 2013-08-04.10:08:53
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1375610934.97.0.503658757825.issue18652@psf.upfronthosting.co.za>
In-reply-to
Content
Let met try to get you sold on adding the “first” function I released on PyPI roughly a year ago:

https://github.com/hynek/first

It’s a very nice complement to functions like `any()` or itertools. I consists effectively of 9 lines of code but it proved extremely handy in production.

***

It returns the first true value from an iterable or a default:

>>> first([0, None, False, [], (), 42])
42

>>> first([0, None, False, [], ()], default=42)
42

Additionally it also allows for a key function:

>>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
4

***

First happens to be especially useful together with the re module:

import re

from first import first


re1 = re.compile('b(.*)')
re2 = re.compile('a(.*)')

m = first(regexp.match('abc') for regexp in [re1, re2])
if not m:
   print('no match!')
elif m.re is re1:
   print('re1', m.group(1))
elif m.re is re2:
   print('re2', m.group(1))


All the knee-jerk alternatives to it have some shortcomings:

next(itertools.ifilter(None, (regexp.match('abc') for regexp in [re1, re2])), None)
next((regexp.match('abc') for regexp in [re1, re2] if regexp.match('abc')), None)

None of them is Pythonic and the second one even has to call match() twice, which is *not* a cheap method to call.

Here the first version for comparison again:

first(regexp.match('abc') for regexp in [re1, re2])

It doesn’t even exhaust the iterator if not necessary.

***

I don’t cling to neither the name or the exact function signature (although it got polished with the help of several people, two of them core developers).  I also don’t really care whether it gets added along of any() or put into itertools.  I just know that I and several other people would appreciate to have such a handy function in the stdlib – I even got an e-mail from OpenStack folks asking when it will be added because they would like to use it and there’s even a debian package by now: http://packages.debian.org/unstable/python-first

There’s also this question on StackOverflow: http://stackoverflow.com/questions/1077307/why-is-there-no-firstiterable-built-in-function-in-python which is nice but doesn’t fix the subtleties like when there is no true value etc which makes it useless for production code and one has to write boilerplate code every single time.

It was even one of five Python packages Lukasz Langa deemed worthy to be highlighted in his PyCon 2013 lightning talk: http://youtu.be/1vui-LupKJI?t=20m40s

FWIW, SQL has a similar function called COALESCE ( https://en.wikipedia.org/wiki/Null_(SQL)#COALESCE ) which only handles NULL though.

***

I’ll happily respond to any questions or concerns that may arise and supply a patch as soon as we agree on a place to add it.
History
Date User Action Args
2013-08-04 10:08:55hyneksetrecipients: + hynek, rhettinger, ncoghlan, lukasz.langa
2013-08-04 10:08:54hyneksetmessageid: <1375610934.97.0.503658757825.issue18652@psf.upfronthosting.co.za>
2013-08-04 10:08:54hyneklinkissue18652 messages
2013-08-04 10:08:53hynekcreate