iterators, map, lambdas and tuple destructuring

504 views
Skip to first unread message

S Wade

unread,
Jul 14, 2012, 10:05:28 AM7/14/12
to juli...@googlegroups.com
hi all,

Consider the following:

julia> map((x, y) -> x + y, [(1, 2), (2, 1)])
in anonymous: wrong number of arguments

julia> map(x -> x[1] + x[2], [(1, 2), (2, 1)])
2-element Int64 Array:
3
3

julia> map(x -> x[1] + x[2], zip([1, 2], [2, 1]))
no method map(Function,Zip)

julia> for z in zip([1, 2], [2, 1])
println(z[1] + z[2])
end
3
3

julia> for (x, y) in zip([1, 2], [2, 1])
println(x + y)
end
3
3

Two questions:

1. map() doesn't seem to play nice with zipped sequences. Is that a bug?
2. how do I destructure collections of tuples when passing them to a lambda?

thanks,
wade

Jeffrey Sarnoff

unread,
Jul 14, 2012, 7:27:08 PM7/14/12
to juli...@googlegroups.com
I have run into these same things.
map( (x, y) -> x+y, [ (1,2), (2,1) ] ) should work with (x,y) accepting e.g. (1,2) as does (x,y) = f() where f returns (1,2);
requiring map( z -> z[1] + z[2], ..) is cumbersome and ugly.
To work around the zip problem, I defined a method -- reluctantly.  Really, that should be system level support.

Jeffrey Sarnoff

unread,
Jul 15, 2012, 1:11:50 PM7/15/12
to juli...@googlegroups.com
not 'ugly', less elegant

S Wade

unread,
Jul 26, 2012, 7:57:04 PM7/26/12
to juli...@googlegroups.com
I think this partially fixes the zip problem, but it's not correct
since it doesn't work on raw iterators. How can I specify a raw
iterator here so that this definition of map doesn't collide with the
other, more type-specific definitions of map():

# map

type Map{I}
mapper::Function
itr::I
end
map(mapper::Function, itr::Union(Reverse, Filter, Zip, Enumerate)) =
Map(mapper, itr)

start(m::Map) = start(m.itr)
function next(m::Map, s)
v,s = next(m.itr, s)
m.mapper(v), s
end
done(m::Map, s) = done(m.itr, s)

Jeff Bezanson

unread,
Jul 27, 2012, 12:08:39 AM7/27/12
to juli...@googlegroups.com
In most functional languages I've used, map of an n-argument function
accepts n containers to iterate over, for example map(+, A, B) for
elementwise add of two arrays. I also don't recommend using Zip. You
won't reach the end of the data before the sun swallows the earth.
Hopefully we can fix that.

Patrick O'Leary

unread,
Jul 27, 2012, 12:40:30 AM7/27/12
to juli...@googlegroups.com
On Thursday, July 26, 2012 11:08:39 PM UTC-5, Jeff Bezanson wrote:
In most functional languages I've used, map of an n-argument function
accepts n containers to iterate over, for example map(+, A, B) for
elementwise add of two arrays.

In Haskell, map works over a single container, and zipWith works over two (and zipWith3 over three, etc.). The implementation of zip is the application of the tuple constructor to zipWith.

This maps neatly to the idea that a tuple represents a function argument; mapping an uncurried function over the list of tuples is equivalent to using zipWith with the same (curried) function:

zip [1..3] [4..6]
=> [(1,4),(2,5),(3,6)]
zipWith (+) [1..3] [4..6]
=> [5,7,9]
map (uncurry (+)) $ zip [1..3] [4..6]
=> [5,7,9]

Using "map" to apply higher arity functions in lieu of zipWith is probably fine, though. It just approaches from a different--in our case, probably more appropriate--point of view.

John Cowan

unread,
Jul 27, 2012, 1:38:45 PM7/27/12
to juli...@googlegroups.com
On Fri, Jul 27, 2012 at 12:40 AM, Patrick O'Leary
<patrick...@gmail.com> wrote:

> On Thursday, July 26, 2012 11:08:39 PM UTC-5, Jeff Bezanson wrote:
>>
>> In most functional languages I've used, map of an n-argument function
>> accepts n containers to iterate over, for example map(+, A, B) for
>> elementwise add of two arrays.

> In Haskell, map works over a single container, and zipWith works over two
> (and zipWith3 over three, etc.). The implementation of zip is the
> application of the tuple constructor to zipWith.

Well, that's because in Haskell all functions have only a single
argument: it is currying, not tupling. That's a more or less
arbitrary choice, with upsides and downsides. Julia, however, is
tupling, and should probably use Lisp-style map.

> Using "map" to apply higher arity functions in lieu of zipWith is probably
> fine, though. It just approaches from a different--in our case, probably
> more appropriate--point of view.

+1

--
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures
Reply all
Reply to author
Forward
0 new messages