《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)>

參考文獻

avatar-img
1會員
5內容數
身為一個軟體工程師,在現今如此快速變化的世界中,該如何確保自生不被滅亡呢?
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
工法人的沙龍 的其他內容
最近開始接觸 Elixir 這門語言,語法風格接近 Ruby。而他有一種動靜皆備的特性,老實說還蠻吸引我的。
最近開始接觸 Elixir 這門語言,語法風格接近 Ruby。而他有一種動靜皆備的特性,老實說還蠻吸引我的。
你可能也想看
Google News 追蹤
Thumbnail
現代社會跟以前不同了,人人都有一支手機,只要打開就可以獲得各種資訊。過去想要辦卡或是開戶就要跑一趟銀行,然而如今科技快速發展之下,金融App無聲無息地進到你生活中。但同樣的,每一家銀行都有自己的App時,我們又該如何選擇呢?(本文係由國泰世華銀行邀約) 今天我會用不同角度帶大家看這款國泰世華CUB
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節旨在介紹 C# 中函數的基本結構,包括訪問修飾符、返回類型、方法名稱、參數列表和方法體。同時,也介紹了函數的各種呼叫方式、參數傳遞方式和返回值類型。讀者可以通過本章節,深入理解 C# 中函數的使用和應用。
Thumbnail
在Python中,我們可以用def關鍵字定義函數,並透過函數名稱呼叫它。函數參數可以是必填、關鍵字、默認或不定長度的類型。return語句負責結束函數並回傳值。全域變數可以在整個程序中使用,而區域變數只能在特定函數內使用。我們還可以在一個文件中定義函數,然後在另一個文件中呼叫它。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
立即(調用)函式 (簡稱 IIFE,Immediately Invoked Function Expression) 是種在定義完可以馬上執行的函式表達式。
Thumbnail
如果我只是想要重複做一些很簡單的運算,還有沒有更簡潔的方式,那就是Lambda匿名函式。 本文將介紹 : Lambda匿名函式的用法,也比較跟自定函式的差異之處。 結合map,filter,sorted函式做應用介紹
Thumbnail
lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。
Thumbnail
現代社會跟以前不同了,人人都有一支手機,只要打開就可以獲得各種資訊。過去想要辦卡或是開戶就要跑一趟銀行,然而如今科技快速發展之下,金融App無聲無息地進到你生活中。但同樣的,每一家銀行都有自己的App時,我們又該如何選擇呢?(本文係由國泰世華銀行邀約) 今天我會用不同角度帶大家看這款國泰世華CUB
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節旨在介紹 C# 中函數的基本結構,包括訪問修飾符、返回類型、方法名稱、參數列表和方法體。同時,也介紹了函數的各種呼叫方式、參數傳遞方式和返回值類型。讀者可以通過本章節,深入理解 C# 中函數的使用和應用。
Thumbnail
在Python中,我們可以用def關鍵字定義函數,並透過函數名稱呼叫它。函數參數可以是必填、關鍵字、默認或不定長度的類型。return語句負責結束函數並回傳值。全域變數可以在整個程序中使用,而區域變數只能在特定函數內使用。我們還可以在一個文件中定義函數,然後在另一個文件中呼叫它。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
立即(調用)函式 (簡稱 IIFE,Immediately Invoked Function Expression) 是種在定義完可以馬上執行的函式表達式。
Thumbnail
如果我只是想要重複做一些很簡單的運算,還有沒有更簡潔的方式,那就是Lambda匿名函式。 本文將介紹 : Lambda匿名函式的用法,也比較跟自定函式的差異之處。 結合map,filter,sorted函式做應用介紹
Thumbnail
lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。