Here's an alternative answer: this is a quirk and implementation detail that should ideally not exist. It's not a result of Julia's type design or dispatch, nor is it really a great design pattern. It's just the status quo.
Matrix multiplication is based upon an in-place API. That is, A*B
becomes mul!(output_array, A, B)
. Thus, we need to pre-allocate the result before actually knowing what will happen. The computation of this output element type is done by a quirky and ill-specified function: promote_op
. It's something that really should be removed but would require a huge and difficult refactor... and thus we have strange cases like this.
For more details, see the docstring of Base.promote_op
(note that it's unexported and doesn't even appear in the online manual):
help?> Base.promote_op
promote_op(f, argtypes...)
Guess what an appropriate container eltype would be for storing results of
f(::argtypes...). The guess is in part based on type inference, so can
change any time.
│ Warning
│
│ Due to its fragility, use of promote_op should be avoided. It is
│ preferable to base the container eltype on the type of the actual
│ elements. Only in the absence of any elements (for an empty result
│ container), it may be unavoidable to call promote_op.
For more internal details on promote_op
see issue #19669, comments in #25689, and their discussion.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…