I wanted a scale! method that works for tridiagonal matrices and did the 
following.

import Base.scale!

function scale!{T}(A::Tridiagonal{T}, x::T)
    Base.scale!(A.dl, x) 
    Base.scale!(A.d,  x)
    Base.scale!(A.du, x)
    return
end

Doing 

methods(scale!)

gives the output

# 15 methods for generic function "scale!":
scale!{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64)}(X::Array{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),N},s::T<:Union(Complex{Float64},Float32,Complex{Float32},Float64))
 
at linalg/dense.jl:11
...
scale!(X::AbstractArray{T,N},s::Number) at linalg/generic.jl:20
...
(A::CholmodSparse{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),Ti<:Union(Int64,Int32)},b::Array{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),1})
 
at linalg/cholmod.jl:907
scale!{T}(A::Tridiagonal{T},x::T) at none:2

however

A=Tridiagonal(rand(3),rand(4),rand(3))
4x4 Tridiagonal{Float64}:
 0.342959   0.878001  0.0        0.0     
 0.0359927  0.481333  0.950373   0.0     
 0.0        0.764103  0.0200941  0.84859 
 0.0        0.0       0.220059   0.131956

scale!(A,2.0)
ERROR: indexing not defined for Tridiagonal{Float64}
 in generic_scale! at linalg/generic.jl:16
 in scale! at linalg/generic.jl:20

We can verify that Julia is not dispatching to the tridiagonal scale! 
method:

which(scale!, (Tridiagonal{Float64},Float64))
scale!(X::AbstractArray{T,N},s::Number) at linalg/generic.jl:20

If I change the first line of the function definition to

function scale!(A::Tridiagonal,x)

then I get some ambiguity warnings:

Warning: New definition 
    scale!(Tridiagonal{T},Any) at none:2
is ambiguous with: 
    scale!(AbstractArray{T,N},Number) at linalg/generic.jl:20.
To fix, define 
    scale!(Tridiagonal{T},Number)
before the new definition.
Warning: New definition 
    scale!(Tridiagonal{T},Any) at none:2
is ambiguous with: 
    scale!(AbstractArray{T,2},AbstractArray{T,1}) at linalg/generic.jl:306.
To fix, define 
    scale!(Tridiagonal{T},AbstractArray{T,1})
before the new definition.
scale! (generic function with 15 methods)

Sure enough, defining 

function scale!(A::Tridiagonal, x::Number)
    Base.scale!(A.dl, x)
    Base.scale!(A.d,  x)
    Base.scale!(A.du, x)
    return
end

works fine. I am a bit mystified by this behaviour.  Why was there no 
warning for my first attempt?
Is there a problem in general with making a method "too specific"?

Reply via email to