List Comprehensions

Terry Reedy tjreedy at udel.edu
Mon Dec 22 15:28:24 EST 2014


On 12/22/2014 12:10 PM, Chris Angelico wrote:
> On Tue, Dec 23, 2014 at 2:18 AM, Steven D'Aprano
> <steve+comp.lang.python at pearwood.info> wrote:
>> Chris Angelico wrote:
>>
>>> On Mon, Dec 22, 2014 at 8:21 PM, Steven D'Aprano
>>> <steve+comp.lang.python at pearwood.info> wrote:
>>>> If the called function has side-effects, a list comp is not a good
>>>> solution.
>>>
>>> Hmm. I'm not so sure about that. Side effects are fine in a list comp,
>>> as long as you're making use of the return values. For instance, if
>>> you have a function that inserts a record to a database and returns
>>> the new ID, you could reasonably use a list comp to save a bunch of
>>> records and get a list of IDs for subsequent use.
>>
>> I hear what you are saying, but a list comprehension is a functional idiom.

In particular, it is a way to hide the mutational, non-functional, 
.append that is a necessary part of constructing an array of references 
in contiguous memory on a physical machine.

>> To mix functional and procedural idioms in the one expression is rather
>> icky.

A list comp with side-effects in the target expression is definitely a 
subversion of the original intent.  Whether Python programmers should 
respect that intent is another matter.  Limiting the 
opinion/recommendation to single expressions makes it more defensible 
than something broader.

>> Better to use one or the other but not both simultaneously.
>> I'll accept that this is a weak recommendation though.


> In my opinion, trying to separate functional and procedural idioms is
> like trying to separate 'for' loops and recursion; they're two tools

A for loop with a recursive call in its body is not 'one expression'. 
Moreover, it is easy to claim that driving multiple recursion with a for 
loop is clearer than using the recursive equivalent of a for loop to 
drive the 'horizontal' repetition.  Untested example for preorder 
traversal of a tree where nodes have ordered children:

def preorder(node):
   yield node
   for child in node.children():  # horizontal repetition
        yield from preorder(child)  # vertically nested repetition

I do not see any such gain over Ganesh Pal's original for-loop code.

> that can be used separately or together, in whatever way makes the
> most sense. Given that side-effecting functions are a mess in
> functional programming anyway, of course they cause problems for
> functional idioms; but if it's okay to have side effects at all, it
> ought to be okay to have side effects of a list comp.

I see this as equivalent to "If it is okay to have separated side 
effects, it ought to be okay to have mixed-in side effects."

I am not claiming that I would *never* use side effects in a list comp, 
but I am sympathetic to the objection.

-- 
Terry Jan Reedy




More information about the Python-list mailing list