《Elixir 101》函式與回傳值

閱讀時間約 11 分鐘
最近又重新開始學 Elixir,這時遇到一個問題:
在 Elixir 裡面要怎麼建立函式,還有函式要怎麼回傳值?
首先這要從 Elixir 有兩種函數類型說起:
  • 匿名函式(Anonymous Functions)
  • 具名函示(Named Functions)

匿名函式 (Anonymous Functions)

匿名函式 (Anonymous Functions),通常指的是這個函式無需有函示的識別符號(identifier)。在有些語言實作上,被稱為 lambda表示式(Pyhton),或者是 閉包(closures) (Rust)。
在 Elixir 裡,匿名函式是宣告一個變數,然後將函式用 fn ... end 包裹起來。
例如我們宣告一個叫 hello_world 的匿名函式,裡面是向顯示器顯示 Hello World ,那我們可以寫作:
hello_world = fn() -> IO.puts "Hello World" end
這時候我們該如何執行這個函式呢?
在其他語言中,可能會很自然的加上 () 作為執行函式的句法,例如上方的 hello_world 變成 hello_world() 來執行。接著就會在 Elixir 中發生錯誤。例如我們在 iex 中試試看:
$ iex
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> hello_world = fn() -> IO.puts "Hello World" end
#Function<21.126501267/0 in :erl_eval.expr/5>
iex(2)> hello_world()
** (CompileError) iex:2: undefined function hello_world/0
在 Elixir 中,必須加入 . (dot) 來執行這個匿名函式(. (dot) 在 Elixir 裡面也是一個運算符號,基於本篇主題,留待下次再說明)。所以執行上方範例的 hello_world 就要變成:
hello.()
這時候我們在 iex 在實驗一次,就可以知道成功執行啦!
$ iex
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> hello_world = fn() -> IO.puts "Hello World" end
#Function<21.126501267/0 in :erl_eval.expr/5>
iex(2)> hello_world.()
Hello World
:ok
iex(3)>

具名函式(Named Functions)

相對於匿名函式,具名函式具有識別符。不過在 Elixir 裡面宣告一個具名函式,和其他語言一些不同。例如在 JavaScript 我們可以直接用 function 語法宣告一個 helloWorld 的具名函式:
function helloWorld(){
console.log('hello world');
}
但在 Elixir 裡面我們可以這樣做嗎?是不是可以將匿名函式的 fn...end 語法直接拿來宣告為:
fn hello_world = () -> IO.puts "hello world"

答案是不能的。

在 Elixir 裡,具名函式的運作範圍僅限於模組(module)。換言之,必須將函式定義在 module 裡。例如我們定義一個 MyModule 名稱的 module,裡面有一個具名函式稱為 hello_world :
defmodule MyModule do
def hello_world() do
IO.puts "hello world"
end
end
當我們在 module 裡面定義好一個具名函式,這時候我們一樣就可以用 . (dot) ,來呼叫這個 module 裡面特定的具名函式。例如上述案例,我們要呼叫 MyModule 裡面的 hello_world 我們就是:
MyModule.hello_world()
在 iex 裡面實驗一次:
$ iex
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule MyModule do
...(1)> def hello_world do
...(1)> IO.puts "hello world"
...(1)> end
...(1)> end
{:module, MyModule,
<<70, 79, 82, 49, 0, 0, 4, 104, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 149,
0, 0, 0, 15, 15, 69, 108, 105, 120, 105, 114, 46, 77, 121, 77, 111, 100, 117,
108, 101, 8, 95, 95, 105, 110, 102, 111, ...>>, {:hello_world, 0}}
iex(2)> MyModule.hello_world()
hello world
:ok
iex(3)>

函式的回傳值

以上介紹了兩種函示:匿名函式以及具名函式。那我們在函式中,要怎麼回傳函式的運算值呢?
在程式語言中,函式回傳值主要有兩種表示方式:
  • 用 return 或相類似的語法
  • 回傳值為函式結構中最後的表示式
第一種方式就例如 JavaScript,在函式結構中用 return 語法回傳函式運算值,如果未設定的話,就是回傳 undefined:
function helloWorld(shouldReturn){
if(shouldReturn){
return 'hello world';
}
}

console.log(helloWorld(true)); // 將輸出 'hello world'
console.log(helloWorld(false)); // 將輸出 undefined
而在 Elixir 裡,則是採用第二種方式,將函式結構中最後表示式作為回傳值。如果沒有,則回傳 nil ,即空值。
以之前 MyModule 為例,我們新增另一個 hello 具名函式,而他的函式結構中未有任何程式碼。並將 hello_world 中的 IO.puts "hello world" 改為 "hello world":
defmodule MyModule do
def hello_world() do
"hello world"
end

def hello() do
end
end
這時候 hello_world 將回傳字串值 hello_world ,而 hello 將僅回傳 nil。我們可以在 iex 中試一下:
$ iex
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule MyModule do
...(1)> def hello_world() do
...(1)> 'hello world'
...(1)> end
...(1)> def hello() do
...(1)> end
...(1)> end
{:module, MyModule,
<<70, 79, 82, 49, 0, 0, 4, 120, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 144,
0, 0, 0, 15, 15, 69, 108, 105, 120, 105, 114, 46, 77, 121, 77, 111, 100, 117,
108, 101, 8, 95, 95, 105, 110, 102, 111, ...>>, {:hello, 0}}
iex(2)> MyModule.hello_world()
'hello world'
iex(3)> MyModule.hello()
nil
iex(4)>

參考文獻

