Programing Languages Part A Note(一):工欲善其事,必先利其器

Motivation

临近毕业季,每天在学校里面除了写论文就是改论文,生活三点一线略显无聊,于是在知乎上搜索了一下Coursera有什么近期开课的计算机神课,看到回答中提到华盛顿大学的Programing Languages并且评价颇高,果断选择旁听入坑。

Programing Languages是一门中级课程,适用于有学习过一门编程语言背景的学生,其目的是通过讲述几门小众语言来描述编程范式(其中尤其注重函数式编程范式)。整个课程分为三个部分,A部分讲述了SML,B部分讲述了Racket,C部分讲述了Ruby。

俗话说,工欲善其事,必先利其器。在学习SML之前,首先得把SML环境和文本编辑器搭起来,课程里面提倡使用的是具有“神的编辑器”之称的Emacs,当然使用别的编辑器也完全没问题,没有强制要求。

一般来说,环境的搭建和工具的流畅使用很大程度决定了学习一门语言的初期成就感,所以投入一定的时间在这上面还是很值得(比如研究Emacs的用法)。

详细的环境搭建教程可以自行查阅课程提供的material(里面记录的非常详细),我在这里只记录一下在搭建过程中遇到的问题以及是如何解决的。

Use Coursera Forum

如果遇到任何在教程中没有给出解决方案的问题,首先在Coursera Forum里面搜一下,里面基本有问题的解决方法。网页版的Coursera在一些还没开课或者刚刚开课的课程主页上,有可能没有显示论坛的入口,所以一开始我是在ios版的Coursera里面进入论坛的,后来需要在论坛上编辑回复手机版非常不方便,所以Google了一下找到解决方法,发现进入discussion forum的链接是有规律的,比如我现在上的这门课的主页是https://www.coursera.org/learn/programming-languages,只要在链接后面加上/discussions就能直接进入课程论坛了。

如果以上链接打不开,你可能需要首先学会如何科学上网。

SML Environment

按照教程在Mac OSX Sierra上安装SML v110.79完之后,然后通过sml命令启动REPL的时候遇到了一个奇怪的错误:

1
sml: unable to determine architecture/operating system

StackOverFlow上面搜了一下发现是79版本的已知bug,80版本这个bug已经修复,解决方法是用brew重装SML或者改一下SML的启动Shell文件,第二种看起来比较省事直接就用第二种吧。

打开/usr/local/smlnj/bin/.arch-n-opsys文件,在下面这个位置加入自己的Mac系统版本即可:

1
2
3
4
5
6
7
8
9
10
10*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.6
11*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.7
12*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.8
13*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.9 Mavericks
14*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.10 Yosemite
15*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.11 El Capitan
16*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.12 Sierra
17*) OPSYS=darwin; HEAP_OPSYS=darwin ;; # MacOS X 10.13 High Sierra

*) exit 1;;

Update

在最新的教程里面提示可以安装110.80版本,但是material里面打开的跳转链接似乎仍然是110.79版本,这里大家要注意一点。推荐大家尽量不要装110.79版本,因为79版本还有个bug就是基本库引用不了,在Homework 1中有一道题目的要求就是使用Int.ToString这个库函数,如果是79版本就会报错找不到这个库的路径:

1
2
3
4
unexpected exception (bug?) in SML/NJ: Io [Io: openIn failed on "/Users/jhr/Work/smlnj/osx-dist/smlnj.dst/sml.boot.x86-unix/smlnj/basis/.cm/x86-unix/basis.cm", No such file or directory]
raised at: Basis/Implementation/IO/bin-io-fn.sml:617.25-617.71
../cm/util/safeio.sml:30.11
../compiler/TopLevel/interact/evalloop.sml:44.55

在Coursera Forum里面提到更新到80版本就能解决这个问题了,在Mac上已经安装了79版本的同学只需要把80版本的pkg下载下来直接安装即可。

SML Mode Installation

SML Mode是Emacs支持SML REPL的一个插件,基本所有的Key Binding都是从M或者C开头,C就是Control这个大家都懂,但M又是什么呢?M是指Meta键,但Mac键盘上没有Meta键,可以通过将Meta键绑定到Option上面,也可以直接用Alt+b来表示Meta键。需要注意Mac系统本身也带有emacs,因此通过命令行启动的emacs默认是老版本,一些Key Binding是未定义的,可以通过Spotlight来打开新版Emacs。

通过C-x C-f test.sml打开一个命名为test的sml文件以后,再输入C-c C-s将会在Emacs底端弹出sml command,输入sml将进入SML REPL,但是此时弹出了一个很奇怪的错误:

1
2
sml command:sml
Searching for program: no such file or directory, sml

搜了一下发现是Emacs在启动的时候没找到sml命令,因此需要在Home目录下编辑Emacs的启动配置文件.emacs(其实教程里面也有提及这个问题,我看漏了。。):

1
2
3
# For Mac OSX 10.6 or later
(setenv "PATH" (concat "/usr/local/smlnj/bin:" (getenv "PATH")))
(setq exec-path (cons "/usr/local/smlnj/bin" exec-path))

编辑完成test.sml文件之后,通过C-x C-s保存文件。

Emacs Technique

屏幕快照 2018-05-31 上午9.28.04

上图是我常用的一个Emacs工作环境布局,左上角的buffer(在Emacs里面一个编辑窗口被称为buffer)是一个SML REPL,用于运行Homework的test文件;左下角的buffer是编写Homework的文件;右上角的buffer是Homework的test文件;右下角的buffer是一个Command Console,用于显示对文件进行了哪些命令操作。

首先说一下如何弄成这个环境布局:

  1. 首先通过C-x C-f打开Homework文件以及test文件,并通过C-c C-s调出SML REPL,此时Emacs上显示的是一个上下布局。

    WX20180531-100402@2x

  2. 让光标悬浮在上面的buffer中,通过C-x 3将光标停留的buffer水平切分成两个buffer;然后让光标停留在下面的buffer作同样处理,此时Emacs的一个四方格布局已经出来了。

    WX20180531-101138@2x

  3. 让光标停留在任意一个buffer,通过C-x C-b查看当前打开的所有buffer,在每个buffer中通过C-x b buffer_name切换当前buffer到对应的buffer。

    WX20180531-101423@2x

    如果想生成我上述的布局,分别是左上角的buffer(光标也要停留在左上角的buffer):C-x b *sml*;左下角的buffer:C-x b hw1.sml;右上角的buffer:C-x b test_hw1.sml;右下角的buffer:C-x b *Messages* (对应Command Console)。

环境布局弄好之后,通过鼠标点击或者C-x o就能移动光标到不同的buffer。

接下来就是Homework编写的流程了:

  1. 在Homework.sml文件编写对应的function,编写完成之后记得要通过C-x C-s保存,Emacs默认是不会自动保存写入的。
  2. 在test文件之中编写测试,首行通过use语句引入homework文件,保存。
  3. 在SML REPL里面通过use语句引入test文件,核对测试结果。

参考链接:Emacs Splitting Windows

有想要共同刷课的欢迎私信我,Enjoy Code。

0%