Julia: `dot(x, y)` method is circular for some arguments

Created on 30 Apr 2020  Â·  6Comments  Â·  Source: JuliaLang/julia

Tried something that I knew wouldn't work, but got an error message that I didn't expect. Not sure if this is just an uninformative error message or something more devious.

julia> using LinearAlgebra

julia> di = Dict("a" => 1, "b" => 2,"c"=>3.0)
Dict{String,Real} with 3 entries:
  "c" => 3.0
  "b" => 2
  "a" => 1

julia> dot(di,rand(3))
ERROR: StackOverflowError:
Stacktrace:
 [1] dot(::Char, ::Float64) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/generic.jl:869 (repeats 79984 times)
julia> versioninfo()
Julia Version 1.4.1
Commit 381693d3df* (2020-04-14 17:20 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
linear algebra

Most helpful comment

Right, the fallback dot(x, y) method is circular when x or y is a non-Number that iterates itself, e.g. a Char. Not sure what the best fix is; maybe we could throw a better error if vx === x?

All 6 comments

The error is right evaluation error.
Please look this a part of dot code.

https://github.com/JuliaLang/julia/blob/8e76b12c01e9a76e70d6b7b1d6c6db7b40f1cee3/stdlib/LinearAlgebra/src/generic.jl#L856-L857

https://github.com/JuliaLang/julia/blob/8e76b12c01e9a76e70d6b7b1d6c6db7b40f1cee3/stdlib/LinearAlgebra/src/generic.jl#L867-L869

dot function in dot calls dot(vx, vy).
If vx, vy are not equal Abstract type, it calls itself.

julia> di = Dict("a" => 1, "b" => 2,"c"=>3.0)
Dict{String,Real} with 3 entries:
  "c" => 3.0
  "b" => 2
  "a" => 1

julia> vx, vs = iterate(di)
(Pair{String,Real}("c", 3.0), 5)

julia> vx2, vs = iterate(vx)
("c", 2)

julia> vx3, vs = iterate(vx2)
('c', 2)

and

julia> vx4, vs = iterate(vx3)
('c', true)

iterate of Char type returns Tuple{Char,Bool}.
So I think the error is right.

Not sure I agree. For a comparable scenario you get

julia> 'a' * 2.0
ERROR: MethodError: no method matching *(::Char, ::Float64)
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:529
  *(::Bool, ::T) where T<:AbstractFloat at bool.jl:110
  *(::Float64, ::Float64) at float.jl:405
  ...
Stacktrace:
 [1] top-level scope at REPL[78]:1

Right, the fallback dot(x, y) method is circular when x or y is a non-Number that iterates itself, e.g. a Char. Not sure what the best fix is; maybe we could throw a better error if vx === x?

Allowing

julia> dot([[Set([[1]])], 2], [1, [(2,)]])
5

in the first place does not sound right to me. Is it intentional?

maybe we could throw a better error if vx === x?

I agree this is the least breaking and user-friendly fix.

LinearAlgebra operates Number, so this code to calculate dot of numbers is defined in LinearAlgebra module.

https://github.com/JuliaLang/julia/blob/8e76b12c01e9a76e70d6b7b1d6c6db7b40f1cee3/stdlib/LinearAlgebra/src/generic.jl#L884

A way solving this problem is to define like

dot(s1::AbstractChar, s2::AbstractChar) = s1 * s2
dot(s1::AbstractChar, s2) = s1 * s2
dot(s1, s2::AbstractChar) = s1 * s2

However it can't solve other iteratable not collection types.
We need to defined it in each type.
And I don't think it is a good design to define other type (not Number type) in LinearAlgebra.
So if we define it, we define it in base/char.jl.

Sorry the code conflicts with other dot (ex. dot(s1::Foo, s2) = s1 * s2).
It doesn't run.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TotalVerb picture TotalVerb  Â·  3Comments

StefanKarpinski picture StefanKarpinski  Â·  3Comments

Keno picture Keno  Â·  3Comments

m-j-w picture m-j-w  Â·  3Comments

ararslan picture ararslan  Â·  3Comments