和6歲孩子的函數(shù)式編程對(duì)話
今天看到Brent寫(xiě)的一篇有趣的文章,分享給大家,尤其適合有孩子的程序員家長(zhǎng)。
昨天,我正在讀一篇關(guān)于函數(shù)式編程的學(xué)術(shù)論文,6歲的兒子朝我走過(guò)來(lái),問(wèn)道:“你在看什么呢?”
我不知道從哪里開(kāi)始給他解釋,于是決定直接了當(dāng)?shù)鼗卮穑?ldquo;我正在看一個(gè)關(guān)于自由定理的很長(zhǎng)的故事。”
他追問(wèn)到:“什么是自由定理?”
這該對(duì)一個(gè)6歲的孩子怎么解釋呢? 但是作為一個(gè)老師, 我不會(huì)在教學(xué)挑戰(zhàn)面前退縮的。
我想了一會(huì)兒,問(wèn)道:“你知道什么是函數(shù)嗎?”
他不知道。
“函數(shù)有點(diǎn)兒像機(jī)器,你可以把一些東西從一端放進(jìn)去,然后另一端就會(huì)出來(lái)一些東西。舉個(gè)例子,你把一個(gè)數(shù)字放進(jìn)去,然后比這個(gè)數(shù)字大1的一個(gè)數(shù)就會(huì)出來(lái),比如你放進(jìn)去3,出來(lái)一個(gè)4, 你放進(jìn)去6,出來(lái)一個(gè)7 。”
這對(duì)他來(lái)清晰易懂,于是我繼續(xù)解釋:“函數(shù)有類型,類型能告訴我們什么樣的東西放進(jìn)去,什么樣的東西取出來(lái)。比如你放進(jìn)去一個(gè)數(shù)字,取出來(lái)一個(gè)數(shù)字;或者你放進(jìn)去一個(gè)包含幾個(gè)數(shù)字的列表,然后也取出來(lái)一個(gè)數(shù)字。”
他很興奮地把我打斷了:“也許我可以把單詞放進(jìn)去?”
“沒(méi)錯(cuò),你可以把單詞放進(jìn)去,再把單詞取出來(lái)?;蛘哂幸粋€(gè)特殊的函數(shù)機(jī)器,可以讓你把函數(shù)機(jī)器放進(jìn)去,然后取出一個(gè)新的函數(shù)機(jī)器!”
他倒吸了一口涼氣:“一個(gè)產(chǎn)生機(jī)器的機(jī)器!”
“所以,” 我總結(jié)道,“自由定理就是你僅僅知道這個(gè)函數(shù)機(jī)器的類型,不知道它內(nèi)部到底干了啥,但是你現(xiàn)在可以對(duì)這個(gè)函數(shù)機(jī)器說(shuō)一些總是為真的斷言。”
很明顯,這遠(yuǎn)遠(yuǎn)超出了他的認(rèn)知。不過(guò)整個(gè)談話給了我一點(diǎn)靈感。
“嗨,我想到了一個(gè)好主意,” 我說(shuō),“咱們來(lái)玩一個(gè)函數(shù)機(jī)器游戲吧,我會(huì)在腦海中想一個(gè)函數(shù)機(jī)器,你告訴我想放進(jìn)去什么東西,我告訴你什么東西會(huì)從機(jī)器中出來(lái),然后你可以猜一猜這個(gè)函數(shù)機(jī)器做了什么事情。”
他立刻喜歡上了這個(gè)游戲,這對(duì)我是個(gè)巨大的“打擊”,因?yàn)樗胍恢蓖嫦氯?。昨天晚上我開(kāi)車(chē)去參加一個(gè)派對(duì)的時(shí)候在玩,我早上沖澡的時(shí)候也在玩。
到目前為止,他正確地猜出了這些“函數(shù)機(jī)器”
這一個(gè)對(duì)他有點(diǎn)難度:
我意識(shí)到在幾種情況下,他能理解函數(shù)的功能,但是不容易用語(yǔ)言表達(dá)出來(lái)。
于是我們對(duì)有些做了一些改變,一旦他覺(jué)得自己猜出了函數(shù)的功能,我們就調(diào)換角色, 由我來(lái)指定輸入,他來(lái)根據(jù)自己的理解產(chǎn)生輸出,看看和我想的對(duì)不對(duì)。
這個(gè)函數(shù)機(jī)器對(duì)他來(lái)說(shuō)出乎意料地難猜(雖然他最終猜對(duì)了),他花了很長(zhǎng)時(shí)間猜測(cè),因?yàn)樗詾闄C(jī)器會(huì)對(duì)輸入數(shù)字做點(diǎn)兒數(shù)學(xué)運(yùn)算, 所以總想找到一個(gè)“公式”。
他沒(méi)有想到的是,函數(shù)機(jī)器可以根本就不關(guān)心輸入數(shù)據(jù)。無(wú)論你輸入什么, 機(jī)器的每次的輸出都是 6 !(有趣的是,在我的函數(shù)式編程課上,很多學(xué)生在做Lambda演算的時(shí)候,也對(duì)cosntant function非常困惑。)
經(jīng)過(guò)幾輪對(duì)我的函數(shù)機(jī)器猜測(cè)之后,小家伙也想構(gòu)造出他的函數(shù)讓我猜了!有時(shí)候他的函數(shù)非常棒,有時(shí)候確沒(méi)什么意義。不管怎樣,這很有趣 !
當(dāng)他最終理解了 這個(gè)函數(shù)做的事情:
隨后,他也想出了這樣“復(fù)雜的”函數(shù):
我想這是因?yàn)樗艿搅擞變簣@課程的啟發(fā),在那里他學(xué)到了一對(duì)兒加起來(lái)等于10的數(shù)字。
這絕對(duì)是我教育孩子最好的時(shí)光之一。
我看完后覺(jué)得這游戲非常有趣,也拉著閨女玩了起來(lái)。
我們玩了幾輪以后,她開(kāi)始構(gòu)造函數(shù)機(jī)器,讓我猜。
可是玩了幾個(gè)普通的函數(shù)以后,小孩子就不按常理出牌了,比如居然給我整了一個(gè)返回隨機(jī)數(shù)的函數(shù),這可真不好猜。
還有一個(gè)非常有代表性的函數(shù)機(jī)器:
我說(shuō):10 , 她說(shuō) :1
我說(shuō):9, 她說(shuō) :2
我說(shuō):33, 她說(shuō) :3
我說(shuō):34 , 她說(shuō) :4
我一下子明白了,她這個(gè)函數(shù)不是“純函數(shù)”,是有狀態(tài)的 !
或者無(wú)意中搞了一個(gè)閉包。
這可怎么給她解釋?!
原文鏈接:https://byorgey.wordpress.com/2018/05/06/conversations-with-a-six-year-old-on-functional-programming/