C++: Variadic Template and Fold Expression are Powerful.

这两天做一个Pipeline的Framework,见识了现在C++ Generic Programming 的强大功能,比原来的 Object Oriented Programming 看上去 Cool 多了:完全没有关系的一堆类型,一样可以放在框架里操作,写出来的程序也没有任何效率的损失,看来这些年C++又进步了很多。下面简要说说我的设计。 Class BaseData 表示 Pipeline 中的一个数据节点。 Class Phase 表示针对数据的某个操作。 Phase 接受一些 BaseData 作为输入,并输出到另外一些BaseData。为了灵活和简单起见,Phase 不设任何 Virtual Method 作为接口,只要就实现一个 Run Method 即可。程序概要如下: class BaseData { public: get() … set() … }; class DataA : public BaseData {…}; class DataB : public BaseData {…}; class DataC : public BaseData {…}; […]

Use Mouse in Terminal Vim like a modern editor

现代的编辑器(Ultraeditor, Editplus) 对于鼠标的使用非常频繁,最常见的是使用鼠标单击来移动光标,鼠标滚轮来上下翻页,或者鼠标双击选中某个词,然后拷贝或者粘贴替换。我最近学到了如何在Terminal-Based Vim 中也这样操作。 首先设置Vim 在 Normal Mode 和 Visual Mode 下激活鼠标: set mouse=nv 这样我们就可以用鼠标单击或者滚轮移动光标了。另外,鼠标双击选中单词也正常工作了。 值得一提的是,我们也可以用键盘来选中一个词:假定我们的光标停在 information 这个词上(任何位置都可以),按下 viw 就可以选中整个词,这个操作不需要鼠标,在某些情况下很方便。 接下来的事情就容易了,拷贝: y 粘贴并替换当前选中的词: p  

第一代之后,基因型不再变化(Stationary GenoType Distribution)

基因 A 和 a是一对等位基因,在人群中构成了三种基因型:AA, Aa 和 aa,其中A是显性,a是隐性。在某些遗传性状比如蓝眼睛、左撇子等,基因型决定了实际表现的性状,假定A代表右撇子,a代表左撇子,那么Aa和AA都表现为右撇子,只有aa表现为左撇子。 假定这三种基因型在男性和女性中的分布概率是一样的,分别是 u, 2v, w,那么我们有: (1)   如果我们用p代表基因A在人群中的概率,我们有: (2)   同样,我们用q代表基因a在人群中的概率,我们同样有: (3)   因为我们假定男性和女性的基因型分布是一样的,那么对于下一代子女来说,因为他(她)们的基因一半来自父亲,另一半来自母亲,所以他们之中纯合基因型AA发生的概率就是继承自父亲和母亲的基因都是A的概率相乘,也就是: (4)   根据同样的道理,子女代中基因型Aa和aa发生的概率分别是: (5)   上面的公式中我们依然使用 u, v, w 代表 基因型AA,Aa和 aa 的概率,但是使用下标1来表示这是子女代。有了每种基因型的概率之后,我们可以知道子女代中实际基因A和a的分布概率是: (6)   那么再下一代的三种基因型的概率分别是多少呢,同样我们可以简单计算如下: (7)   (8)   (9)   同样,第二代中基因A和a的概率分别是: (10)   (11)   计算了这么拉拉杂杂一大堆,到底有什么用处呢?下面是关键的一步,因为我们有: (12)   显而易见: (13)   我们很容易推导出上一代的基因A的概率和下一代基因A的概率关系如下: (14) […]

C++ 的一些新感想

因为在工作中C++用的比较多,听说 C++ 17 最近又引入了很多新特性,就买了几本 C++ 的书回来看。看了一阵,感慨颇多,罗列如下: C++ 在 Library 开发人员和普通使用人员之间的鸿沟是越来越大了。新增加的很多特性都是给Library作者提供的,普通用户平时根本用不到。特别的,我以前总是以为所谓 Library 就是在语言之上提供一些包装好的功能模块,现在看到标准库中很多 Type Traits (比如 is_trivially_destructible) 都需要编译器的特殊支持才能实现,远远地超出了我以前的理解范畴。一般的 C++ 用户,如果打开标准库里面的程序想要研究一下某个特性是如何实现的,多半和天书一样看不懂。 C++ 现在的救命稻草就是运行时刻的性能了,这集中体现在C++为程序员提供的内存控制上。为此 C++ 几乎牺牲了其他可能的前进方向,并且不惜在语言上增加了巨大的复杂性。C++ 的创始人 Bjarne Stroustrup 前些年还提要在 C++ 中引入自动内存管理,现在是绝口不提了,估计搞出来也没有人用;为了更有效的支持大型对象,C++ 搞出来 Rvalue Reference 和 Move Constructor,让我这样的 C++ 的老鸟程序员也感到太过复杂;更不用提新的 std::string_view,本身大概唯一的作用就是在大字符串上搞一些子串操作比较有效率,结果强行塞进标准库,连 C++ 的资深作者 Nicolai M. Josuttis 都看不下去,在他的书中大声疾呼:string_view is considered harmful! 即便如此追求性能,看着 Programming Language Popularity Trend 上面 C++ 日渐下滑的曲线,我估计日后 […]

