Matrix 首页推荐 

Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。

文章代表作者个人观点,少数派仅对标题和排版略作修改。


前言

基于 Jupyter 等即时的编程工具,减缓「编译」「程序管理」「IDE 配置」对编程本身造成阻碍。从而实现快速上手编程语言。

免责声明:「函数式语言」不在本文讨论范畴,只是简单说一说我日常研究用到的一些语言的速成途径。此外,本文重点仅仅停留在「理解一门编程语言语法和基本使用」,复杂的场景不进行讨论分析。

前些日子写了一篇文章,简单说了一下自己之前英文速成的一套方案:让语言学习更简单的 WordFlow。今天在火车上的时候,想到当时挖的一个坑,于是打算填了。

第一门编程语言

对于大部分编程和科研人员,第一门接触的编程语言大概率是大学第一年学习的「C 语言编程」。回顾一下当时的学习,可以说很多场景也是比较「莫名其妙」。我依稀记得自己当年最早用纸和笔写代码,经历一段时间之后学习安装「DEV C++」,学了一些「虽然不明白为什么要这么用,但是确实可以跑起来」的「技术」。但总之,自己就懵懵懂懂的学会了用 C 解决自己科研生活中的一些问题。

但是不可置否的是,我们在那一门课程的学习过程中,确实遇到了很多「本不应该在那门课程上解决的问题」。比如我对系统的最早认识、对编译的概念也是在那门课程中逐渐学习的。而这些事情,本应该在 Introduction to Computer System 或者 Introduction to Computer Science 这样的课程结束之后。除此之外,在我们学习最初的时候,最先不得不接触 #include<stdio.h>int main(int argc, char **argv) 之类后续学习了比较长时间之后才能理解的概念。所以实际上,学习的过程并不是很平滑。不过还好,作为大学的入门课程,他的考核过程也只是笔试。通过暴力记忆和理解程序语法就可以通过考试了。

但其实,在这门课程之后,我们大脑里建立了许多「Hidden Layers」,这在我个人看来是最有价值的一部分。在之后学习 Python 和其他语言的时候,有了「变量」「分支」「循环」「函数」等概念,可以将知识进行有效的迁移。以及如何用「编程解决问题」的思考模式,会长期持续地影响我们之后的学习过程。回顾这些经历,一个自然的想法也孕育而生,能否将最单纯的编程学习过程独立出来,用最快的方式去理解一门程序语言?

Jupyter, and more on Jupyter?

言已至此,大家也大概可以猜到如何更快更直观地学习了。编程的学习过程无法逃避「动手实践」这一最重要的环节。如果将「配置环境」,「编译调试」,「运行代码」的流程压缩简化到最简,不会对学习过程产生阻碍,就可以提升学习的流畅度了。

所以从学习层面上,Python 这类解释性语言有一些天然的优势。配合上 Python 的最好用的工具:Jupyter,执行代码就变得更加直观。可以把自己在各种视频和书籍中的代码直接复制过去执行,从而理解各种复杂的语法。Jupyter 的各种教程网上已经很多了,这里不做赘述。但是,Jupyter 本身作为学习工具,可以添加 Markdown Blocks 作为笔记,可以记录代码和运行结果,方便自己之后理解复习,方便打包共享。这些优势如果只能为 Python 服务,属实有点浪费。

所幸的是,Jupyter 的核心,「Jupyter Kernel」是一个可以替换的模块。一个非常常用的功能:「Bash Kernel」。可以方便我们在 Python Script 之外添加 Bash Script 作为辅助,提供更加便捷的系统交互。Jupyter Bash Kernel 中提供了教程作为参考。简单来说,使用:

pip install bash_kernel
python -m bash_kernel.install

即可完成 bash kernel 的安装。

同理,对于一些其他的语言,Julia 有 IJulia.jl;Go 有 gophernotes;Swift 有 swift-jupyter

虽然利用 Jupyter 学习新语言多快好省,但是也不得不说一些缺点:

  1. 部分语言的 Jupyter 配置过程比较复杂,反而会成为学习上的阻碍。安装时候建议参考相关的视频教程进行操作。例如 rust 的 evcxr、 JS 的 ijavascript、Java 的 IJava。如果自己配置还有一些困难,建议找有经验的朋友配置,或者在 Colab 中找对应已经完成配置的环境。
  2. 简单的上手语法之后,Jupyter 并不能替代学习者对于项目构建过程的理解。某种意义上学会的是语法八股,做点 LeetCode 之类的小练习可能尚可,可是实打实的进行应用就存在一些问题。因此不能过度依赖。

