函式

函式 在 Julia

2 個練習

關於 函式

Basics概念介紹了定義函式的兩種方式。

最一般來說,多行形式:

function muladd(x, y, z)
    x * y + z
end

「指定」或「單行」形式,用於簡短定義:

muladd(x, y, z) = x * y + z

第三種、甚至更簡短的形式,可以建立沒有名稱的簡短、單次使用的函式:

julia> map(x -> 2x, 1:3)
4-element Vector{Int64}:
 2
 4
 6

julia> map((x, y) -> x * y, 1:3, 4:6)
3-element Vector{Int64}:
  4
 10
 18

在這種情況下,x -> 2x是一個「匿名函式」。 這等同於其他語言所稱的「lambda 函式」。

請注意,多個引數需要括號,例如(x, y) -> x * y。

匿名函式在 Julia 程式碼中很常見,尤其是與高階函式(例如map()和filter())結合使用時。

函式引數

到目前為止,在課程大綱中,我們只探討了具有確切引數數量的函式,並且要求函式呼叫必須以正確的順序提供所有引數。 這樣會有限制且不方便,所以還有其他幾種選項。

選擇性引數

與許多語言一樣,Julia 允許函式定義為個別引數提供預設值。

然後,函式呼叫可以為該引數提供值,或者省略它並依賴預設值。

julia> f(x, y=10) = x * y
f (generic function with 2 methods)

julia> f(2, 3)
6

julia> f(2)
20

所有_沒有_預設值的引數都必須排在_有_預設值的引數之前,這表示f(x=2, y)會是無效的。

關鍵字引數

到目前為止的所有範例都使用positional arguments,其中函式呼叫提供的值必須符合函式定義中對應引數的順序。

與許多語言一樣,Julia 也允許keyword arguments。 函式呼叫必須指定引數名稱,但多個關鍵字引數可以接著以任意順序指定。

Julia 的一個獨特功能是,函式定義中的關鍵字引數(如果有的話)前面必須加上分號;,以便與任何位置引數區分開來。 函式呼叫可以在最後一個位置引數和第一個關鍵字引數之間使用;或,。

julia> b(x; y) = x + y
b (generic function with 1 method)

julia> b(2, y=3)
5

# keyword is required when calling
julia> b(2, 3)
ERROR: MethodError: no method matching b(::Int64, ::Int64)
The function `b` exists, but no method is defined for this combination of argument types.

可以選擇性地指定預設值,就像位置引數一樣。

在函式呼叫中,當與參數同名的變數已經事先計算好時,經常會出現像myarg=myarg這樣的語法。 這種情況下允許使用簡寫語法:

julia> width = 4.0
4.0

julia> height = √ width
2.0

julia> area(; width, height) = width * height
area (generic function with 1 method)

# repetition
julia> area(; width=width, height=height)
8.0

# shorthand form
julia> area(; width, height)
8.0

Splat 與 slurp

這些是 Julia 語法中某個實用層面的標準名稱,以防你好奇。 兩者都指...運算子。

Splat

Splat 用於函式_呼叫_,將集合展開為函式所需的個別值。

這用示範可能比解釋更容易:

julia> fxyz(x, y, z) = x * y * z
fxyz (generic function with 1 method)

julia> xyz = [2, 3, 4]
3-element Vector{Int64}:
 2
 3
 4

# Using the vector directly in a function call is invalid
julia> fxyz(xyz)
ERROR: MethodError: no method matching fxyz(::Vector{Int64})
The function `fxyz` exists, but no method is defined for this combination of argument types.

# splatting converts the vector to 3 numbers, used as positional arguments
julia> fxyz(xyz...)
24

有些「函式呼叫」被語法糖隱藏,所以 splat 也可以用於較不明顯的方式。

例如,多重指定在內部使用了元組建構函式:

julia> first, rest... = [1, 2, 3, 4]
4-element Vector{Int64}:
 1
 2
 3
 4

julia> first
1

julia> rest
3-element Vector{Int64}:
 2
 3
 4

關鍵字引數也可以透過 splat 提供,通常使用named tuple。 Dict也可以運作,但鍵必須是符號(在這裡字串無法運作)。

# function with 3 keyword arguments
julia> fabc(; a, b, c) = a + b + c
fabc (generic function with 1 method)

# named tuple
julia> abc_nt = (a=2, b=3, c=4)
(a = 2, b = 3, c = 4)

# there are no positional arguments, so need to use ; before kw argument
julia> fabc(;abc_nt...)
9

# Dict
julia> abc_dict = Dict(:a=>2, :b=>3, :c=>4)
Dict{Symbol, Int64} with 3 entries:
  :a => 2
  :b => 3
  :c => 4

julia> fabc(;abc_dict...)
9
Slurp

Slurp 用於函式_定義_,將任意數量的個別值打包到集合中。

julia> f_more(i, j, more...) = i + j + sum(more)
f_more (generic function with 1 method)

julia> f_more(1, 3, 5, 7, 9, 11)
36

被 slurp 的引數名稱(在這個例子中是more)並不重要。 這個變數的型別由編譯器選擇,但對於位置引數而言,很可能是tuple或類似的東西。

關鍵字引數也可以被 slurp,得到一個Dict(或類似的東西)。

julia> f_kwslurp(x, y; switches...) = :mult in keys(switches) ? x * y : x + y
f_kwslurp (generic function with 1 method)

julia> f_kwslurp(5, 6; mult=true)
30

julia> f_kwslurp(5, 6)
11

呼叫時可以使用任何關鍵字引數。 函式定義要決定要回應哪些關鍵字,以及忽略哪些。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 函式

練習已鎖定

再解鎖 1 個練習,就能練習 函式