又一篇写给小师妹的Scala学习笔记·一

每天两页,分享《Programming in Scala》的心得。

这个系列之前其实写过。具体可以看:

写给小师妹的Scala学习笔记·开篇
写给小师妹的Scala学习笔记·二

当时是为了快速“学会”Scala,选择了疾风式的搞法,几周就撸完一本书。

这次我们慢下来,找一本Scala作者自己写的书,仔细品一品Scala的设计哲学,并且以日记的形式记录一下所思所想。

以下是正文部分。

2022-01-02

今天读的这一章的大标题叫做“ A Scalable Language”。Scala这个名字,源于作者希望创造一种Scala-ble的语言。

接下来,他简要的介绍了Scala的几个特性:

首先,它是一种运行在JVM上的语言,因此和Java具有“无缝”的交操作性。借助于Java强大的生态,可以少造无数轮子。当然像Groovy、Clojure等等都有这样的特性。

其次,Scala兼有面向对象和函数式2种编程范式(这一点其实是相当不常见的),而且是一门静态类型的语言(所谓动态一时爽,重构火葬场,静态语言,可以让编译器替你干不少脏活累活)。函数式的一面使得它易于构建小组件,面向对象使得它可以用来构建大型程序。

接下来作者强调,编写Scala代码的过程是“fun”的。并通过一个Map的例子,作者展示了,Scala具备类型推导能力和易用的API。

var captial = Map("US" -> "Washington", "France" -> "Paris")
captial += ("Japan" -> "Tokyo")
println(captial("France"))

比如,不需要多余的分号,不需要声明Map<String, String>这样的类型,初始化时可以直接设置2个键值对进去,而不用单独调用put方法。

对比一下原生Java的写法:

Map<String, String> captial = new HashMap<>();
captial.put("US", "Washington");
captial.put("France", "Paris");

captial.put("Japan", "Tokyo");
System.out.println(captial.get("France"));

2022-01-03

今天读的这一节的小标题是“A language that grows on you”,翻译过来应该是“一门会让你慢慢爱上的语言”。

接下来作者用两个例子,印证了这句话。这两个例子分别是,可自定义的数据类型(以BigInt为例)和可自定义的控制结构(以Akka的API为例)。在一番code show之后,作者都要表达一下“这些并不是语言内建(build-in)的特性,但是用起来和内建的没有区别”。

过程中,还引用了Eric Raymond《大教堂与集市》的说法,表达了Scala的设计哲学更接近于集市。

到这里,作者想表达的意思是比较明确的:Scala是一门内核极其精炼的语言,但却有着非常高的可拓展性。就好像集市一样,它并没有(也不可能)事先规划好所有的内容,但却拥有极强的演化能力。

2022-01-04

今天读的这一小节的标题是:“What makes Scala scalable?”。对于之前提到的面向对象及函数式编程再次做了个补充,并且可以说是干货满满。

首先作者讲了,Scala是OO的。而OO的本质是把数据和操作封装在一个容器中,这个容器就叫做Object。这样,操作变成了一种数据,容器本身也作为数据可以被传来传去。

同时,作者举了例子,说有些语言不是那么“纯”的OO,比如在Java里面,原始类型就不是对象(数组也不是),同时,Java还允许在class中定义静态的字段和方法。而在Scala中,任何的值本质上都是对象,甚至与1 + 2也是,它的底层是针对1这个Int调用了+这个方法,同时传入了参数2。

作者举的第二个例子是关于trait。它有点像Java中的接口,但是拥有自己的字段和方法实现。关于trait其实一直有一些困惑,希望后面的章节可以解答。

接着作者又讲到Scala是函数式的。这一段堪称“教科书”式的介绍。

作者介绍了,函数式编程的2个特点。函数是一等公民、函数调用需要做到引用透明,也就是没有副作用。

一等公民是指,函数可以在任意地方被定义(比如在一个函数里),还可以像数值一样作为入参或者返回(高阶函数)。

那什么叫有副作用的函数调用。包括:

打印日志、修改了函数的入参、从函数参数外(全局变量、bean、threadlocal)获取数据、抛出异常等等。对应的,一个没有副作用的,引用透明的函数,只有输入/输出,并且输出可以被等价替换掉。

比如1+sum(1, 1)中,sum函数如果可以直接用2替换,就说明是引用透明的。

2022-01-05

