Using zip() with count()

I’m trying to use count where the iterator is taken from zip.

Here is the code I’ve written:

function hamming(c, d)
    count((x,y) -> (x != y), zip(c,d))

However, when this is run on any non-empty collections, e.g. hamming("123","1X3"), an exception is thrown:

ERROR: MethodError: no method matching (::getfield(Main, Symbol("##9#10")))(::Tuple{Char,Char})

Closest candidates are:

#9(::Any, ::Any) at REPL[71]:2


[1] count( ::getfield(Main, Symbol("##9#10")), ::Base.Iterators.Zip{Tuple{String,String}} ) at ./reduce.jl:772

[2] hamming( ::String, ::String ) at ./REPL[71]:2

[3] top-level scope at REPL[72]:1

I can’t see any obvious reason this wouldn’t work based on the documentation for count().

There is also no problem when count is replaced by an equivalent for loop, something like:

for (x,y) in zip("123","1X3")
    print(x == y ? 0 : 1)

Can someone help me out? What have I misunderstood?


Regarding your question:
I noticed the following would work:

julia> count(x -> (x[1] == x[2]), zip("1X3","123"))

The result of zip is a tuple. How about this?

function hamming(c, d)
    count(t -> (t[1] == t[2]), zip(c,d))

count( ( (x,y)::Tuple{Any,Any} )->(x==y),zip("123","1X3"))

I think

(x,y) -> (x == y)

is interpreted as a function with two parameters x::Any and y::Any and not as a single Tuple parameter

1 Like

As others have pointed out, zip produces Tuples, as a single argument. You can also do

hamming(c, d) = count(Base.splat(==), zip(c,d))

Very nice!

As an alternative, similar to oheil’s solution but imho more canonical, I’d suggest using an anonymous function with one argument used with tuple destructuring.
So you can write:

hamming(c,d) = count( ((x,y),) -> x == y, zip(c,d))

where we have a anonymous function ((x,y),) -> x == y which has one argument (note that the one-argument tuple is (a,) not (a) - in the latter case the parens are interpreted as showing precedence which doesn’t make sense here.
This one argument is then destructured as a tuple of two elements.

This works in general and doesn’t rely on unexported Base functions.


Perfect, all makes sense - thanks everyone!

It didn’t occur to me that (x,y) -> x == y would be interpreted as a function of two parameters, whereas I was aiming for a function of one (tuple) parameter.

I also just noticed I supplied the wrong condition in the first post for the Hamming distance.

Original: count(x -> x[1] == x[2], zip(s1,s2))
Fixed: count(x -> x[1] != x[2], zip(s1,s2))

Apologies to everyone whose replies are now slightly wrong.