不过,诸位可能发现我没有提本文之前提过的主角:C++。C++ 确实没有一个好用的 Jupyter Kernel,因为一个强大的组织做了一个神奇的工具: ROOT。

ROOT

在本科快毕业的时候,我和一些天文系的同学聊天,聊起了他们用的一款神奇工具:ROOT。着实惊为天人,让我相见恨晚。ROOT 可以简单理解成一个「编程了解释语言的 C++」,由 CERN(The European Center for Nuclear Research)早在上个世纪就提出了开发计划。开发之初的想法非常简单,就是为了方便科研人员进行数据分析处理,而有一些科研人员更习惯用 C++,于是 CERN 就维护了这么一个神奇的工具。

相信熟悉编译原理的朋友也能理解这件事情本身的复杂性。C++ 的语法并不适合编程一个解释性语言,而且要适配现有的编译器,适配多样的 C++ 语法也绝非易事。而且 CERN 的项目组至今保持活跃,2015 年还开发了 Jupyter 模块。

这里也把 ROOT 的使用方法分享给大家。

ROOT 安装

ROOT 有着极度简化的安装流程,在各个平台上,基本上只需要一两行命令就能完成安装 ROOT install。例如 MacOS 上只需要:

brew install root

而 Ubuntu 只需要:

sudo snap install root-framework
snap run root-framework

ROOT CLI 直接使用

命令行 ROOT 的使用的方法也和 Pyhton 非常类似。安装完成后,输出了和 Python CLI 类似的交互:

输入 .demo 可以看到一些可交互的参考案例:

和 Python 一样,也有类似的快捷键操作:

  • Ctrl + D:退出
  • Ctrl + C:终端当前执行的命令
  • Ctrl + R:检索历史
  • Ctrl + P:上一条命令
  • Ctrl + N:下一条命令(使用 Ctrl + P 之后使用)

一些常用的指令是使用 . 前缀说明的,例如 .help。ROOT 也保留了传统编译性 C++ 的一些特写,例如可以使用 .O0.O3 实现 O0-O3 的优化,也可以使用 > 完成重定向,使用 stateundo 实现倒带回溯。

到这里还只是「ROOT 常态发挥」的范畴,接下来是是「ROOT」的仙术时间。

ROOT 仙术

在施展仙术之前,先把 ROOT的 的 Jupyter 配置好,方便之后编辑测试。

首先在 Python 中测试 ROOT 的可用性,直接 import ROOT 是不能直接使用的。但 ROOT 并不是通过 pip 进行安装,而是:

source /opt/homebrew/opt/root/bin/thisroot.sh

而在 Linux 下可能是:

source /usr/local/root_install/bin/thisroot.sh

需要找出 thisroot.sh 的路径,如果不确定,也可以通过 which thisroot.sh 进行确定。

之后在 Python 中 import ROOT 进行测试:

Tips:Python 版本过新可能不适配:

这种时候适当降低 Python 版本即可。建议使用 Pyenv 进行管理。

之后在 Notebook 中,import ROOT 之后就可以使用 ROOT 了。可以在一个 block 前使用 %%cpp 声明模块使用 C++。

可以使用 ROOT 中的统计函数:

更离谱的是,可以直接使用 Python 调用自己写的 CPP 模块1

对于日常测试一些简单的函数模块也非常好用。作为一个 CERN 的御用数据分析器,在 C++ 的基础上实现了类似 Matplotlib 的功能,可以生成许多图表:

流程图


可交互的统计图表

更多的好用功能可以在 ROOT 的文档里继续挖掘。近期有时间的话会整理类似 Matplotlib Examples 一样的页面,方便自己和别人查阅。

Interpreter is not panacea

解释器可以简化学习过程,但不是万能的。深入理解编程语言的底层原理对于学好一门语言至关重要,例如对于数组的使用,需要理解内存机制和空间局部性。在此基础上,还可以学习更复杂的高级用法,如多维张量存储、超大数组、文件系统映射到数组等。所以,最后还是要在此重新声明,工具的作用是有限的,还是需要进行踏实的学习。

> 下载 少数派 2.0 客户端、关注 少数派公众号,解锁全新阅读体验 📰

> 实用、好用的 正版软件,少数派为你呈现 🚀