Julia/函式簡介
函式是 Julia 程式碼的基本構建塊,充當其他程式語言中發現的子例程、過程、塊和類似的結構概念。
函式是收集在一起的一組指令,可以返回一個或多個值,可能基於輸入引數。如果引數包含可變的值(如陣列),則陣列可以在函式內部修改。按照慣例,函式名稱末尾的感嘆號(!)表示函式可能會修改其引數。
定義函式有各種語法
- 當函式包含單個表示式時
- 當函式包含多個表示式時
- 當函式不需要名稱時
要定義一個簡單的函式,您只需在等號的左側提供函式名稱和任何引數(用括號括起來),在等號的右側提供一個表示式。這就像數學函式一樣
julia> f(x) = x * x
f (generic function with 1 method)
julia> f(2)
4
julia> g(x, y) = sqrt(x^2 + y^2)
g (generic function with 1 method)
julia> g(3, 4)
5.0
定義包含多個表示式的函式的語法如下
function functionname(args)
expression
expression
expression
...
expression
end
這是一個典型的函式,它呼叫另外兩個函式,然後結束。
function breakfast()
maketoast()
brewcoffee()
end
breakfast (generic function with 1 method)
最終表示式(此處為 brewcoffee() 函式)返回的值也是 breakfast() 函式返回的值。
您可以使用 return 關鍵字來指示要返回的特定值
julia> function canpaybills(bankbalance)
if bankbalance < 0
return false
else
return true
end
end
canpaybills (generic function with 1 method)
julia> canpaybills(20) true julia> canpaybills(-10) false
有些人認為始終使用 return 語句是一種良好的風格,即使它不是嚴格必要的。稍後我們將看到如何確保當您使用錯誤型別的引數呼叫函式時,函式不會偏離軌道。
要從函式返回多個值,請使用元組(在後面的章節中更詳細地探討)。
function doublesix()
return (6, 6)
end
doublesix (generic function with 1 method)
julia> doublesix() (6, 6)
這裡您可以編寫 6, 6 而不使用括號。
您可以定義帶有可選引數的函式,這樣如果未提供特定值,函式可以使用合理的預設值。您在引數列表中提供預設符號和值
function xyzpos(x, y, z=0)
println("$x, $y, $z")
end
xyzpos (generic function with 2 methods)
當您呼叫此函式時,如果您沒有提供第三個值,則變數 z 預設值為 0,並在函式內部使用該值。
julia> xyzpos(1,2) 1, 2, 0 julia> xyzpos(1,2,3) 1, 2, 3
當您編寫具有很長引數列表的函式時,如下所示
function f(p, q, r, s, t, u)
...
end
遲早您會忘記必須按什麼順序提供引數。例如,它可能是
f("42", -2.123, atan2, "obliquity", 42, 'x')
或
f(-2.123, 42, 'x', "42", "obliquity", atan2)
您可以透過使用關鍵字標記引數來避免此問題。在函式的未標記引數後使用分號,然後在其後加上一個或多個 keyword=value 對
function f(p, q ; r = 4, s = "hello")
println("p is $p")
println("q is $q")
return "r => $r, s => $s"
end
f (generic function with 1 method)
當呼叫時,此函式需要兩個引數,還接受一個數字和一個字串,分別標記為 r 和 s。如果您沒有提供關鍵字引數,則使用它們的預設值
julia> f(1,2)
p is 1
q is 2
"r => 4, s => hello"
julia> f("a", "b", r=pi, s=22//7)
p is a
q is b
"r => π = 3.1415926535897..., s => 22//7"
如果您提供了關鍵字引數,它可以在引數列表中的任何位置,而不僅僅是在末尾或匹配位置。
julia> f(r=999, 1, 2) p is 1 q is 2 "r => 999, s => hello" julia> f(s="hello world", r=999, 1, 2) p is 1 q is 2 "r => 999, s => hello world" julia>
在定義帶有關鍵字引數的函式時,請記住在關鍵字/值對之前插入一個分號。
以下是 Julia 手冊中的另一個示例。rtol 關鍵字可以出現在引數列表中的任何位置,也可以省略
julia> isapprox(3.0, 3.01, rtol=0.1) true julia> isapprox(rtol=0.1, 3.0, 3.01) true julia> isapprox(3.0, 3.00001) true
函式定義可以結合所有不同型別的引數。以下是一個包含普通引數、可選引數和關鍵字引數的示例
function f(a1, opta2=2; key="foo")
println("normal argument: $a1")
println("optional argument: $opta2")
println("keyword argument: $key")
end
f (generic function with 2 methods)
julia> f(1) normal argument: 1 optional argument: 2 keyword argument: foo julia> f(key=3, 1) normal argument: 1 optional argument: 2 keyword argument: 3 julia> f(key=3, 2, 1) normal argument: 2 optional argument: 1 keyword argument: 3
函式可以定義為可以接受任意數量的引數
function fvar(args...)
println("you supplied $(length(args)) arguments")
for arg in args
println(" argument ", arg)
end
end
三個點表示著名的splat。這裡表示“任意”,包括“無”。您可以使用任意數量的引數呼叫此函式
julia> fvar() you supplied 0 arguments julia> fvar(64) you supplied 1 arguments argument 64 julia> fvar(64,65) you supplied 2 arguments argument 64 argument 65 julia> fvar(64,65,66) you supplied 3 arguments argument 64 argument 65 argument 66
等等。
以下是一個例子。假設您定義了一個接受兩個引數的函式
function test(x, y)
println("x $x y $y")
end
您可以按照通常的方式呼叫它
julia> test(12, 34) x 12 y 34
如果您有兩個數字,但它們在一個元組中,那麼如何將一個數字元組提供給這個需要兩個引數的函式呢?答案仍然是使用省略號(splat)。
julia> test((12, 34) ...) x 12 y 34
省略號或“splat”的使用也稱為“拆分”引數
julia> test([3,4]...) x 3 y 4
您也可以這樣做
julia> map(test, [3, 4]...) x 3 y 4
您在函式內部定義的任何變數在函式結束時都會被遺忘。
function test(a,b,c)
subtotal = a + b + c
end
julia> test(1,2,3) 6 julia> subtotal LoadError: UndefVarError: subtotal not defined
如果您想跨函式呼叫保留值,那麼您可以考慮使用全域性變數。
函式無法修改作為引數傳遞給它的現有變數,但它可以更改傳遞給它的容器的內容。例如,以下函式將其引數更改為 5
function set_to_5(x)
x = 5
end
julia> x = 3 3 julia> set_to_5(x) 5 julia> x 3
雖然函式內部的 x 被更改了,但函式外部的 x 沒有被更改。函式中的變數名稱對該函式是區域性的。
但函式可以修改容器的內容,例如陣列。此函式使用 [:] 語法訪問容器 x 的內容,而不是更改變數 x 的值
function fill_with_5(x)
x[:] .= 5
end
julia> x = collect(1:10);
julia> fill_with_5(x)
5
julia> x
10-element Array{Int64,1}:
5
5
5
5
5
5
5
5
5
5
您可以更改陣列的元素,但您無法更改變數,使其指向另一個數組。換句話說,您的函式不允許更改引數的繫結。
有時您不想為函式想出一個很酷的名稱。匿名函式(無名函式)可以在 Julia 中的許多地方使用,例如與 map() 一起使用,以及在列表推導中。
語法使用 ->,如下所示
x -> x^2 + 2x - 1
這定義了一個無名函式,它接受一個引數,將其稱為 x,並返回 x^2 + 2x - 1。
例如,map() 函式的第一個引數是一個函式,您可以定義一個一次性函式,該函式僅存在於一個特定的 map() 操作中
julia> map(x -> x^2 + 2x - 1, [1,3,-1])
3-element Array{Int64,1}:
2
14
-2
map() 結束後,函式和引數 x 都消失了
julia> x ERROR: x not defined
如果您想要一個接受多個引數的匿名函式,請將引數作為元組提供
julia> map((x,y,z) -> x + y + z, [1,2,3], [4, 5, 6], [7, 8, 9])
3-element Array{Int64,1}:
12
15
18
請注意,結果為 12、15、18,而不是 6、15 和 24。匿名函式將每個陣列的第一個值加在一起,然後是第二個值,然後是第三個值。
此外,如果您使用“空”元組 (),匿名函式可以具有零個引數
julia> random = () -> rand(0:10) #3 (generic function with 1 method) julia> random() 3
julia> random() 1
如果您已經有一個函式和一個數組,您可以透過使用 map() 為陣列中的每個元素呼叫函式。這會依次對每個元素呼叫函式,收集結果,並將它們返回到一個數組中。這個過程稱為對映
julia> a=1:10;
julia> map(sin, a)
10-element Array{Float64,1}:
0.841471
0.909297
0.14112
-0.756802
-0.958924
-0.279415
0.656987
0.989358
0.412118
-0.544021
map() 返回一個新的陣列,但如果你呼叫 map!(),你會修改原始陣列的內容。
通常,你不需要使用 map() 來將 sin() 之類的函式應用於陣列的每個成員,因為許多函式會自動“逐元素”運算。這兩個不同版本的計時是相似的(sin.() 可能佔有優勢,具體取決於元素的數量)。
julia> @time map(sin, 1:10000); 0.149156 seconds (568.96 k allocations: 29.084 MiB, 2.01% gc time) julia> @time sin.(1:10000); 0.074661 seconds (258.76 k allocations: 13.086 MiB, 5.86% gc time)
map() 會將每次應用的結果收集到一個數組中並返回該陣列。有時你可能想要“對映”操作,但不想將結果作為陣列返回。在這種情況下,請使用 foreach()
julia> foreach(println, 1:20) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
並且 ans 為空(ans == nothing 為 true)。
使用多個數組進行對映
[edit | edit source]你可以使用 map() 來處理多個數組。函式將應用於每個陣列的第一個元素,然後是第二個元素,依此類推。陣列必須具有相同的長度(與 zip() 函式不同,zip() 函式對長度要求更寬鬆)。
以下是一個示例,它生成一個英制扳手/套筒尺寸陣列。第二個陣列只是一堆重複的 32,用於匹配第一個陣列中從 5 到 24 的整數。Julia 會為我們簡化有理數。
julia> map(//, 5:24, fill(32,20))
20-element Array{Rational{Int64},1}:
5//32
3//16
7//32
1//4
9//32
5//16
11//32
3//8
13//32
7//16
15//32
1//2
17//32
9//16
19//32
5//8
21//32
11//16
23//32
3//4
(實際上,一個英制扳手套裝不會包含一些奇怪的尺寸——我從未見過一個 17/32 英寸的扳手,但你可以在網上購買。)
使用點語法應用函式
[edit | edit source]除了 map(),還可以將函式直接應用於作為陣列的引數。請參閱關於 向量化函式的點語法 的部分。
歸約和摺疊
[edit | edit source]map() 函式收集某個函式對可迭代物件(例如數字陣列)的每個元素的運算結果。reduce() 函式執行類似的任務,但在所有元素都被函式處理後,只剩下一個元素。函式應接收兩個引數並返回一個引數。陣列透過持續應用進行歸約,直到只剩下一個元素。
一個簡單的示例是使用 reduce() 來對可迭代物件中的數字求和(這與內建函式 sum() 相似)。
julia> reduce(+, 1:10) 55
在內部,它執行類似於以下操作的操作
((((((((1 + 2) + 3) + 4) + 6) + 7) + 8) + 9) + 10)
在每次新增兩個數字的操作之後,都會將單個數字傳遞到下一輪迭代。此過程會將所有數字歸約為單個最終結果。
一個更有用的示例是,當你想對可迭代物件中的每個連續對應用函式時。例如,以下是一個函式,它比較兩個字串的長度並返回更長的字串
julia> l(a, b) = length(a) > length(b) ? a : b l (generic function with 1 method)
這可以透過逐對處理字串來找到句子中最長的單詞
julia> reduce(l, split("This is a sentence containing some very long strings"))
"containing"
“This” 持續了幾輪,然後被 “sentence” 打敗,但最終 “containing” 取得領先,並且之後沒有其他挑戰者。如果你想看看魔法是如何發生的,請重新定義 l 如下
julia> l(a, b) = (println("comparing \"$a\" and \"$b\""); length(a) > length(b) ? a : b)
l (generic function with 1 method)
julia> reduce(l, split("This is a sentence containing some very long strings"))
comparing "This" and "is"
comparing "This" and "a"
comparing "This" and "sentence"
comparing "sentence" and "containing"
comparing "containing" and "some"
comparing "containing" and "very"
comparing "containing" and "long"
comparing "containing" and "strings"
"containing"
你可以使用匿名函式來逐對處理陣列。訣竅是讓函式留下一個將在下一輪迭代中使用的值。此程式碼接收一個類似於 [1, 2, 3, 4, 5, 6...] 的陣列,並返回 [1 * 2, 2 * 3, 3 * 4, 4 * 5...],將相鄰元素相乘。
store = Int[];
reduce((x,y) -> (push!(store, x * y); y), 1:10)
julia> store
9-element Array{Int64,1}:
2
6
12
20
30
42
56
72
90
摺疊
[edit | edit source]Julia 還提供了兩個相關的函式 foldl() 和 foldr()。它們提供與 reduce() 相同的基本功能。區別在於遍歷的方向。在上面的簡單求和示例中,我們對 reduce() 操作內部發生的事件的最佳猜測是假設第一對元素首先被新增,然後是第二對元素,依此類推。但是,reduce() 也可能從末尾開始,然後向前面進行。如果這很重要,請使用 foldl() 進行從左到右的遍歷,使用 foldr() 進行從右到左的遍歷。在許多情況下,結果是相同的,但以下是一個示例,其中你將根據使用哪個版本獲得不同的結果
julia> reduce(-, 1:10) -53 julia> foldl(-, 1:10) -53 julia> foldr(-, 1:10) -5
Julia 提供了此組中的其他函式:請檢視 mapreduce()、mapfoldl() 和 mapfoldr()。
如果你想對僅接收一個引數的函式使用 reduce() 和 fold-() 函式,請使用一個虛擬的第二個引數
julia> reduce((x, y) -> sqrt(x), 1:4, init=256) 1.4142135623730951
這等效於呼叫 sqrt() 函式四次
julia> sqrt(sqrt(sqrt(sqrt(256)))) 1.4142135623730951
返回函式的函式
[edit | edit source]你可以像對待其他 Julia 物件一樣對待 Julia 函式,特別是在將它們作為其他函式的結果返回時。
例如,讓我們建立一個函式建立函式。在此函式內部,將建立一個名為 newfunction 的函式,該函式將把它的引數 (y) 提升到最初作為引數 x 傳入的數字。這個新函式將作為 create_exponent_function() 函式的值返回。
function create_exponent_function(x)
newfunction = function (y) return y^x end
return newfunction
end
現在我們可以構建許多指數建立函式。首先,讓我們構建一個 squarer() 函式
julia> squarer = create_exponent_function(2) #8 (generic function with 1 method)
以及一個 cuber() 函式
julia> cuber = create_exponent_function(3) #9 (generic function with 1 method)
趁此機會,讓我們構建一個“提升到 4 次冪”的函式(稱為 quader,儘管我開始對拉丁語和希臘語的命名感到困惑)
julia> quader = create_exponent_function(4) #10 (generic function with 1 method)
這些是普通的 Julia 函式
julia> squarer(4) 16 julia> cuber(5) 125 julia> quader(6) 1296
上面 create_exponent_function() 的定義是完全有效的 Julia 程式碼,但它不是慣用的。一方面,返回值並不總是需要明確提供——如果未使用 return,則返回最終的評估結果。此外,在這種情況下,函式定義的完整形式可以用更短的一行版本替換。這給出了簡潔的版本
function create_exponent_function(x)
y -> y^x
end
它以相同的方式執行。
make_counter = function()
so_far = 0
function()
so_far += 1
end
end
julia> a = make_counter(); julia> b = make_counter(); julia> a() 1 julia> a() 2 julia> a() 3 julia> a() 4 julia> b() 1 julia> b() 2
以下是如何建立函式的另一個示例。為了更清楚地看到程式碼的功能,以下是 make_counter() 函式以略微不同的方式編寫
function make_counter()
so_far = 0
counter = function()
so_far += 1
return so_far
end
return counter
end
julia> a = make_counter()
#15 (generic function with 1 method)
julia> a()
1
julia> a()
2
julia> a()
3
julia> for i in 1:10
a()
end
julia> a()
14
函式連結和組合
[edit | edit source]Julia 中的函式可以相互結合使用。
函式組合是指將兩個或多個函式應用於引數。你可以使用函式組合運算子 (∘) 來組合函式。(你可以在 REPL 中使用 \circ 來輸入組合運算子)。例如,sqrt() 和 + 函式可以像這樣組合
julia> (sqrt ∘ +)(3, 5) 2.8284271247461903
它先將數字相加,然後求平方根。
此示例組合了三個函式。
julia> map(first ∘ reverse ∘ uppercase, split("you can compose functions like this"))
6-element Array{Char,1}:
'U'
'N'
'E'
'S'
'E'
'S'
函式連結(有時稱為“管道”或“使用管道將資料傳送到後續函式”)是指將函式應用於上一個函式的輸出
julia> 1:10 |> sum |> sqrt 7.416198487095663
其中 sum() 生成的總數將傳遞給 sqrt() 函式。等效的組合是
julia> (sqrt ∘ sum)(1:10) 7.416198487095663
管道可以將資料傳送到接受單個引數的函式。如果函式需要多個引數,你可能可以使用匿名函式
julia> collect(1:9) |> n -> filter(isodd, n)
5-element Array{Int64,1}:
1
3
5
7
9
方法
[edit | edit source]一個函式可以有許多不同的方法來完成類似的任務。每種方法通常專注於針對特定型別執行任務。
以下是一個函式,用於在輸入位置時檢查經度
function check_longitude_1(loc)
if -180 < loc < 180
println("longitude $loc is a valid longitude")
else
println("longitude $loc should be between -180 and 180 degrees")
end
end
check_longitude_1 (generic function with 1 method)
如果你在 REPL 中定義此函式,你看到的“通用函式,包含 1 種方法”訊息告訴你這時有一種方法可以呼叫 check_longitude_1() 函式。如果你呼叫此函式並提供一個數字,它可以正常工作。
julia> check_longitude_1(-182) longitude -182 should be between -180 and 180 degrees julia> check_longitude_1(22) longitude 22 is a valid longitude
但是,如果你輸入一個以 Google Maps 上看到的格式顯示的經度,會發生什麼情況?
julia> check_longitude_1("1°24'54.6\"W")
ERROR: MethodError: `isless` has no method matching isless(::Int64, ::UTF8String)
錯誤訊息告訴我們函式已停止,因為當一個引數是字串,另一個引數是數字時,小於的概念 (<) 在我們的函式內部沒有意義。字串不小於或大於整數,因為它們是兩個不同的東西,所以函式在此處失敗。
請注意,雖然check_longitude_1() 函式已經開始執行了。但是引數loc 可以是任何型別 - 字串,浮點數,整數,符號,甚至是陣列。這個函式有許多可能出錯的方式。這不是編寫程式碼的最佳方式!
為了解決這個問題,我們可能會想新增程式碼來測試傳入的值,以便以不同的方式處理字串。但 Julia 提出了一個更好的選擇:**方法** 和 多重派發。
在經度以數值形式提供的情況下,loc 引數被定義為“型別為 Real”。讓我們重新開始,定義一個新函式,並正確地進行。
function check_longitude(loc::Real)
if -180 < loc < 180
println("longitude $loc is a valid longitude")
else
println("longitude $loc should be between -180 and 180 degrees")
end
end
現在這個 check_longitude 函式甚至不會在 loc 中的值不是實數時執行。避免了當值為字串時該怎麼辦的問題。使用型別 Real,可以使用任何引數呼叫此特定方法,前提是它是某種數字。
我們可以使用 applicable() 函式來測試這一點。applicable() 讓你知道你是否可以將一個函式應用於一個引數 - 也就是說,對於具有該型別的引數,該函式是否有可用的方法。
julia> applicable(check_longitude, -30) true julia> applicable(check_longitude, pi) true julia> applicable(check_longitude, 22/7) true julia> applicable(check_longitude, 22//7) true julia> applicable(check_longitude, "1°24'54.6\"W") false
false 表示你不能將字串值傳遞給 check_longitude() 函式,因為沒有用於該函式的方法可以接受字串。
julia> check_longitude("1°24'54.6\"W")
ERROR: MethodError: `check_longitude` has no method matching check_longitude(::UTF8String)
現在函式主體甚至不會被檢視 - Julia 不知道如何使用字串引數呼叫 check_longitude() 函式的方法。
接下來的明顯步驟是為 check_longitude() 函式新增另一種方法,只是這一次接受一個字串引數。這樣,一個函式可以被賦予多個備選方法:一個用於數值引數,一個用於字串引數,等等。Julia 根據你提供給函式的引數型別來選擇並執行其中一個可用方法。
這就是**多重派發**。
function check_longitude(loc::String)
# not real code, obviously!
if endswith(loc, "W")
println("longitude $loc is West of Greenwich")
else
println("longitude $loc is East of Greenwich")
end
end
check_longitude (generic function with 2 methods)
現在 check_longitude() 函式有兩個方法。要執行的程式碼取決於你提供給函式的引數型別。你可以避免在函式開始時測試引數型別,因為只有在 loc 是字串時,Julia 才會將流程分派到字串處理方法。
你可以使用內建的 methods() 函式來找出你為特定函式定義了多少方法。
julia> methods(check_longitude) # 2 methods for generic function "check_longitude": check_longitude(loc::Real) at none:2 check_longitude(loc::String) at none:3
一個有啟發性的例子是檢視 + 函式有多少種不同的方法。
julia> methods(+)
# 176 methods for generic function "+":
[1] +(x::Bool, z::Complex{Bool}) in Base at complex.jl:276
[2] +(x::Bool, y::Bool) in Base at bool.jl:104
...
[174] +(J::LinearAlgebra.UniformScaling, B::BitArray{2}) in LinearAlgebra at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v0.7/LinearAlgebra/src/uniformscaling.jl:90
[175] +(J::LinearAlgebra.UniformScaling, A::AbstractArray{T,2} where T) in LinearAlgebra at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v0.7/LinearAlgebra/src/uniformscaling.jl:91
[176] +(a, b, c, xs...) in Base at operators.jl:466
這是一個很長的列表,列出了當前為 + 函式定義的每種方法;你可以將許多不同型別的物件加在一起,包括陣列、矩陣和日期。如果你設計自己的型別,你可能想編寫一個將兩個型別加在一起的函式。
Julia 選擇“最具體的那個方法”來處理引數型別。對於 check_longitude(),我們有兩個特定方法,但我們可以定義一個更通用的方法。
function check_longitude(loc::Any)
println("longitude $loc should be a string or a number")
end
check_longitude (generic function with 3 methods)
當 loc 引數既不是 Real 數字也不是字串時,就會呼叫這種 check_longitude() 方法。它是最通用的方法,如果存在更具體的方法,則根本不會被呼叫。
在方法定義中使用型別資訊是可能的。這是一個簡單的例子。
julia>function test(a::T) where T <: Real
println("$a is a $T")
end
test (generic function with 1 methods)
julia> test(2.3)
2.3 is a Float64
julia> test(2)
2 is a Int64
julia> test(.02)
0.02 is a Float64
julia> test(pi)
π = 3.1415926535897... is a Irrational{:π}
julia> test(22//7)
22//7 is a Rational{Int64}
julia> test(0xff) 255 is a UInt8
test() 方法會自動提取傳遞給它的單個引數 a 的型別,並將其儲存在“變數”T 中。對於此函式,T 的定義是**其中 T 是 Real 的子型別**,所以 T 的型別必須是 Real 型別的子型別(它可以是任何實數,但不能是複數)。“T”可以像任何其他變數一樣使用 - 在此方法中,它只是使用字串插值打印出來。(它不一定是 T,但幾乎總是這樣!)
當你想要將特定方法定義的引數限制為特定型別時,此機制很有用。例如,引數 a 的型別必須屬於 Real 數字超型別,因此當 a 不是數字時,此 test() 方法不適用,因為此時引數的型別不是 Real 的子型別。
julia> test("str")
ERROR: MethodError: no method matching test(::ASCIIString)
julia> test(1:3)
ERROR: MethodError: no method matching test(::UnitRange{Int64})
這是一個例子,你可能想要編寫一個適用於所有一維整數陣列的方法定義。它查詢陣列中的所有奇數。
function findodds(a::Array{T,1}) where T <: Integer
filter(isodd, a)
end
findodds (generic function with 1 method)
julia> findodds(collect(1:20))
10-element Array{Int64,1}:
1
3
5
7
9
11
13
15
17
19
但不能用於實數陣列。
julia> findodds([1, 2, 3, 4, 5, 6, 7, 8, 9, 10.0])
ERROR: MethodError: no method matching findodds(::Array{Float64,1})
Closest candidates are:
findodds(::Array{T<:Integer,1}) where T<:Integer at REPL[13]:2
請注意,在這個簡單的例子中,因為你沒有在方法定義中使用型別資訊,你最好堅持使用更簡單的方法定義方式,透過在引數中新增型別資訊。
function findodds(a::Array{Int64,1})
findall(isodd, a)
end
但是,如果你想在方法中做一些取決於引數型別的事情,那麼型別引數方法就會很有用。