1會員
5Content count
身為一個軟體工程師,在現今如此快速變化的世界中,該如何確保自生不被滅亡呢?
留言0
查看全部
發表第一個留言支持創作者!
工法人的沙龍 的其他內容
最近開始接觸 Elixir 這門語言,語法風格接近 Ruby。而他有一種動靜皆備的特性,老實說還蠻吸引我的。
最近開始接觸 Elixir 這門語言,語法風格接近 Ruby。而他有一種動靜皆備的特性,老實說還蠻吸引我的。
你可能也想看
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
展覽中我們似乎可以從作品中看出一些東西、但又不那麼明確,覺得他就是個色彩斑斕的抽象畫,但又依稀在其中看到一些具體的形象。我覺得那就像是記憶畫面在我們心靈裡沉積,並變化為精神、變成情感的一個過程。
Thumbnail
本文討論了箭頭函式 (arrow function) 對於 this 關鍵字的影響。
Thumbnail
記錄 JavaScript 學習旅程中遇到的 method 與 this 問題
Thumbnail
宇宙是嚴格的生命教練,又是溫柔地守護母親; 所說的話,祂都有在聽,並提醒著此刻真正要學習的就是靜觀、順流。
Thumbnail
來到桃園之前,一直以為桃園是美食沙漠,但我在這裡生活才一個多禮拜,就已經發現不少街邊美食了,請大家不要再誤會桃園了~~ 1.乾拌-韓式甘甜醬🌶️ 甘甜醬
Thumbnail
本文的目的是先從文本分析中仔細的描述命題香對化的原理,接著才從文學史上的兩個事件來把握此原則的起源。
Thumbnail
時間進入2021年最後一個月,歲末年終,街道上開始出現一些溫暖的聖誕布置,在寒流來襲的日子,你是否和阿蒙一樣,也感受到許多喜樂、寧靜的氛圍呢?然而,和越來越濃的節慶氣氛不同,過去這幾天,國際金融市場並不平靜。
Thumbnail
英雄和惡龍可能是與深淵互相凝視的關係,而公主則是英雄的阿尼瑪。 英雄之旅,其實就是英雄本人通往自我的內在旅程。因此或許可以把英雄,當成一個踏上冒險旅途的人來看待,是個生命的冒險者。 而《尚氣與十環傳氣》,從亞洲的家庭與親屬觀切入,講述了一篇繼往開來,且極可能開創新局的英雄故事。
Thumbnail
故事敘述尚氣,自幼接受父親文武的鐵血戰鬥培訓,精通各種武術招式。長大後為了逃離家鄉,他改名換姓展開新生活,認識了新摯友凱蒂,平靜日子就這樣過了十年,直到過去再度找上門…….尚氣能否會發掘十環的無敵力量,無懼擺脫父親的勢力?
Thumbnail
好啦我知道拍很爛 好,先坦承這本書我還沒讀完,然後它的全名叫做《活出語言來:語言人類學導論》──我想這就不難理解為什麼我沒有讀完它了。因為它實際上是一本語言學專用的教材書,書的內容自然也較為學術,用字遣詞偏生硬,不過不至於難以理解。我相信只要是受過論述訓練的讀者都能很好適應它;不過即便如此,我還是很
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
展覽中我們似乎可以從作品中看出一些東西、但又不那麼明確,覺得他就是個色彩斑斕的抽象畫,但又依稀在其中看到一些具體的形象。我覺得那就像是記憶畫面在我們心靈裡沉積,並變化為精神、變成情感的一個過程。
Thumbnail
本文討論了箭頭函式 (arrow function) 對於 this 關鍵字的影響。
Thumbnail
記錄 JavaScript 學習旅程中遇到的 method 與 this 問題
Thumbnail
宇宙是嚴格的生命教練,又是溫柔地守護母親; 所說的話,祂都有在聽,並提醒著此刻真正要學習的就是靜觀、順流。
Thumbnail
來到桃園之前,一直以為桃園是美食沙漠,但我在這裡生活才一個多禮拜,就已經發現不少街邊美食了,請大家不要再誤會桃園了~~ 1.乾拌-韓式甘甜醬🌶️ 甘甜醬
Thumbnail
本文的目的是先從文本分析中仔細的描述命題香對化的原理,接著才從文學史上的兩個事件來把握此原則的起源。
Thumbnail
時間進入2021年最後一個月,歲末年終,街道上開始出現一些溫暖的聖誕布置,在寒流來襲的日子,你是否和阿蒙一樣,也感受到許多喜樂、寧靜的氛圍呢?然而,和越來越濃的節慶氣氛不同,過去這幾天,國際金融市場並不平靜。
Thumbnail
英雄和惡龍可能是與深淵互相凝視的關係,而公主則是英雄的阿尼瑪。 英雄之旅,其實就是英雄本人通往自我的內在旅程。因此或許可以把英雄,當成一個踏上冒險旅途的人來看待,是個生命的冒險者。 而《尚氣與十環傳氣》,從亞洲的家庭與親屬觀切入,講述了一篇繼往開來,且極可能開創新局的英雄故事。
Thumbnail
故事敘述尚氣,自幼接受父親文武的鐵血戰鬥培訓,精通各種武術招式。長大後為了逃離家鄉,他改名換姓展開新生活,認識了新摯友凱蒂,平靜日子就這樣過了十年,直到過去再度找上門…….尚氣能否會發掘十環的無敵力量,無懼擺脫父親的勢力?
Thumbnail
好啦我知道拍很爛 好,先坦承這本書我還沒讀完,然後它的全名叫做《活出語言來:語言人類學導論》──我想這就不難理解為什麼我沒有讀完它了。因為它實際上是一本語言學專用的教材書,書的內容自然也較為學術,用字遣詞偏生硬,不過不至於難以理解。我相信只要是受過論述訓練的讀者都能很好適應它;不過即便如此,我還是很