Kotlin — 什麼是 Function literals with receiver

JLin
9 min readMar 25, 2021

--

再看了一些Code後常常會看到有一種寫法

啥?

 HTML.() -> Unit

這是什麼意思? 如果是

() ->Unit

這我還知道阿,這是lambda function,前面是參數後面是回傳值`,()代表是空參數,如果下面這樣就代表兩個參數A / B 還有回傳C

(A,B) -> C

例如,可以傳入String跟Int,ex.(“name”,15)

(String,Int) -> Unit

但前面多了一個 HTML. 是什麼意思??

這時候想到了extension function,那我是不是可以解讀成

再宣告的當下HTML這個物件,就會透過lambda function擁有後面那個型態的extension function,也就是擁有init的行為

這樣會清楚多了嗎?

平常

fun html(init: () -> Unit): HTML { … }

在前面會多了一個

HTML.

必須解讀成剛剛那句話,

再宣告的當下HTML這個物件,就會透過lambda function擁有後面那個型態的extension function,也就是擁有init的行為

所以在這個裡面,html實體體化後就可以呼叫init()的方法,也就是

html.init()

而通常這樣的方式就稱為 function literals with receiver

可以在官方文件的Lambda章節找到

再談之前先弄懂!

什麼是 literals?

https://semicolonspace.com/kotlin-lambda-function-literals/

查了一下字典他是

The literal meaning of a word is its original, basic meaning.

有點像是,字面的意思、表面的意思~

這樣還是無法懂啊!!

但查了一下Wiki

在電腦中,他是一個固定不可變的值,也就是定義的常數的值,譬如

kotlin

val x = 10 
val name = "Tom"

於是乎可以稱為這些為 Int literal / String literal

參考上面網站寫的

被定義出來的就要稱為該型態的literal ,在上面定義講到

“When we assign a function to a variable, it becomes a function literal. Kotlin provides 2 types of function literals.”

當我們指派一個function給一個變數,他就會成是一個function literal,或者也可以當成該變數的實例化結果(如果把他想成一個class的話,但其實這並不正確)

因此呢?

什麼是 function literal ?

也就是一個function types的常數宣告結果

或者是有兩個東西在kotlin中就被稱為function literal

也就是

lambda expression

或是

Anonymous Function

沒有名稱的function

不得不說這是我第一次看到有這樣的寫法,也就是一個沒有function名稱的function,並且可以透過變數來儲存

Function type

Function literals with receiver就是這樣來的https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver

官方範例就是用html

這樣的使用方式,大部分也被用在type-safe builders 的模式中

function literals with receiver it is possible to create type-safe, statically-typed builders in Kotlin.Type-safe builders allow creating Kotlin-based domain-specific languages (DSLs) suitable for building complex hierarchical data structures in a semi-declarative way

因此這模式就很適合拿來寫DSL語言的方式進行定義,譬如

html{
p{
+"Title"
}
}

如果是從java剛入手的人一定會一頭霧水,啥?這是什麼操作 ,現在你知道原因跟寫法為什麼可以寫成這樣了,但大致上是這樣的概念。

因此剛剛那整段程式碼可以看做成

或是

衍生應用

那看看這個範例, head { } / body{} 這些我都懂了,但那個 +”Xml encoding ..” 是什麼意思? string 是要怎麼用 +????

如果有略懂kotlin就會知道kotlin是可以重寫運算元的

So basically, you just put a string inside a tag body, but there is this little + in front of it, so it is a function call that invokes a prefix unaryPlus() operation.

這解釋了為什麼可以

+ ”This is”

這樣的寫法,更進一步

That operation is actually defined by an extension function unaryPlus() that is a member of the TagWithText abstract class (a parent of Title ):

operator fun String.unaryPlus() {
children.add(TextElement(this))
}

So, what the prefix + does here is wrapping a string into an instance of TextElement and adding it to the children collection, so that it becomes a proper part of the tag tree.

透過這樣定義string的+寫法,他會再+的時後轉變成

產生一個

val textElement = TextElement(this) // this也就是那串字串 "This is"

然後再透過

children.add(textElement)

清楚一點來看是

operator fun String.unaryPlus() {
val textElement = TextElement(this)
children.add(textElement)
}

也就是上面這個定義等同於這樣的描述

+ " This is kotlin”

所以也才能透過

這樣的寫法達成再kotlin中可以寫成類似html的語法,再同一個語言中你可以用kotlin去解決問題,也可以使用類似html語法去建立UI.

以上是個人查看後的一點心得,很多用詞不是很精準,如果有任何錯誤歡迎提出建議修正,感謝各位。

延伸閱讀

--

--

JLin
JLin

Written by JLin

台中 / JAVA / Android /Kotlin / Kotlin Native 對於Kotlin衍生的JVM等技術 Compose for web / desktop / Ktor Server,生成式AI (Gemini/OpenAI)各式應用, 都有小興趣

No responses yet