Vim Window Management (Vim 多窗口管理)

我一直使用Vim作为编辑器。现在大屏幕显示器越来越流行,使用Vim的时候也越来越多地同时用到多个窗口。为了能够更有效地利用多个窗口,我琢磨着写了一些脚本来更好地在多个窗口之间切换,下面把我学到的知识说一说。 首先我不会写 Vim Script,所以我的脚本都是用 Python写的,不过 Vim的 Python Interface 也很方便,就把脚本写在一个单独的 window.py 文件中,然后在 vimrc 里面加上: py3file window.py 就可以了。 要想有效的管理窗口,首先需要能够了解当前的窗口分布情况。Vim 的 Python Interface 提供了一个 vim.windows 对象,不过更好的办法是调用 winlayout 这个函数。因为 Vim 中所有的窗口都是从一个主窗口水平或者垂直切分得到的,所以所有的窗口可以表示为一棵递归二叉树。遍历这棵树就可以得到所有窗口的信息,包括其编号、大小,当前位置,父窗口以及其中显示的数据。具体的调用方法如下: winlayout = vim.eval(‘winlayout()’) 第二个非常有用的命令是 wincmd。Vim提供的绝大部分窗口管理命令都从快捷键 CTRL+W 开始,但是这个快捷键在脚本中使用起来并不方便,这个时候就可以使用wincmd。比如我们要把输入焦点切换到左面的窗口,可以使用: vim.command(‘wincmd l’) 最后就是创建新窗口和关闭当前窗口的命令,这方面Vim提供了非常繁多的命令,但是对于脚本作者来讲最实用的也就是下面几个: 关闭当前窗口:vim.command(‘close’) 关闭所有其他窗口,只留下当前窗口:vim.command(‘only’) 垂直切分在右面打开新窗口:vim.command(‘rightbelow vnew’) 垂直切分在左面打开新窗口:vim.command(‘leftabove vnew’) 水平切分在下面打开新窗口:vim.command(‘rightbelow new’) 水平切分在上面打开新窗口:vim.command(‘leftabove new’) 有了这些命令以后,我们就可以编写脚本来控制Vim的多个窗口了。我自己写了一个脚本用于管理两个Side by Side 放置的窗口,再加上一些水平切分的支持,结果挺方便的,以后有机会放到 Github 上吧。

等位基因的组合数目

假定某种形状(比如豌豆花的颜色)由一对等位基因控制,其中显性基因用字母表示,隐性基因用字母表示。显而易见,我们一共有三种可能的基因型:,分别对应红色、粉色和白色。如果某个等位基因一共有种可能的变异,即: (1)   那么一共有多少种可能的基因型呢(注意基因型 和 是一样的)? 这个问题看上去很简单,但是我自己却迷惑了很长一段时间。最后我终于认识到:在阅读 William Feller 老爷爷的概率书的这段时间里,自己在经过了相当多的训练之后,已经习惯性的去考虑样本空间内每一个样本的概率是相等的情形了,从这一点讲,那么很明显我们一共有 种基因组合的结果。但是问题是这些组合虽然每一个出现的概率相等,但是其中却有一些重复;等到我们把重复的合并以后,剩下的样本出现的概率却不相等了。具体来讲,纯合的基因型: (2)   要比杂合的基因型 (3)   出现的概率要低。具体到豌豆花的例子,也就是白色和红色出现的概率分别是 25%,而粉色出现的概率是50%。在领悟到这一点之后,前面给出的题目就很容易计算了:当某个等位基因一共有种可能的变异的时候,我们可以把所有的可能的组合排成一个 的表格,其中对角线上的基因型是纯合的,一共有个,而非对角线上的基因型是杂合的,一共有 种。考虑到杂合的基因型每种都会出现两次,那么所有不同的基因型一共有: (4)   这和William Feller 老爷爷书中给出的答案完全一致。

音乐欣赏的两个对比

以前自己都是只会打开音响听音乐,自从自己开始弹琴以后,才慢慢悟出来音乐欣赏这里面还有两个有趣的对比:第一,同样一首歌曲,听别人弹和听自己亲手弹出来的感觉,后者带来的愉悦要大得多,听着旋律与和声跟随着自己手指的动作流淌出来,即使是很简单的曲目,也很享受,要是别人弹,可能就会觉得这旋律很简单,没什么特别的。第二,钢琴想要弹到别人觉得好听要比自己觉得好听难得多,常常一段旋律自己弹得摇头晃脑,乐在其中,可是家人已经听过无数遍了,早已听得滚瓜烂熟,耳朵起茧了。 看来要想领会音乐的妙处,自己动手实践是一个好办法呀。