今天的这一小节,大标题是“Why Scala?”,作者从兼容性、简洁程度、高级抽象(?)和静态类型4个方面讲了,为什么要选择Scala。

第一部分是兼容性,除了前面提到的互操作性之外,还强调了,像底层的String、Int之类的都是复用的Java原生的类型。同时,Scala还通过一个叫“隐式转换”的概念,在不修改这些类源码的情况下,对这些类做了增强。

第二部分是简洁性。这个不多说了,差不多是同样功能的Java的代码量的1/4吧。后面又介绍了“trait”这个留到后面展开。

2022-01-08

中间的记录断了两天,不过问题不大。书还是在看的。

这一段,作者提到Scala是“high-level”的,实际上,作者想强调的依然是“函数式”编程范式带来的好处。

(正本清源)

函数式编程和面向对象编程并不冲突,用Java照样可以写出非常函数式的代码。

真正不太兼容的其实是描述式的风格和命令式的风格。

比如给定一个Int列表,求各元素之和。如果用命令式风格来写,起手一个sum = 0,后接一个i = 0,最后for循环收尾。

如果用描述式风格来写,“一个列表的各个元素之和” 等于 “列表的第一个元素” 加上 “列表其余元素构成的列表的各个元素之和”。

假设取列表的第一个元素用head表示,取列表的剩余元素构成的列表用tail表示。则伪代码如下:

sum(alist) = {
if(alist != empty) return 0
else return head(alist) + sum(tail(alist))
}

可以看到,描述式风格和递归是比较自然的一对组合,无怪于FP系的语言都喜欢用递归。

遵循函数式风格的另一个好处,是可以写出“引用透明”的函数。也就是说,这个函数调用的结果,可以用该函数的返回值等价的替换掉。

比如代码里有一段是:a + sum(b, c),如果b和c分别等于2和3的话,那么和直接写a + 5是等价的。或许因为这个例子太简单了,并且是数值计算,所以大部分人可以天然的写出这种引用透明的函数。

但,如果是一段业务代码,你能保证不在函数里调用Spring的bean去读写数据库吗?能保证不修改某个全局变量或者ThreadLocal吗?能保证不去调用某个入参的set方法吗?

引用透明的另一种说法是“没有副作用”,以上列的一些例子都是副作用的体现。

没有副作用的代码,易于测试和重构,也更少的引入bug。想想是不是经常发现某个字段,在经历了一系列的函数调用之后,不知道什么时候就被设置了一个不太符合预期的值,然后引出一系列莫名其妙的问题?

上面提到的最后一个例子,有一个专门的名字,叫aliasing problem,那么函数式的编程风格,是如何避免这样的问题呢?答案就是使用不可变的数据(immutable data)。

通过把一个类所有的字段都设置成final的,这个类就是一个不可变的类(如果有个字段是final的Map,非要去修改这个Map,就属于硬杠了)。

相应的,函数体里面也不再能set各种字段。一旦要改变些什么,要应该通过返回一个新的类的实例完成。

实际上对于大多数程序员来说,疑问都是,不可变的数据,能编程吗?看看Java的String,看看Spark的RDD。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,858评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,372评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,282评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,842评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,857评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,679评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,406评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,311评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,767评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,945评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,090评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,785评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,420评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,988评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,101评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,298评论 3 372
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,033评论 2 355

推荐阅读更多精彩内容

  • 缘起 前几天偶然看到我的To Do里有一条内容是关于学习Scala的。虽然记不起是为什么以及什么时候加进去的,但是...
    elon_wen阅读 396评论 0 0
  • 第二周 这一周的内容主要围绕着“函数”来进行。本来想顺着书的内容往下讲,不过那样就没有自己的东西了,所以,就想到哪...
    elon_wen阅读 141评论 0 1
  • 大数据开发中常用 Scala 进行功能开发,而且大数据处理和计算框架 Flink 和 Spark 都是基于 Sca...
    火影启源阅读 616评论 0 2
  • scala学习笔记 第2章 变量和数据类型 基本数据 scala的核心数据为四种 :字面量、值、变量、类型 值使...
    485b1aca799e阅读 2,124评论 0 1
  • Scala是一种函数式编程语言,它具有函数式编程范式的诸多特点。需要说明的是,scala并不是一种纯函数式编程语言...
    我是老薛阅读 1,956评论 0 2