Is there a Python equivalent of the Haskell 'let' expression that would allow me to write something like:
list2 = [let (name,size)=lookup(productId) in (barcode(productId),metric(size)) for productId in list]
If not, what would be the most readable alternative?
Added for clarification of the let syntax:
x = let (name,size)=lookup(productId) in (barcode(productId),metric(size))
is equivalent to
(name,size) = lookup(productId) x = (barcode(productId),metric(size))
The second version doesn't work that well with list comprehensions, though.
This ability doesn't exist in Python, because of the thought that when people write something like: if row = db.
You could use a temporary list comprehension
[(barcode(productId), metric(size)) for name, size in [lookup(productId)]][0]
or, equivalently, a generator expression
next((barcode(productId), metric(size)) for name, size in [lookup(productId)])
but both of those are pretty horrible.
Another (horrible) method is via a temporary lambda, which you call immediately
(lambda (name, size): (barcode(productId), metric(size)))(lookup(productId))
I think the recommended "Pythonic" way would just be to define a function, like
def barcode_metric(productId): name, size = lookup(productId) return barcode(productId), metric(size) list2 = [barcode_metric(productId) for productId in list]
Recent python versions allows multiple for clauses in a generator expression, so you can now do something like:
list2 = [ barcode(productID), metric(size) for productID in list for (name,size) in (lookup(productID),) ]
which is similar to what Haskell provides too:
list2 = [ (barcode productID, metric size) | productID <- list , let (name,size) = lookup productID ]
and denotationally equivalent to
list2 = [ (barcode productID, metric size) | productID <- list , (name,size) <- [lookup productID] ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With