I was just thinking about multiple-dispatch and something just occurred to me. Currently, there is multiple-dispatch based on input types but what if it can dispatch on output type as well?
For example sqrt(-1) will fail currently but sqrt(-1)::Complex should succeed because sqrt is dispatching on output type. One way around this currently is to have the output type as a parameter e.g. sqrt(-1, outType = Complex) then it will dispatch based on Type{Complex}. For example
import Base.sqrt
sqrt(x, ::Type{Complex}) = sqrt(Complex(x))
sqrt(-1, Complex) # works fine
Of course this a very weird idea as most of the time we write
x = sqrt(-1)
and at this point, x isn’t defined, so it will fail; but
x::Complex = sqrt(-1)
should work if multiple-dispatch is on output type.
I can see how implementing this sort of things will rely on more magic, so may not be a good idea but I think this may be something not many people have talked about. So worth mentioning.
But this is already taken for type assertion syntax.
Also, I am not saying that the original idea is a good one, just trying to interpret what was suggested.
I actually think that making caller context available to functions in this subtle, optional way is not a good design choice. If the function needs that information, it should be explicit in the argument list.
One thing: typically in Julia, when making a method of a function where you want to dispatch on a type, in particular to indicate the return type, it is the first argument, for example, convert, rand, zero, etc., so if you did this, it probably should be something like: sqrt(Complex, -1)
Let’s not pick at old comments in old topics, please. We generally keep topics open here because they gather search rank and there could be relevant new information that comes to light, but we don’t need to resurrect threads to just argue about asides. You can see that nobody ran with that suggestion in the seven years since.
Perhaps not with Complex, but one can imagine other types where there is overhead in creating T(-1) first. E.g. some field where sqrt is defined on some embedding of whole numbers.
So, say you have some algebraic structure GAlgebra which allows square roots. Let’s say its representation is somewhat complicated, but the whole numbers can be embedded. You don’t want to write sqrt(GAlgebra(-1)) because creating GAlgebra(-1) is quite involved, and the general sqrt for GAlgebra is also quite involved. But, due to circumstances, constructing the square root of GAlgebra(-1) directly from -1 (or any other whole number) is simple.
You would likely want something like sqrt(GAlgebra, -1). The typical way in julia would be to make it general, with a fallback like sqrt(::Type{T}, x) where {T} = sqrt(convert(T, x)), and allow specializations for structs like GAlgebra or SMatrix{N, N} where N
Converting a value or real type to complex is a loss of information, so the sqrt method you end up calling may quite possibly be less efficient, because it doesn’t know the imaginary part is zero.
A simple example is Complex{BigFloat}. It’s both costly to work with, and not ultimately implemented in Julia (the implementation relies on the venerable MPFR C library). The latter severely restricts the kinds of compiler optimizations that are possible.
calculating sqrt(GAlgebra(-1)) would be slow in general because sqrt(GAlgebra(<anyfloat>)) is some complicated method
but there is a much simpler implementation sqrt(GAlgebra(-1)) because -1::GAlgrbra is a special case (excuse the abuse of notation)
This is a “runtime” special case. It depends on the value at runtime.
Therefore it should be implemented (it could be implemented?) in the function as a branch statement.
function sqrt(galgebra::GAlgebra)
if galgebra.something_value == -1
...
else
...
Julia doesn’t currently provide a way to dispatch methods using values as well as types. Nor (IMO) should it.
I’m aware that’s not what is being asked for with a syntax like
sqrt(GAlgebra, -1)
Can you get the same behavior by “overloading” sqrt (providing a method for sqrt) with a method which takes an argument type as the first argument?
sqrt(some_type, value)
if some_type isa GAlgebra ...
Perhaps this is what was being suggested and I just missed the point being made or otherwise misunderstood here?