访谈嘉宾:

(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系列的书吗?用来涵盖计算机科学方面的其他主题?

我希望可以!我得好好思考一下,我还可以写些什么(笑)。


——更多访谈


更多精彩,加入图灵访谈微信!