Questo funziona a causa di una delle caratteristiche fondamentali di Julia: invio multiplo. In Julia, le funzioni possono avere molti metodi che si applicano a varie combinazioni di tipi di argomenti e quando si chiama una funzione, Julia invoca il metodo più specifico che corrisponde al tipo di tutti gli argomenti con cui lo si chiama. La chiamata //
nella definizione del metodo che hai postato definisce il valore intero-razionale //
in termini di intero-intero //
- quindi non è effettivamente ricorsivo perché il metodo non chiama se stesso, ma chiama un metodo diverso che fa parte dello stesso " funzione generica ".
Per capire come funziona la spedizione multipla in questo caso, consideriamo la valutazione dell'espressione (3//4)//6
. Useremo la macro @which
per vedere quale metodo chiama ogni chiamata di funzione.
julia> @which (3//4)//6
//(x::Rational{T<:Integer}, y::Integer) at rational.jl:25
Da 3//4
è un Rational{Int} <: Rational
e 6
è un Int <: Integer
, e applicare altri metodi più specifici, questo metodo viene chiamato:
//(x::Rational, y::Integer) = x.num // (x.den*y)
La current version del metodo è in realtà leggermente più complicato di quello hai postato perché è stato modificato per verificare l'overflow dei numeri interi, ma è essenzialmente lo stesso, ed è più facile capire la versione più vecchia e più semplice, quindi la userò. Assegniamo x
e y
agli argomenti e vedere quale metodo la definizione chiama:
julia> x, y = (3//4), 6
(3//4,6)
julia> x.num
3
julia> x.den*y
24
julia> x.num // (x.den*y)
1//8
julia> @which x.num // (x.den*y)
//(n::Integer, d::Integer) at rational.jl:22
Come si può vedere, questa espressione non significa chiamare lo stesso metodo, che definisce un different method:
//(n::Integer, d::Integer) = Rational(n,d)
Questo metodo chiama semplicemente il costruttore Rational
che inserisce il rapporto di n
e d
in termini minimi e crea un oggetto numero Rational
.
È abbastanza comune definire un metodo di una funzione in termini di un altro metodo della stessa funzione, in Julia. Ecco come funzionano le impostazioni predefinite degli argomenti, ad esempio.Considerare questa definizione:
julia> f(x, y=1) = 2x^y
f (generic function with 2 methods)
julia> methods(f)
# 2 methods for generic function "f":
f(x) at none:1
f(x, y) at none:1
julia> f(1)
2
julia> f(2)
4
julia> f(2,2)
8
La sintassi dell'argomento predefinito genera semplicemente un secondo metodo con solo onee argomento, che definisce la forma con due argomenti con il valore predefinito. Così f(x, y=1) = 2x^y
è esattamente equivalente a definire due metodi, in cui il metodo appena unario chiama il metodo binario, fornendo un valore di default per il secondo argomento:
julia> f(x, y) = 2x^y
f (generic function with 1 method)
julia> f(x) = f(x, 1)
f (generic function with 2 methods)
Questo era molto lucida. Grazie. – dopatraman