Basic string iteration

Hello, I came across this iteration behaviour I don’t really grasp.

I can define a string and iterate through it character-by-character as

julia> test_string = "abc"
"abc"

julia> for character in test_string
           println(character)
       end
a
b
c

but why does the .|> notation iterate as the string is indeed an array containing a string?

julia> test_string .|> character->println(character)
abc

Both variants work, because iterate is defined for Strings.
Wrong. Second variant with .|> does not iterate over characters in the String.

ok…but why the . doesn’t make any difference?

julia> test_string .|> character->println(character)
abc

julia> test_string |> character->println(character)
abc

Ah, ok, output should be

a
b
c

not
abc
… have to investigate…

Strings are scalars for the purposes of broadcasting, so "abc" .|> x->println(x) and "abc" |> x->println(x) do the same thing and they both call println on the entire string a single time. If you want to broadcast over the characters of a string, you need to collect it first: collect("abc") .|> x->println(x). However, this is an antipattern because you are using broadcasting for a side-effect and uselessly constructing a vector of nothing values. Consider doing foreach(println, "abc") instead. The foreach function doesn’t need to guess what is a scalar or not, it only makes sense to apply it to something iterable.

3 Likes

The REPL docs results in the same:

help?> .|>
search:

  x .|> y is akin to broadcast(|>, x, y). See broadcast.

Therefore we have:

broadcast(|>, "abc", character->println(character) )

which is equivalent to:

broadcast(|>, "abc", println )

which is just

println("abc")

It seems I have some kind of error in this argument, but I can’t find it…
I see, this is only stringent, when Strings are scalars in this context, as Stefan pointed out.

1 Like

I see, thanks you both for the explanation!