《演算法圖解》作者Adit Bhargava:插圖筆記法解除演算法的魔咒(圖靈訪談)

劉敏ituring發表於2017-03-30

訪談嘉賓:

《演算法圖解》作者Adit Bhargava:插圖筆記法解除演算法的魔咒(圖靈訪談) (Adit自畫像)

Adit Bhargava, 軟體工程師,兼具電腦科學和美術方面的教育背景,在adit.io撰寫程式設計方面的部落格。

因為愛好,Adit踏入了程式設計殿堂。Visual Basic 6 for Dummies教會了他很多基礎知識,但始終對演算法沒搞明白。直到遇到一位優秀的演算法教授後,他才認識到這些概念是多麼地簡單且優雅。

幾年前,他開始在adit.io上撰寫圖解式博文,介紹函數語言程式設計、Git、機器學習和併發。圖解式寫作風趣幽默、化繁為簡、清晰明確,受到大量讀者的喜愛。


我們主要聊了些:

  • 為什麼要寫這樣一本萌萌的演算法入門書
  • 封面插畫背後的故事
  • Adit神祕的演算法導師
  • Adit最喜歡的演算法
  • 評判演算法的重要指標
  • 程式設計學習低齡化

英文版

為什麼想寫這樣的一本入門書,充滿了有趣的場景和可愛的手畫插圖?

學習一些新事物的時候,我自己通常會做筆記,因為這可以幫助我學習。比如,下面是我學習《抽象代數》時的原版筆記。有趣場景加上手畫插圖是我一直使用的學習技巧,我認為它對其他人也會同樣有用,所以寫了這篇博文。看了部落格文章,人們挺喜歡的,所以我想做成一本相同風格的書可能會很好。

(一起感受下,Adit的天才圖解技能之Monad!)

學習 Monad的渠道:

  • 取得電腦科學專業的博士學位。
  • 壓根兒不學。這裡根本用不到那些條條框框!

Functor 將一個普通函式應用到被封裝的值上:

enter image description here

Applicative 將一個封裝的函式應用到封裝的值上:

enter image description here

Monad 將一個 “接受普通值並回傳一個被封裝值” 的函式應用到一個被封裝的值上,這一任務由函式 >>=(讀作 bind)完成。聽起來似乎很拗口,讓我們來看個例子吧,還是熟悉的 Maybe

enter image description here

假設 half 是隻對偶數感興趣的函式:

half x = if even x
     then Just (x `div` 2)
     else Nothing

enter image description here

如果扔給 half 一個封裝的值會怎樣?

enter image description here

這時,我們需要用 >>= 把被封裝的值擠到 half中。猜猜>>= 的照片:

enter image description here

再看看它的效果:

> Just 3 >>= half
Nothing
> Just 4 >>= half
Just 2
> Nothing >>= half
Nothing

這其中究竟發生了什麼?Monad 是另一種型別類,這是它定義的一部分:

class Monad m where
    (>>=) :: m a -> (a -> m b) -> m b

下圖展示了 >>= 各個引數的意義:

enter image description here

下面的定義讓 Maybe 成了 Monad:

instance Monad Maybe where
    Nothing >>= func = Nothing
    Just val >>= func  = func val

來看看執行 Just 3 時發生了什麼:

enter image description here

如果傳入 Nothing 就更容易了:

enter image description here

你還可以把這些呼叫過程連起來,比如執行 Just 20 >>= half >>= half >>= half 會得到 Nothing

enter image description here

enter image description here

太棒啦!

(節選自Adit的文章Functors, Applicatives, And Monads In Pictures

從書封看,我以為《演算法圖解》的手繪插圖是老鼠系列的。似乎並沒有,還有其他的形象像綿羊、鳥、兔子等。為什麼要把那張照片放在書封上?

我希望我有一個更好的答案給你!Manning選擇了封面上的圖片,他們真的很喜歡這張圖。但內容方面,Manning給了我很大的主動權。

很多讀者非常好奇你在作者簡介部分提到的演算法老師。這位優秀的老師如何把概念變得簡單又優雅,你能分享一些他/她的教學方法嗎?

當然!她的最有效的教學方法是逐行過程式碼、精講演算法。遇到難的部分,大家很容易就選擇跳過。但為了學習,應該在難的部分放緩腳步,仔細研究。對每一個演算法,她都會慢下來,一行一行過程式碼,解釋每一行的作用。我在書裡面也試著做同樣的事情。在遞迴部分,我逐行分析程式碼,展示如何進行棧的改變。我覺得深入細節是非常重要的。

你最喜歡的演算法是什麼?為什麼這個演算法給你留下如此深刻的印象?

在《演算法圖解》這本書裡,我好幾次提到過我有多愛“圖演算法”。圖是一種很神奇的結構,絕對無處不在。我覺得,只用圖演算法就能解決很多的問題。最近,我和朋友去吃午飯,吃飯時一個人說:“我敢打賭,我可以在15分鐘內教會你範疇理論。”其實,我並不知道任何關於範疇論的東西,但我知道圖和抽象代數,有了這些知識我實際上只花了不到5分鐘的時間就理解了範疇論。工作中,我把一些枯燥的任務進行自動化,因為我知道怎麼運用拓撲排序和橫向優先搜尋。

有時候,操作時間短並不一定意味著良好的表現。除了時間外,還有哪些維度來評判演算法?

是的!我認為“易用性”是一個非常重要的指標。比如,機器學習裡有很多技術比K最近鄰演算法更先進。但如果要開始處理問題,你可能會利用K最近鄰演算法,即使你是一名機器學習專家。如果這個演算法很容易理解,bug可以藏身的地方就變少。一旦開始進入更復雜的演算法像神經網路,你需要花更多的時間找出bug的原因,因為需要檢查的可能隱藏bug的地方會更多。選擇演算法和考慮執行時間的時候,考慮程式設計師的能力也很重要!容易理解的程式碼更容易維護,更有可能避免bug。

一些青少年實際上也在讀你的書。你怎麼看較早學習演算法,比如小學階段甚至更早?

我認為這很有意義。程式設計是一種創造力,就像繪畫和音樂。我開始學程式設計就很早,會做視訊遊戲和動畫。越早學習程式設計,就能越早應用在自己的專案!

你會堅持寫Grokking系列的書嗎?用來涵蓋電腦科學方面的其他主題?

我希望可以!我得好好思考一下,我還可以寫些什麼(笑)。


——更多訪談


更多精彩,加入圖靈訪談微信!

相關文章