Eu estava tentando algumas coisas no REPL Julia (1.2) e prendi minha mente em algo que não entendo sobre o envio.
Eu tentei pela primeira vez essa coisa que está funcionando da maneira que eu esperava:
f(a::T) where {T <: Int} = "Test"
Chamar f (3) funciona desde
Int <: Int == true
Chamar f ("Hello") resulta em um erro "MethodError: no method matching" desde
String <: Int == false
Então, tentei esse método e não entendo por que chamá-lo funciona em alguns casos:
f(a::T, b::U) where {T, U <: T} = "Another Test"
Chamar f (3, 3) funciona (como eu esperava)
MAS f (3, "Hello") também funciona e não gera um "MethodError: nenhum método correspondente" ???
Eu pensei que (desde que T se torna um Int e U uma String) String <: Int == false
???
Acho que estou perdendo algo bem direto aqui, mas não consigo encontrá-lo ... Portanto, esta é a minha pergunta, por que f (3, "Olá") está funcionando ???
Além disso, eu tentei esse trecho de código (tentei recriar a segunda assinatura do método) e ele falhou corretamente como eu esperava:
Test = Tuple{T, U} where {T, U <: T}
Test{Int, String}
(isso falha como eu esperava com "TypeError: no tipo, em U, U esperado <: Int64, obteve o tipo {String}")
Int64,String,false
. Pode ser necessário reiniciar a Julia se você adicionar métodos às funções. Basta usar um novo personagem, por exemplo,h
para um novo teste. Para sua pergunta: Parece que o sistema tenta encontrar qualquer solução para a restrição de tipo eT=Any, U=Any where U:<T
é uma delas. Se você introduzir um tipo concreto, como no terceiro exemplo, ele funcionará conforme o esperado. Pessoas com um conhecimento mais profundo do sistema do tipo Julia darão em breve uma resposta adequada.Respostas:
O que está acontecendo aqui é que
T
pode ser um tipo de dados eU
qualquer supertipo de string. Este as condições são cumpridas. A única coisa que estava provocando você com uma string que não é um subtipo de int é um arenque vermelho, pois nenhum tipo concreto é o subtipo de qualquer outro.fonte
Ok, graças ao trabalho , parece que agora entendo o que estava acontecendo. Se usarmos este método:
f(a::T, b::U) where {T, U <: T} = "Another Test"
'U' é o "UnionAll", também conhecido como "União Iterada" de todos os tipos possíveis de 'b' que são subtipos de 'T'
O que eu estava entendendo errado era o fato de que se (exemplo) a :: Int, então T pode pegar um tipo abstrato pai do tipo de (a). Desde Int <: Qualquer, então T = Qualquer é uma solução válida para envio.
Portanto, agora temos U <: T que resolve como Any <: Any == true, e o método é chamado!
Espero conseguir :)
fonte