├── 2014亚洲超级计算预赛题目.md
├── Introduction.md
├── Markdown
├── Markdown.md
└── markdown快速查阅.md
├── README.md
├── Rumeo.png
├── UnderstandingGIL.md
├── courseNote
├── usercasediagram.md
└── 大型主机实验.md
├── debug
├── 16and128.md
├── mkview.md
├── npm_install_Error.md
├── pipInstallInVirtualenv.md
└── why_all_my_MPI_process_has_rank_0.md
├── feeling
└── rain.md
├── lvthw.md
├── man.md
├── tips
└── style.md
├── tools
├── goodinputmethod.md
├── idea.md
├── installWPS.md
├── pandoc.md
└── vimium.md
├── translation
├── pythonFAQPassing.md
└── 受检异常带来的问题.md
├── tucao
└── 2014-5-7.md
└── whatWillTheNumIsInC.md
/2014亚洲超级计算预赛题目.md:
--------------------------------------------------------------------------------
1 | 2014亚洲超级计算预赛题目
2 | ====
3 |
4 | 原题是英文的,这里特地翻译成中文,并加以解释。
5 |
6 | 第一题,讲学校在超算方面的教育和科研等等,大概是写一篇东西。
7 | 我就不详细解释了。
8 |
9 | 第二题:HPL Test
10 | ----
11 |
12 | 这个是老题了,去年第二道也是这个题。
13 | HPL是超级计算机的一个运算能力的基准测试,每年都考不奇怪。
14 |
15 | [HPL的介绍](http://www.elecfans.com/dianzichangshi/linpack.html)
16 |
17 | [HPL官网](http://www.netlib.org/benchmark/hpl/)
18 |
19 | 这里把原题翻译一下(大意):
20 |
21 | 在预赛阶段的HPL测试,每支队伍可以在自己的硬件平台上测试并优化HPL,以达到最佳性能。
22 |
23 | 提案中必须包括软件平台(操作系统,编译器,数学库,MPI软件和HPL版本等等),测试步骤,表现评估,优化方法,问题及解决方案等等。最好可以深入分析HPL算法和代码。
24 |
25 | 运行方式?
26 |
27 | 需要有并行软件和包括BLAS(Basic Linear Algebra Subprograms [基础线性代数程序集](http://zh.wikipedia.org/zh-cn/BLAS)
28 | ,维百里终于有相关的条目了)的数学库。
29 | 据推荐,有一个GOTO数学库在这方面表现最佳。
30 | 不过我们选择的是intel的MKL数学库,因为资料比较多。
31 |
32 | 优化方法?
33 | 按目前查到的情况,大概有以下几种:
34 | 1. 在文件的第一部分为配置文件hpl.dat的配置。在下面的部分,
35 | 注意设置如下的各项:
36 |
37 | N: 给出有最高GFLOPS值的矩阵规模或问题规模。
38 | 正如拇指规则,对于最好的性能,此数一般不高于总内存的80%。
39 |
40 | NB: 对于数据分配和计算粒度,HPL使用的块尺度NB。
41 | 小心选择NB尺度。从数据分配的角度看,最小的NB应是理想的;
42 | 但太小的NB值也可以限制计算性能。
43 | 虽然最好值取决于系统的计算/通信性能比,但有代表性的良好块规模是32到256个间隔。
44 |
45 | “根据我的测试经验,NB大小的选择还跟通信方式、矩阵规模、网络、处理器速度等有关系。
46 | 一般通过单节点或单CPU测试可以得到几个较好的NB值,但当系统规模增加、问题规模变大,有些NB取值所得性能会下降。
47 | 所以最好在小规模测试是选择三个左右性能不错的NB,在通过大规模测试检验这些选择。”
48 |
49 | 嗯……还是干脆给链接吧>.<
50 | [链接](http://longgeek.com/2012/07/18/hpc-high-performance-cluster-linpack-optimization-method/)
51 |
52 | 2. 使用性能优异的BLAS库,尤其是dgemm函数表现优异的
53 |
54 | 第三题: The Quantum Espresso(QE) Test
55 | ----
56 |
57 | 提案中必须包括软件平台(操作系统,编译器,数学库,MPI软件和QE版本等等),测试步骤,表现评估,优化方法,问题及解决方案等等。最好可以深入分析QE算法和代码。
58 |
59 | 其实就是跟HPL的一样啦>.<
60 |
61 | 下面的不一样:
62 |
63 | 由于QE提供了不同的workloads,所以规定各个参赛队伍必须使用下面的[两个workloads](http://www.asc-events.org/ASC14/032123hiacscdioeucoqe92312iasd.pdf)
64 |
65 |
66 | 第四题: Design and Optimization of 3D-EW on CPU+MIC platform
67 | ----
68 |
69 | 在CPU+MIC混合平台上设计并优化3D弹性波模型(3D—EW)代码。
70 |
71 | 3D—EW是一种通过推演波动场在各向同性的弹性介质中模拟弹性波传播的方式。
72 | 在代码中,P波和S波分别独立地被模拟,以此来更好地了解在弹性介质中,P波和S波的传播方式。
73 | 模拟方式通过高位有限差分来模拟弹性波的传播。
74 |
75 | 关键字:**弹性波,P波与S波分别模拟,有限差分**
76 |
77 | 相关程序的介绍:
78 |
79 | 1. 程序下载地址:[这里](http://www.asc-events.org/ASC14/032123hiacscdioeucoqe92312iasd.pdf)
80 |
81 | 2. 内容:
82 | * 3d2rewq.tar: 3D-EW source code
83 | * verify.tar : result verification code
84 |
85 | 3. 3D-EW source code
86 | * run
87 |
88 | make
89 | ./3d2rewq input_file output_file log_file
90 |
91 | * test cases:
92 |
93 | workload1 para1.in
94 | workload2 paea2.in
95 |
96 | 4. Verification
97 | * run
98 |
99 | make
100 | ./verify record1_old.dat record1_new.dat
101 | (输出结果满足L1 < 0.00001 并且 RMS < 0.00001)
102 |
103 | 5. 提交内容跟前两项相同。
104 |
--------------------------------------------------------------------------------
/Introduction.md:
--------------------------------------------------------------------------------
1 | 新年给自己的礼物,用Markdown写自己的一些小想法(当然,这里写的只是些与编程有关的事情)。
2 |
3 | HELLO WORLD
4 | =
5 |
6 | 一楼祭天地
7 | -
8 |
9 | 二楼留自己
10 | -
11 |
12 | 为什么写博客?
13 | -
14 |
15 | 因为想写呗。给自己一个可以默默吐槽的空间。
16 |
17 | 为什么用Markdown?
18 | -
19 |
20 | 因为Markdown轻便,而且github支持。
21 | 当然我也可以拿出众多的证据说明Markdown的好——事实上我正在写一篇关于Markdown的文章
22 |
23 | 你这算是博客吗?
24 | -
25 |
26 | 你说不算就不算咯。反正就是一些放在网上的文本文件罢了。
27 |
28 | That's ALL, thanks
29 | -
30 |
--------------------------------------------------------------------------------
/Markdown/Markdown.md:
--------------------------------------------------------------------------------
1 | # 什么是Markdown? #
2 |
3 | 可以参见维基百科上的介绍:[Markdown](http://zh.wikipedia.org/wiki/Markdown)
4 |
5 | ***一言以蔽之,markdown是一种轻量级的标记语言,类似于电子邮件采用的标记形式,可以集成html语句。***
6 |
7 | # 为什么用Markdown #
8 |
9 | Markdown可以让你流畅地写出带丰富格式的文字来,同时不需要复杂的标记或者特殊的编辑器。
10 | 是自由散漫、想啥写啥的博主的最佳选择。
11 | 当然了,你可能会怀疑这一点。毕竟,如果我宣称葡萄最好吃,就一定会有人举出苹果、荔枝等其他水果来驳斥我的说法。
12 | 所以我要想捍卫葡萄最好吃的地位,我就得拿各类水果来进行比较,最后来证明我家的葡萄是最棒的。
13 | 那么,让我们不厌其烦地比较一下吧:
14 |
15 | ##Markdown VS XX##
16 |
17 | ###1. txt
18 |
19 | txt是一种纯文本格式,额,既然是一种纯文本格式,显然不能表达太多内容。。。
20 | 比如我们在回复别人时,往往也会需要用些表情卖下萌的。
21 | 如果使用了unicode编码,那么还可以用些颜文字;如果是ascii编码,那么只好浪费一些空白了。比如下面这个
22 |
23 | 11111 1111111 1111 1111 1111
24 | 11111 111111 111111 1111 1111
25 | 111 111111111111111 1111 1111
26 | 111 1111111111111 1111 1111
27 | 111 11111111111 111 111
28 | 111 1111111111 111 111
29 | 111 11111111 111111111111
30 | 11111 111111 111111111111
31 | 11111 1111 1111111111
32 |
33 | 一般打出了这个字样的,都会收到女神的好人卡,
34 | 因为一看就知道发信息的人缺乏[艺术细胞](http://www.guokr.com/article/94559/)。
35 | 如果没有受到好人卡,那么请珍惜那个女生,她一定在之前就默默地爱着你,而且不会因发现了真相而背你而去。
36 |
37 | **结论:没有可比性**
38 |
39 | ###2. RTF
40 |
41 | RTF知道的人貌似不多。那么按照惯例,上[链接](http://zh.wikipedia.org/wiki/RTF)
42 |
43 | RTF是一种富文本格式,大概是一个\反斜杠打头,然后是一些复杂的控制命令行。这类格式可以被**字处理软件**识别
44 | 首先呢,富文本格式跟Markdown这种轻量级的没有可比性,毕竟Markdown不需要一个**字处理软件**来解析。
45 | 其次,RTF文件,默认是作为二进制文件进行处理的,就像.doc或.odt一样。
46 |
47 | **综上所述,RTF与Markdown没有可比性。**
48 |
49 | ###3. tex
50 |
51 | tex就是大名鼎鼎的TEX排版软件的文件格式。
52 | 啊不,为免受到鄙视(以及让Knuth教授满意),应该是TEX
53 | (这里体现了Markdown文件的一个好处,就是可以与html标记集成。比如这里可以写做T/E/X)
54 | 这个格式跟前文的RTF一样,也是用反斜杠打头,接着是一些复杂指令。当然比起RTF,tex可以支持更加丰富的语法形式。
55 | 你完全可以把tex当作印刷排版的xml。所以这里有一个问题,对于web文本来说,它太过复杂了。
56 | 事实上,按照笔者的看法,tex文件比html还要难懂多了。
57 |
58 | **结论:用得着tex么?**
59 |
60 | ###4. 其他轻量级标记语言
61 |
62 | 除了Markdown,还有其他的轻量级标记语言,比如rst(reStructedText),等等。
63 | 而且其他轻量级标记语言也得到了很多便利的支持,比如spinx可以将rst转化为PDF等等更加可读的方式,emacs有一个org-mode的插件用来管理日程。
64 |
65 | 那么为什么我选择了Markdown呢?
66 |
67 | 一个重要的原因是Markdown是我遇到的第一个轻量级标记语言……
68 | 当然更为重要的原因是,但凡是编程的网站,都会提供支持Markdown的编辑框。
69 | 而且比起其他的轻量级标记语言,Markdown的使用范围是最广的。
70 | 就凭这两点,我决定使用Markdown来写我的文章,还有各种文档。
71 |
72 | **结论:我还是倾心于Markdown,虽然别的轻量级标记语言也有它们的美**
73 |
--------------------------------------------------------------------------------
/Markdown/markdown快速查阅.md:
--------------------------------------------------------------------------------
1 | #Markdown语法简介
2 | ---
3 | **快速学习Markdown,或者供Markdown书写者查阅**
4 |
5 | ---
6 | ##相关资源链接:
7 |
8 | [Markdown语法介绍](http://wowubuntu.com/markdown/)
9 |
10 | [轻量级标记语言介绍](http://www.worldhello.net/gotgithub/appendix/markups.html)
11 |
12 | ---
13 | ##目录
14 |
15 | 1. ###[区块元素](#blockElement)
16 | 2. ###[区段元素](#sectionElement)
17 | 3. ###[链接](#link)
18 | 4. ###[其他](#other)
19 |
20 | ---
21 |
22 | ##区块元素
23 |
24 | 1. 段落
25 |
26 | Markdown的段落由一个空行来分割。
27 | 就是说,如果没有使用空行,换行符将被忽略。
28 | 另外,无法使用空格或者制表符来进行段落中的缩进。
29 |
30 | 2. 缩进
31 |
32 | 缩进大概需要这样:
33 |
34 | 缩进大概需要这样:
35 |
36 | ` `在html中是空格转义之后的形式。
37 | 记住,Markdown中支持html的语法,所以可以很方便(或者不得不)用html扩充。
38 |
39 | 3. 标题
40 |
41 | 两种标题语法:
42 |
43 | 1. 底线形式:
44 |
45 | 任意数量的=代表最高阶标题
46 |
47 | 任意数量的-代表第二阶标题
48 |
49 | 例如:
50 |
51 | This is H1
52 | ====
53 | This is H2
54 | --
55 |
56 | 2. \#号形式:
57 |
58 | 行首插入 1 到 6 个 # ,对应到标题 1 到 6 阶
59 |
60 | 例如:
61 |
62 | # This is H1
63 | ## This is H2
64 | ###### This is H6
65 |
66 | 可以选择是否闭合#号,不过只是纯装饰作用,不会影响最终解析的结果
67 |
68 | 4. 列表
69 |
70 | 1. 有序列表
71 |
72 | 使用数字点号空格的方式声明。
73 |
74 | 例如:
75 |
76 | 1. 第一
77 | 2. 第二
78 | 3. 第三
79 |
80 | 2. 无序列表
81 |
82 | 使用*或+,-三种符号作为列表标记。
83 |
84 | 例如:
85 |
86 | * 嗯
87 | * 哼
88 | * 哈
89 |
90 | 或者:
91 |
92 | + 嗯
93 | + 哼
94 | + 哈
95 |
96 | **注意!**
97 |
98 | 如果列表各项中插入别的Markdown区块元素,将会使列表顺序失效!
99 | **处理方法**:在区块元素(包括文本段落)前加四个空格或者制表符进行缩进。
100 | 注意是在原来的基础上增加缩进。
101 |
102 | 5. 区块引用
103 |
104 | 同电子邮件一样,使用>的方式。
105 | 比如:
106 |
107 | > 先弄清楚事实,歪曲是之后的事。
108 | > —— 马克·吐温
109 |
110 | 注意,在引用区块中可以使用其他Markdown语法。
111 |
112 | 同理,如果要嵌套引用,就增加一个>
113 |
114 | > 让我们看看一个嵌套引用
115 | >
116 | >> 这是一个嵌套引用
117 | >
118 |
119 | 注意,如果在列表中使用引用,需要再增加缩进。
120 |
121 | 6. 代码区块
122 |
123 | 加四个空格或者制表符进行缩进。
124 | 就是这么简单。
125 |
126 | 注意,如果在列表中使用引用,需要再增加缩进。
127 |
128 | 7. 分割线
129 |
130 | 在一行中用三个以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。
131 |
132 | ---
133 |
134 |
135 | ##区段元素
136 |
137 | 1. 强调
138 |
139 | 使用`*`或`_`包围一段文本来生成``的效果。
140 |
141 | *斜体*
142 |
143 | 使用`**`或`__`包围一段文本来生成``的效果。
144 |
145 | **加粗**
146 |
147 | 如果你的 * 和 _ 两边都有空白的话,它们就只会被当成普通的符号。
148 |
149 | 2. 代码
150 |
151 | 使用反引号把行内代码包起来。
152 | 如果要在代码区段内插入反引号,你可以用多个反引号来开启和结束代码区段:
153 |
154 | `` 代码有反引号` ``
155 |
156 | 代码区段的起始和结束端都可以放入一个空白,起始端后面一个,结束端前面一个,这样你就可以在区段的一开始就插入反引号:
157 |
158 | `` `反引号` ``
159 |
160 | 3. 图片
161 |
162 | 图片链接语法分两种,行内式和参考式。
163 |
164 | 行内式:
165 |
166 | 
167 |
168 | 参考式:
169 |
170 | ![Alt text][name]
171 | [name]: /path/to/img.jpg
172 |
173 |
174 | ##链接
175 |
176 | 1. 自动链接
177 |
178 | 在网址和电子邮件地址包裹方括号,就可以生成链接。
179 |
180 | 比如:
181 |
182 |
183 |
184 |
185 | 2. 生成链接
186 |
187 | Markdown生成的链接分两种,行内式和参考式。
188 |
189 | 行内式把链接地址直接给到链接内容之后。
190 | 参考式则在最后才给出链接的索引。
191 |
192 | 比如:
193 |
194 | 行内式:
195 | [github](https://github.com)
196 | 或者加上title
197 | [github](https://github.com "github")
198 |
199 | 支持相对路径:
200 | [here](/here/)
201 |
202 | 参考式:
203 | [github][1]
204 | [1]: https://github.com "github"
205 | 或者
206 | [github][]
207 | [github]: https://github.com "github"
208 |
209 | 方括号括住的是生成链接的文本。
210 |
211 | 同时注意,参考式里冒号之后必须留空白。
212 | 而且最后面的title属性文本可以用双引号或括号包住。
213 |
214 |
215 | ##其他
216 |
217 |
218 | 可以使用\来对特殊符号进行转义。
219 |
220 | 可以在Markdown中嵌入html标记,正如这篇文章一样。
221 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | blogWithMarkdown
2 | ================
3 |
4 | write blogs in Markdown
5 |
6 | 遵循[ CC BY-NC-SA - Creative Commons Attribution-NonCommercial-ShareAlike](http://creativecommons.org/licenses/by-nc-sa/3.0/)
7 |
--------------------------------------------------------------------------------
/Rumeo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spacewander/blogWithMarkdown/e0cdcea2a123e423be8d7cb8b709152e7f27b6d9/Rumeo.png
--------------------------------------------------------------------------------
/UnderstandingGIL.md:
--------------------------------------------------------------------------------
1 | 本文是《[Understanding GIL](http://www.dabeaz.com/python/UnderstandingGIL.pdf)》的读后感。
2 |
3 | 什么是GIL呢?就是全局解释器锁。Python作为一种解释型的语言,代码需要在运行时由Python解释器进行实时解释。所以每当Python代码要想运行,需要有一个解释器实例来处理代码,比诸如C,Java之类的编译型语言多了个中间层。
4 |
5 | 这么做有一个缺陷,就是在多线程的情况下,多个线程共享同一个解释器实例,每次都只有一个线程可以被解释器所支持。于是,如果这些线程都是CPU-bound(计算密集型)的线程,那么就会产生锁争用的情况。每个线程都缺乏IO阻塞,像个吝啬鬼一样牢牢抓住自己那份解释器份额绝不分给同伴。这么一来,多线程的优势就被限制住了。所以GIL一直是Python心中永远的痛。
6 |
7 | GIL的释放需要以上两个条件之一:
8 |
9 | 1. 该线程在执行完一段(包括若干个tick)代码之后
10 | 2. 该线程进行IO操作
11 |
12 | GIL的实现是一个semaphore,包括一个mutex和cond。
13 |
14 | 获取锁时,获取mutex,如果没法得到锁,cond_wait,最后释放mutex。释放锁时,先获取mutex进行锁记录的修改,再释放mutex,然后发送cond_signal给之前因为获取不了锁而cond_wait的线程。
15 |
16 | GIL释放后,所有的线程都可以重新获取,就像抛球一样。不过有些线程就是长得高……所有的线程按优先级排队,OS会把GIL分配给优先级高的线程。
17 |
18 | Python 3.2后引入了新的GIL。添加一个全局变量用于线程间的协调。当某个线程等到黄花菜都凉了的时候,它会设置这个变量为1。当前线程会因此不得不忍痛让出GIL。
19 |
20 | 当然这个“让出”不是直接丢掉GIL那么简单。当前线程会发送一个信号,然后停下来,等待某个线程的ACK。在接到ACK之后,当前线程才会真正suspend起来。这么一来,锁争用就得到了避免。
21 |
22 | 但是这么做有一个严重的问题……作者在文中就举了个例子。如果有一个线程是CPU-bound线程,另一个线程则需要通过I/O转发一批数据,那么在新的GIL设计下,CPU-bound线程需要等到I/O线程等得心急如焚,设置了协调的全局变量时才会让出GIL。而假如这个I/O线程进行的不是阻塞I/O操作,那么每次I/O之后,GIL又会回到CPU-bound的线程手上,然后自己还要再等上很长一段时间 - 这样继续重复 - 重复……
23 |
24 | 作者提出可能的解决方法是分别对待CPU-bound线程和I/O-bound线程,并且动态调整优先级。
25 |
26 | > 注: 虽然这里讲的是python的GIL,但其实Ruby也有GIL的问题。Ruby开发者也一直准备淘汰掉GIL,使用Actor或其他的并发模型。作为一个Ruby粉,希望我大Ruby早日脱离GIL的苦海,争取向现代语言靠齐。
27 |
--------------------------------------------------------------------------------
/courseNote/usercasediagram.md:
--------------------------------------------------------------------------------
1 | 用例图速查
2 | =====
3 |
4 | 建模
5 | -----
6 |
7 | 业务建模 » 概念建模 » 系统建模
8 |
9 | 版型 (stereotype)
10 | -----
11 |
12 | 对一个UML元素基础定义的拓展,在同一个元素基础定义的基础上赋予特别的含义,使得这个元素适用于特定的场合。
13 |
14 | 类似于子类化的概念。
15 |
16 | 参与者(Actor)
17 | -----
18 |
19 | 在系统之外与系统交互的某人或某事物。用一个小人表示。
20 |
21 | 参与者是*涉众(stakeholder)*的代表。
22 |
23 | *用户(user)*是参与者的代表。
24 |
25 | *角色(user)*是参与者的职责
26 |
27 | ### 版型
28 |
29 | 1. 业务主角
30 |
31 | 用于定义业务的参与者,在需求阶段使用。
32 |
33 | 2. 业务工人
34 |
35 | 被动参与业务,没有具体目的的参与对象。他跟参与者之间的关系如同龙套与主角。注意两者间的区分。
36 |
37 | 用例(user case)
38 | -----
39 |
40 | 与参与者交互的,并且给参与者提供可观察的有意义的结果的一系列活动的集合。
41 |
42 | 1. 相对独立
43 | 2. 执行结果对于参与者来说是可观测的和有意义的
44 | 3. 必须由参与者发起
45 | 4. 以动宾短语形式出现的
46 | 5. 一个用例就是一个单元
47 |
48 | 标志是一个椭圆形
49 |
50 | ### 版型
51 |
52 | * 用例实现
53 |
54 | 用例的一种具体实现方式
55 |
56 | 关系(relation)
57 | -----
58 |
59 | 抽象出对象之间的联系,让对象构成某个特定的结构。
60 |
61 | 1. 关联(association)
62 |
63 | `————————` 直线或带箭头的直线
64 |
65 | 当用直线表示时,代表两个对象互相了解。如果只有一个箭头,则代表一个对象了解另一个。
66 |
67 | 2. 依赖(dependency)
68 |
69 | `--------->` 带箭头的虚线
70 |
71 | 描述对一个对象的修改会导致另一个对象的修改
72 |
73 | 3. 扩展(extends)
74 |
75 | 带箭头的虚线加`<>`于其上
76 |
77 | 向基本用例中的某个扩展点插入(可选或特定条件下的)扩展用例
78 |
79 | 4. 包含(include)
80 |
81 | 带箭头的虚线加`<>`于其上
82 |
83 | 在执行基本用例的用例实施过程中插入的(必需的)行为段
84 |
85 | 注意与扩展关系的区别,也即可选和必需的差别
86 |
87 | 5. 实现(realize)
88 |
89 | 带空心箭头的虚线
90 |
91 | 连接用例及其实现
92 |
93 | 6. 精炼(refine)
94 |
95 | 带箭头的虚线加`<>`于其上
96 |
97 | 用于连接基本用例和精炼用例。一个基本用例可以分解出许多更小的关键精炼用例,这些精炼用例更细致地展示了基本用例的核心业务。
98 |
99 | 7. 聚合/组合关系(aggregation/composition)
100 |
101 | 带空心(或实心,有些情况下聚合关系是这样)菱形箭头直线
102 |
103 | 这两个关系在实际上经常混为一体。
104 | 用于表示整体与部分的关系。聚合是弱依赖关系,即使整体不存在了,部分仍然存在;组合是强依赖关系。
105 |
106 |
107 |
--------------------------------------------------------------------------------
/courseNote/大型主机实验.md:
--------------------------------------------------------------------------------
1 | 课堂笔记之大型主机操作系统基础实验
2 | =====
3 |
4 | 大型主机系统基础实验的笔记。准备要考试了喔。
5 |
6 | 1.概述
7 | -----
8 | 可靠性、可用性、可服务性:简称**RAS**
9 |
10 | 初代主机 **System/360** 诞生于**1964**年
11 |
12 | z/OS的目标:
13 |
14 | 1. 多道程序设计 : 同时执行多个程序
15 | 2. 多重处理 : 多个处理器同时运行
16 |
17 | 地址空间:
18 |
19 | 1. 地址空间隔离 : 地址空间标识符(ASID)类比于进程ID(PID)
20 | 2. 地址空间通信
21 |
22 | 1. 调用一个服务请求块(SRB),一个异步过程
23 | 2. 使用交叉内存服务和访问寄存器,一个同步过程
24 |
25 | 动态地址转换(DAT)是指在存储定位过程中将虚拟地址转换成所对应的实存地址的过程。
26 |
27 | 三种寻址方式(历史遗留问题):24位,31位,64位
28 |
29 | z/OS监督作业的机制
30 |
31 | 1. 中断处理
32 | 2. 创建作业调度单元
33 | 3. 调度任务
34 | 4. 串行化系统资源之使用
35 |
36 | 中断处理中的程序状态字(**PSW**)是处理器中一个128位的数据区.当前PSW包括了下一个程序指令的地址和正在执行的程序的控制信息.每个处理器只有一个当前的PSW.
37 |
38 | 可抢占VS不可抢占
39 |
40 | 缩写| 全名 | 注释
41 | ----|---------|--------
42 | TCB |任务控制块| 在一个地址空间内执行的任务
43 | SRB |服务请求块 |在特定地址空间内执行一个特定功能或服务的程序。
44 |
45 | SRB是不可抢占的,由TCB表示的程序(比如用户程序)是可抢占的.
46 |
47 | 调度器队列
48 | 地址空间可以存在于以下4个队列的任何一个
49 |
50 | * 内就绪队列 - 在中央存储器中,等待调度
51 | * 内等待队列 - 在中央存储器中,但在等待一些事件完成
52 | * 外就绪队列 - 处于执行就绪状态,但已经被换出
53 | * 外等待队列 - 被换成并等待一些事件完成
54 |
55 | 2.z/OS交互
56 | -----
57 | 分配数据集:
58 | * 卷序列号 包含6个字符 为外部存储设备卷名 如USER01
59 | * 设备类型 一个磁盘设备的型号或类型 如3390
60 | * 等等
61 |
62 | 行命令操作
63 | * I[n] 插入n行
64 | * D[n] 删除n行
65 | * R[n] 重复n行
66 | * C[n] 后面跟着a或b,在之后或之前复制n行
67 | * M[n] 移动n行
68 | * X[n] 隐去n行
69 | * S[n] 显示n行
70 |
71 | 数据集操作
72 | -----
73 |
74 | 数据集是包含一个或多个记录的一个文件。可以被编目,编目是指可以通过名称引用数据集而不需要指定存储位置。
75 | 记录是包含数据的固定数目的字节。
76 |
77 | 三种常用数据集: 顺序数据集(PS)、分区数据集(PDS)、VSAM数据集
78 |
79 | DSAD卷用来存储数据和可执行程序(包含操作系统本身),以及用于临时工作的存储。
80 |
81 | 卷标签存储在0号柱面的0号磁道上,用于确定每个DASD卷。
82 |
83 | 数据集名可以由总长不超过44个字符、22个字段组成。其中第一个字段为高级限定词,最后一个字段是最低级限定词。字段第一个字符必须为字母或{# @ $},字段间以'.'隔开。
84 |
85 | 数据集名常见约定从略(看书上的清单)
86 |
87 | RECFM 数据集记录格式:
88 |
89 | * F 块/记录大小相同 少有
90 | * FB 定长组块 定长记录
91 | * V 变长不组块 逻辑记录即物理块
92 | * VB 变长组块
93 | * U 无定义
94 |
95 | BLKSIZE :
96 | * F/FB 物理块大小
97 | * 其它:可用的物理块的最大空间
98 |
99 | LRECL :
100 | * 逻辑记录大小
101 | * V/VB 允许的逻辑记录大小
102 |
103 | 分区数据集通过引用指向成员。成员按照字母顺序存于目录之中,但在分区数据集中的成员按照任意顺序排列
104 |
105 | 缺点:没法重用原成员的空间,必须通过重组来移除浪费的空间。PDS的目录只能存储固定数量的成员条目。
106 |
107 | 卷内容表(VTOC)是一种包含数据集标签的结构,管理数据集的存储和布置。影响了盘卷里能放的数据集数量。
108 |
109 | 磁盘或磁带上的数据集都可以被编目。包括下面三个信息:数据集名称、卷名、设备单元。使用目录可以为已经编目的任何数据集提供单元设备类型和卷名。
110 |
111 | z/OS使用一个主目录和许多与之关联的用户目录。
112 |
113 | 世代数据组(GDG)是一些历史相关的非VSAM数据集的集合,这些数据集按时间顺序排序。这个组里每个数据集与其它数据集是历史相关的。
114 |
115 | 过滤数据集:`*`至少一个限定符 `**`0个或多个限定符 `%`一个字符
116 |
117 | 数据集编辑
118 | -----
119 |
120 | UC 小写转大写
121 |
122 | SORT \<起始列 结束列 A or D\> 排序
123 |
124 | FIND 在文档中查找字符串
125 |
126 | CHANGE 查找并替换字符串
127 |
128 | LOCATE n 前往第n行
129 |
130 | CUT PASTE COPY 功能同其名
131 |
132 | 复制顺序数据集 3.3后选C
133 |
134 | 移动顺序数据集 3.3后选M
135 |
136 | JCL
137 | -----
138 |
139 | 系统规定JCL语句的长度为80列。逻辑上将这80列分成5个区域,即标识符区、名称区、操作符区、参数区和说明区。
140 |
141 | * 标识符区位于前两列,符号为`//`
142 | * 名称区第一个字符必须为字母或通配符。
143 | * 各区间以空格分割
144 |
145 | 每个作业可以由一个或多个作业步组成。
146 | 每个作业必须包含三种JCL语句
147 |
148 | 1. 作业语句 JOB
149 | 2. 执行语句 EXEC
150 | 3. 数据定义语句 DD 提供执行语句中的程序运行所需的输入和输出文件。
151 |
152 | 例子看书上。具体的不多列举了。
153 |
154 | ###作业语句
155 |
156 | 作业语句标志一个作业的开始、指定作业名并设置相关参数
157 |
158 | // JOBNAME JOB NOTIFY=&SYSUID, MSGLEVEL=(1,1)
159 |
160 | ###执行语句
161 |
162 | 执行语句标明作业或过程中的每个作业步的开始,告诉系统如何执行这个作业步。
163 |
164 | 需要有PGM参数或PROC参数。
165 |
166 | PGM参数用于指明所要执行的程序名。
167 |
168 | PROC指明作业步所要运行的过程名。
169 |
170 | // STEP1 EXEC PGM=IEFBR14
171 |
172 | ###数据定义语句
173 |
174 | 用于定义一个数据集及该数据集所需输入及输出资源
175 | 常见参数如下:
176 | * DSN= 定义数据集名
177 | * DISP= 定义数据集部署 格式 (status, success, fail)
178 |
179 | * status : 对数据集的动作
180 | * NEW : 新建
181 | * OLD : 每个作业独占
182 | * SHR : 每个作业共享
183 | * MOD : 当前作业独享
184 | * normal end / abnormal end : 处理成功/失败后的返回
185 | * DELETE : 删除并取消编目
186 | * KEEP : 保留不编目
187 | * CATLG : 保留编目
188 | * UNCATLG : 保留取消编目
189 | * PASS : 交由下面的作业步决定
190 | * SPACE= 所需的存储空间 如 (TRK,(10, 5)) 初次分配10个磁道,每次拓展分配5个磁道
191 | * SYSOUT= 定义打印位置
192 | * VOL=SER= 设定卷名、磁盘名、磁带名
193 | * UNIT= 设定系统磁盘、磁带、其他设备类型
194 | * DEST= 将输出发到远程目的地
195 | * LRECL= 逻辑记录长度
196 | * RECFM= 记录格式 定长 组块 变长
197 | * BLOCKSIZE= 记录块大小 LRECL倍数
198 | * DSORG= 数据集类型
199 | * LABEL= 预期的磁带标签
200 | * DUMMY= 导致空输入或舍弃写在ddname上的数据
201 | * `*` : 后面接输入数据或控制语句
202 |
203 | ### 续行要求
204 |
205 | 前一行参数写完整 然后后面加逗号
206 |
207 | 下一行 `//`开头,后面留至少一个空格
208 |
209 | 续行内容必须在第16列或之后开始,不得超过72列
210 |
211 | ###SDSF
212 |
213 | ST下使用`PREFIX *`等进行过滤作业
214 |
215 | ST下在作业号左边输入P(居然)可以删除
216 |
217 | 使用DA显示所有活动的作业
218 |
219 | ###作业控制子系统
220 |
221 | 可定制为JES2或JES3。
222 | 在单处理器下差别不大。
223 |
224 | 多处理器下:
225 | 只有JES3提供了全局处理器来实现调度。
226 |
227 | ###作业处理流程
228 |
229 | 1. 输入
230 | 2. 转换
231 | 3. 处理
232 | 4. 输出
233 | 5. 硬拷贝/打印
234 | 6. 清除
235 |
236 | ###系统库
237 |
238 | SYS1.PROCLIB z/OS发布的JCL过程
239 |
240 | SYS1.PARMLIB z/OS和一些程序的控制参数
241 |
242 | SYS1.LINKLIB 许多系统的基本执行模块。
243 |
244 | 实用程序
245 | ---
246 |
247 | IEFBR14 提供内容为0的返回码
248 |
249 | IEBGENER 可以将一个顺序数据集内容复制到另一个数据集中。
250 |
251 | IEBCOPY 将一个分区数据集中选定的(或所有的)成员复制到另一个分区数据集中。
252 |
253 | IEBDG 创建记录,该记录的域可以用各种类型的数据填充。创建测试数据。
254 |
255 | IEBUPDTE 在一个分区数据集中创建多个成员,或更新一个成员的记录。
256 |
257 | VSAM
258 | -----
259 |
260 | CI(control interval)由一个或多个物理记录组成,是VSAM文件的基本组成块。
261 |
262 | CA(control area)是由两个或以上CI组成的一块区域。
263 |
264 | ###VSAM组件
265 |
266 | 1. 数据组件:用以存放数据记录
267 | 2. 索引组件:只有KSDS和RRDS VSAM数据集才会使用索引组件
268 |
269 | 一个VSAM文件中会包含数据组件和索引组件。但在用户眼里只有一个VSAM,这就是簇群(cluster)的作用。
270 |
271 | ###定位数据记录
272 |
273 | * 键值域
274 | * 相对字节地址
275 | * 相对记录数
276 |
277 | ###种类
278 |
279 | 1. KSDS 以键值的升序存放。该记录的键值不能改变。插入新纪录也是按升序排列的
280 | 2. ESDS 按照先来后到排序,不需要索引组件。可以顺序访问或通过RBA直接访问
281 | 3. LDS 在CI中没有嵌入的控制信息。所有的域都是数据。其逻辑记录必须通过应用程序来分块
282 | 4. RRDS 只能用于定长的数据集,包含多个预定的定长的孔,每个孔有一个唯一的相对记录数。按升序排列
283 |
284 | ###ditto
285 |
286 | 主界面使用`du`打开打开ditto界面。具体行操作等同于一般的编辑界面。
287 |
--------------------------------------------------------------------------------
/debug/16and128.md:
--------------------------------------------------------------------------------
1 | 为什么我的程序处理不了>=16的情况?
2 | =====
3 |
4 | 在昨天写我的obj-c小练习*powerby2*的时候,我发现有一个蹊跷的地方。
5 | 就是当一个NSNumber的值达到16或以上时,就会导致某个流程无法进行
6 |
7 | 排查过程没有什么好说的,就是二分法排错。最后也锁定了错误所在。
8 |
9 | 程序有一处逻辑判断,需要判断两个NSNumber是不是相等。
10 | 我的写法是
11 | `self.value[step + j] == self.value[step + k]`
12 |
13 | 如果你用过obj-c,或者java,你可能会对此皱眉头。
14 | 虽然这种设计比较反人类,但是在这两种语言中,`==`操作符只能比较两个类的内存地址是否相同,如果你想要比较两个类是否相同,需要调用专门的方法。
15 | 在java中,这个方法来自`Object`的`compareTo`,通过返回一个整数来判断是否大于、等于或小于。
16 | 在obj-c中,这个方法来自`NSObject`的`compare`,通过返回`NSOrderSame`和`NSOrderAscend`、`NSOrderDescend`来分别表示等于、大于、小于。
17 | (看到了吗,obj-c又一次表现出了对封装和一致性的追求。)
18 | 一般这两个根类的子类都会重载这两个方法。
19 |
20 | 说了这么多,你应该已经明白,如果需要比较,应该使用`compare`而非`==`。否则,就只能使用`raw type`,比如使用`NSInteger`代替`NSNumber`。
21 | 要养成这种习惯很困难,就像刚开始编程时要用`==`来代替表示判断相等的`=`。
22 | 当然这种转变并不像刚开始那么困难,至少我已经适应了Shell里面的`=`和` = `之间的差别了:-D
23 |
24 | 如果本文就停止在这里,那么就只是一篇简单的经验文。不过我还是想升华一下主题,^_^
25 |
26 | 未定义行为
27 | -----
28 |
29 | 前面讲到,当NSNumber的值达到16或以上时,就会出问题。
30 | 而这个问题,出在 `self.value[step + j] == self.value[step + k]`身上。
31 | 如果原因是`==`和`compare`的原因,那么为什么要等到>=16才会被触发?
32 |
33 | debug一下,你就知道。原来不大于8的NSNumber的内存位置都是一样的。
34 | 也即是说,程序已经分配好若干个NSNumber,而调用时只是引用它们而已。
35 | 既然同等的值的NSNumber都是对一个NSNumber的引用,那么`==`显然会返回正确的结果。
36 |
37 | 所以,`==`触发的,是一个**未定义行为**!
38 |
39 | 如果触发了**未定义行为**,那么一切皆有可能。也许程序因为NSNumber的值不大于8就可以正确运行,但是情况一变,就会导致各种杯具。
40 |
41 | 在java里也有同样的现象。Integer在正负128内的值都是被缓存的,也即是说,在这个范围里,`==`也能正确运行。
42 | 只不过你会埋下一颗定时炸弹罢了。
43 |
44 | 总结
45 | -----
46 |
47 | **珍爱生命,远离未定义行为!**
48 |
--------------------------------------------------------------------------------
/debug/mkview.md:
--------------------------------------------------------------------------------
1 | 如何正确地在Vim里记录折叠等视图?
2 | =====
3 |
4 | 如果你用Vim的折叠命令手工折叠/打开了若干处,然后你希望下次打开的时候也能看到这
5 | 些折叠,你应该怎么做?
6 |
7 | 在一个月之前,我开始写一些javascript代码,然后需要折叠一些跟我的代码无关的内容,
8 | 来突出自己写的逻辑。
9 |
10 | 然后我惊奇地发现,Vim居然不会保存我制作的折叠!这一点出乎我的所料,因为无论是IDE
11 | ,还是我以前使用过的文本编辑器(Notepad++, Sublime 2),都会提供记忆折叠的特性。不
12 | 过Vim作为编辑器之神,根据以前我折腾Vim的经验,这个功能很可能是有的,只是没有被设
13 | 置出来罢了。
14 |
15 | 于是上网找。很快就找到了这条:
16 |
17 | :::vim
18 | au BufWinEnter * silent loadview
19 | au BufWinLeave * silent mkview
20 |
21 | 这段Vimscript代码很直白,就是在BufWinEnter的时候执行自动命令加载对应的视图,在
22 | BufWinLeave的时候执行自动命令制作对应的视图。视图里就包含了文本的折叠情况。把它
23 | 拷贝到vimrc里就好了。
24 |
25 | 现在,我再也不用在反复地手工折叠不相关的代码了,Vim能够记忆每次会话后代码的折叠
26 | 情况,并自动为我加载。
27 |
28 | 不过!
29 | -----
30 |
31 | 要是这样,这篇文章也就到此结束了。
32 |
33 | 可惜,世事总不遂人愿。很快我就遇到了问题。
34 |
35 | 1. 当我打开一个未命名文件时,会显示一个“E32 没有文件名”的错误……
36 | 2. 如果前面那个比较正常,那么还有一个让人摸不着头脑:当我使用帮助命令打开帮助文件时,
37 | 也会显示E32。
38 | 3. 还有一个问题,当我删掉某个文件,然后又重新复制了一个同名文件后,会产生视图加
39 | 载错误。
40 |
41 | 好吧,第3个算不上什么问题,第1个可以接受。但是第2个就让我百思不得其解了。我特意
42 | 使用expand('%')命令确认一下,帮助文件是显然有名字的。
43 |
44 | 不过你既然都说了,错误是没有文件名。那么我就修改一下,如果没有文件名,就不调用
45 | loadview和mkview。于是代码改成这样:
46 |
47 | :::vim
48 | if expand('%') !=? ''
49 | au BufWinEnter * silent loadview
50 | au BufWinLeave * silent mkview
51 | endif
52 |
53 | 代码不需要解释吧?就是加了个判断而已。可惜这个代码不顶用。之前提出的问题1,2都没
54 | 有解决。我以为是没有调用,加了个echo语句上去,结果发现无论如何,if里面的内容都会
55 | 被执行,而我在对应的未命名文件用命令行模式执行这段代码,if里面的内容不会执行。(
56 | 当然,在帮助文件下显然会执行这段代码。)
57 |
58 | 嗯,那好吧。于是改成代码2:
59 |
60 | :::vim
61 | if expand('%') !=? '' && &filetype !=? 'help'
62 | au BufWinEnter * silent loadview
63 | au BufWinLeave * silent mkview
64 | endif
65 |
66 | 结果呢,还是不行。一开始我以为是`expand('%')`和`filetype`的判断那里出问题,于是
67 | 换成别的API。但是,无论我怎么折腾,那个烦人的E32还是一再!反复!出现!
68 |
69 | 看来我只能忍了?不过我很快想到,会不会是执行顺序的问题呢?会不会是BufWinEnter和
70 | BufWinLeave那里的问题?
71 |
72 | 于是,我又走上阅读Vim文档的道路。在反复通读了`autocmd.txt`之后,我终于大概弄清楚
73 | 这些Vim事件的执行顺序。
74 |
75 | BufReadPre -> 获得文件名及大小 -> BufReadPost -> BufRead -> BufWinEnter ->
76 | BufEnter -> BufWrite -> BufWritePre -> 写入磁盘 -> BufWritePost ->
77 | BufLeave -> BufWinLeave
78 |
79 | BufLeave <-> BufEnter
80 |
81 | 但即使如此,我反复地把那两个BufXXX事件换成其他的BufXXX事件,要不无法解决E32问题
82 | ,要不可以避免E32,却无法正常加载视图。
83 |
84 | 对策
85 | -----
86 |
87 | 好吧,在忍受了一段日子后,我突然想到了一个比较蠢,但是管用的办法,就是硬编码。我
88 | 把两个视图命令写出一个函数,然后制定一个可以调用它们的白名单类型,比如:
89 |
90 | :::vim
91 | function! SetView()
92 | au BufWinEnter * silent loadview
93 | au BufWinLeave * silent mkview
94 | endfunction
95 |
96 | augroup setFileView
97 | autocmd!
98 | au FileType python :call SetView()
99 | au FileType c :call SetView()
100 | ...
101 |
102 | 大概就是这么挫。不过至少在使用帮助文件时,再也不会有E32了。
103 |
104 | 解法
105 | -----
106 |
107 | 就这样将就了一段时间。有一次我在查找有关执行外部命令的资料时,突然看到了一个
108 | silent!命令,它可以使得命令的输出完全屏蔽掉,包括错误。(Vimscript里没有异常的概
109 | 念,只有错误,而且没有捕获错误的机制)
110 |
111 | 之前大家都应该知道一个silent命令,这个silent!是它的加强版,连错误都保持沉默。
112 |
113 | 这不是我想要的吗!!!于是,代码最终变成这个样子:
114 |
115 | :::vim
116 | au BufWinEnter * silent! loadview
117 | au BufWinLeave * silent! mkview
118 |
119 | 问题终于解决了!虽然现在依旧会有错误抛出,不过这已经跟我无关了。眼不见为净嘛。
120 |
121 | 后记
122 | ----
123 |
124 | [@Cloudprogram](https://github.com/Cloudprogram) 提供了个更好的方法来解决 E32 问题。
125 |
126 | 参考;https://vi.stackovernet.com/cn/q/4214
127 |
128 | Switching to ?* as the regex will no longer match empty file names. I actually recommend you switch to the following, which is a corresponding block of .vimrc that has been tweaked to suppress many of the errors you are likely to encounter when following the referenced advice.
129 |
130 | ```
131 | augroup AutoSaveFolds
132 | autocmd!
133 | " view files are about 500 bytes
134 | " bufleave but not bufwinleave captures closing 2nd tab
135 | " nested is needed by bufwrite* (if triggered via other autocmd)
136 | autocmd BufWinLeave,BufLeave,BufWritePost ?* nested silent! mkview!
137 | autocmd BufWinEnter ?* silent loadview
138 | augroup end
139 | ```
140 |
141 | The BufWritePost event (+ nested) can be left out if you prefer, though you will experience no penalty for leaving it in.
142 |
143 | Furthermore, I use
144 |
145 | ```
146 | set viewoptions=folds,cursor
147 | set sessionoptions=folds
148 | ```
149 |
--------------------------------------------------------------------------------
/debug/npm_install_Error.md:
--------------------------------------------------------------------------------
1 | NPM Install : Error: No compatible version found
2 | =====
3 |
4 | 前一段时间,我打算安装npm来玩玩。但是,我惊讶地发现,无论下什么包,都会有同样的
5 | 错误: Error: No compatible version found. 即使我直接指定了版本号,还是下不了对
6 | 应的包,所以应该不是版本号的问题。
7 |
8 | 作为墙内的子民,第一个想到的解决方案大概会是被墙的问题吧。不过我可以肯定地排除被
9 | 墙的可能,因为在被墙的情况下,直接连都登不上。所以我
10 | 才特意战略转移到墙比较矮的网络环境(图书馆的教育网)下。现在总算可以连上官网了,但
11 | 是还是下不了对应的包,真是郁闷啊。
12 |
13 | 还是老办法,Google之,到StackOverflow看看。然后我找到了许多方法,不过大部分都未
14 | 能奏效。但是幸运的是,至少有一个是奏效的了。
15 |
16 | 解决方法在这里
17 |
18 |
19 | 这个解决方法很奇妙吧,发行版源里的npm版本太旧了,添加一个新源,下最新版的npm就能
20 | 解决问题了。
21 |
22 | 现在我用的是npm 1.3.24, 总算可以成功地安装各种好玩的包啦。
23 |
--------------------------------------------------------------------------------
/debug/pipInstallInVirtualenv.md:
--------------------------------------------------------------------------------
1 | 在virtualenv中正确地安装python包
2 | =====
3 |
4 | 首先需要声明一下,我使用的是virtualenvwrapper, 如果你是用virtualenv,可能情况会
5 | 不一样。并且为了简明扼要,以下由virtualenvwrapper创建的vitual environment一概简
6 | 称为virtualenv,希望不会让你把它跟virtualenv程序弄混淆了。
7 |
8 | 昨天我遇到了一个麻烦:发现在virtualenv下找不到之前安好的包。一开始我还没有意识到
9 | 这可能是virtualenv的问题,而是这个包的问题。
10 |
11 | 这是一个flask插件,叫做flask-WTF的(起个好名字很重要),当然这个插件是用来处理表单
12 | 认证的,估计是wrap the form的简称。然后呢,这个包自己有一个问题,就是在0.9的时候
13 | ,它突然改变了自己的架构,把一些部件移到另外的子模块里,其变动之大只有py2下的
14 | urllib2跟py3下的urllib相比拟。结果是显然的,许多人毫无戒备地掉到了坑里。
15 |
16 | 举个例子,0.9版以前,所有的部件都可以在flask.ext.wtf下import进来。但是在0.9版之
17 | 后,所有的Field都需要从wtforms里引入。此外,还有一个Form的常用类,现在既可以从
18 | flask.ext.wtf,也可以从wtforms下面import进来。且慢!wtforms里的那个Form是
19 | flask.ext.wtf那个的Form的基类。如果你想要使用Form来添加安全验证的保障,必须使用
20 | flask.ext.wtf那个!
21 |
22 | 情况就是这么糟糕,难怪有人会在github上相关的issue上调侃,它是不是改名成WTF了。
23 |
24 | 啰里啰嗦说了一大堆,事实还没有说到我的问题上。不过正为flask-wtf所苦的童鞋可以参
25 | 考我上面的内容。
26 | 比如oschina上的这篇[教程](http://www.oschina.net/translate/the-flask-mega-tutorial-part-iii-web-forms)就需要修改修改。
27 |
28 | 我的问题,嗯,其实是没有办法引入所有在virtualenv下安装的包,原因嘛……因为我根本就
29 | 没把它安装进virtualenv里!
30 |
31 | 发现这一点很容易,使用pip freeze或pip list列出当前环境下的安装的包。结果呢,我发
32 | 现我把包安装到全局空间里了。。。(╯°Д°)╯︵ ┻━┻
33 |
34 | 错误示范: `sudo [-E] pip install thieves`
35 |
36 | 正确示范: `pip install thieves`
37 |
38 | 为何捏?
39 |
40 | 先解释下sudo -E吧。以下内容摘自sudo的用户手册:
41 |
42 | -E The -E (preserve environment) option indicates to the security
43 | policy that the user wishes to preserve their existing environ‐
44 | ment variables. The security policy may return an error if the
45 | -E option is specified and the user does not have permission to
46 | preserve the environment.
47 |
48 | 虽然提到了preserve environment variables,但是sudo -E不会让你成功地把包安装在虚拟环
49 | 境中。事实上,根本不能使用sudo!
50 |
51 | 当你使用sudo时,包会安装到/usr/local/lib/python2.7/dist-packages下,不管你是在
52 | virtualenv中还是不在其中。因为你现在是想**以root的身份**给系统中所有的用户安装一个
53 | python包。
54 |
55 | 如果不用sudo,假设你不在virtualenv中,包同样会安装在/usr/local/lib/python2.7/dist-packages
56 | 之下,只不过由于没有root权限,不一定能成功安装。
57 |
58 | 那么,假设你在virtualenv中,包就会安装在/home/me/.virtualenvs/myvirtualenv/local/lib/python2.7/dist-packages
59 | 中,注意跟前面的区别。
60 |
61 | 所以解决办法很简单:
62 |
63 | 1. 在对应的virtuallenv下面使用pip安装需要的包。
64 | 2. 不要使用sudo pip, 使用pip即可。
65 |
66 |
--------------------------------------------------------------------------------
/debug/why_all_my_MPI_process_has_rank_0.md:
--------------------------------------------------------------------------------
1 | Why All My MPI Process has the rank 0?
2 | =====
3 |
4 | 嗯,当我开始写MPI程序的时候,也遇到了这个问题。
5 |
6 | ## 背景知识
7 |
8 | 先介绍一下背景。
9 |
10 | MPI全称是message passing interface,即信息传递接口。它提供让相关进程之间进行通信,同步等操作的API,可以说是并行计算居家出游必备的基础库。
11 |
12 | MPI的编程方式,是“一处代码,多处执行”。编写过多线程的人应该能够理解,就是同样的代码,不同的进程执行不同的路径。
13 |
14 | 那么怎么区分不同的进程呢?
15 |
16 | MPI有几个常用的API,其中有一个叫做`MPI_Comm_rank`, 它返回调用它的进程的具体进程号。比如我启动了10个进程,然后每个进程的这个调用会返回0-9对应的进程编号。这样它们就知道谁是老大,谁是老二,谁是老九……于是我们可以很确定地下命令,让老大去买菜,老二到老五洗中午的碗碟,老六到老九准备做饭。
17 |
18 | 要想运行MPI并行程序,使用普通的编译器是不行的,需要使用特殊的mpi编译器。其实所谓的mpi编译器,只是普通的编译器外加了个套件。比如mpicxx,就是在g++外面套了个mpi的壳。而且除了编译器要用特殊的编译器之外,运行时还要用特殊的程序,比如mpiexec和mpirun。
19 |
20 | 这里澄清一下,虽然mpiexec和mpirun除了前缀其他各不相同,但是它们不是两兄弟,只是一个程序的不同说法罢了……
21 | 具体的运行方法,是`mpirun -n x ./myProgram`,其中x是要启动的进程数。这时候,如果你使用系统监视器或者终端下的`top`命令,应该能够看到x个名字一模一样的进程正嘿哟嘿哟地运行着。
22 |
23 | 前面讲到的`MPI_Comm_rank`调用,返回的值为0到x-1中的一个值,取决于对应的进程是老大还是老x。
24 |
25 | 背景知识介绍完毕。如果想要知道更多,请移步到维基页面[信息传递接口](http://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E5%82%B3%E9%81%9E%E4%BB%8B%E9%9D%A2);
26 | 想要知道更更多,请移步到英文维基页面[Message Passing Interface](http://en.wikipedia.org/wiki/Message_Passing_Interface)。
27 |
28 | ## 问题
29 |
30 | 好了,是时候交代我的问题了。
31 |
32 | **无论我指定了多少个进程,所有的进程都会声称自己的进程号为0.**
33 |
34 | 没错,`MPI_Comm_rank`调用不灵了。
35 |
36 | ## debug
37 |
38 | 在排除了我自己在代码中犯错的情况后,我果断可以求助于万能的互联网。
39 |
40 | 搜索了一下才知道,原来网上也有很多人遇到了跟我一样的问题:
41 | > Why All My MPI Process has the rank 0?
42 |
43 | OK, 这样就简单多了^_^。。。
44 |
45 | Wait!怎么答案有点不靠谱?>_<
46 |
47 | 在爆栈网上有一个相关的问题,有人回答:
48 | > 这是openmpi的错!卸openmpi保平安!卸掉装mpich就好了!
49 | 不过接下来有人回答:
50 | > 我卸掉mpich就正常了!现在哥用的是openmpi!
51 | 你们……
52 |
53 | (这里解释一下:openmpi和mpich是mpi的两个开源实现,同样也是使用最广泛的两个实现。)
54 |
55 | ## 转机
56 |
57 | 嗯,于是我丢下了不靠谱的答案,继续在茫茫的信息大海中捞取有用的内容。
58 |
59 | 然后我看到了:(原文为英文,但是具体内容已经忘了,所以这里复述其大意)
60 | > 为什么我的MPI程序中所有的进程都返回rank 0呢?
61 | > 你检查一下mpic++和mpiexec具体链接到哪个程序上?
62 | > 哦,原来...
63 |
64 | **一言惊醒梦中人!**
65 |
66 | 于是乎用`which`来查看`mpicxx`和`mpiexec`,结果大出我所料,`mpicxx`居然有`openmpi`和`mpich`两个版本。
67 | 同样的事情也发生在`mpiexec`上。
68 |
69 | 有趣的是,这两个版本的后缀是不同的。`mpicxx`链接到的是`mpicxx.mpich`和`mpicxx.openmpi`,`mpiexec`也一样。
70 |
71 | 那么,名字上的冲突会导致什么问题呢?
72 |
73 | ## 答案
74 |
75 | 根据这篇[mpich FAQ](https://wiki.mpich.org/mpich/index.php/Frequently_Asked_Questions),
76 | 可以看到mpich官方对于**All my processes get rank 0**这个问题的解答。
77 |
78 | 鉴于内容较多,且大部分内容不在“人话”的领域内,我就只摘抄结论如下:
79 | > So, in some sense, mpiexec or srun is just a user interface for you to talk in the appropriate PMI wire protocol.
80 | > If you have a mismatch, the MPI process will not be able to detect their rank, the job size, etc.,
81 | > so all processes think they are rank 0.
82 |
83 | 所以,如果调用的`mpiexec`和`mpirun`不是同一个版本的,就会产生**所有进程都返回rank0**这种情况。
84 |
85 | ## 解决
86 |
87 | 解决方法很简单,在`openmpi`和`mpich`中选择一个即可。
88 | 不管怎样,在编译和运行时,最好都添加上后缀,比如使用`mpicxx.mpich`编译,那么运行就用`mpiexec.mpich`。
89 |
90 | 虽然最后还是用卸掉其中一个解决了问题……不过至少现在知道了其中的原理,而不是人云亦云地敷衍了事。
91 |
92 |
--------------------------------------------------------------------------------
/feeling/rain.md:
--------------------------------------------------------------------------------
1 | #下雨天
2 |
3 | 当我还小的时候,我很喜欢下雨。下雨该有多好啊。一下雨,天气一下子凉快了许多。
4 |
5 | 不过这不是关键的,关键的是,我一向认为暴雨乃是天地的一道奇观,而雨声,则是当之无愧的天籁。
6 |
7 | 当倾盆大雨以雷霆之势灌注于大地之上时,天地犹如被连天的乌云镇住,所有的一切都湮没在昏暗之中,所有的一切都隐藏在雨帘之后。雨点,成千上万的雨点,争先恐后地捶打覆盖在大地上的那一层水膜上,激起万千浪花。伴随着雨点的还有那风。肆虐的狂风呼叫着,一次次无谓地撕开连接天地的雨帘,让雨丝纠缠,成为无数扭结的雨柱。一时间,平淡无奇的天地间充斥着一股力量,一扫炎日的颓废,一扫宁静的空虚,把一种力量美酣畅淋漓地表现出来。就像是突然发生的快闪。不过路人可不会驻足旁观。他们恐怕都避之不及,甚至会咒骂这不请自来的暴雨,憎恨着粗犷的暴力。
8 |
9 | 然而我是不会厌恶的。即使不得不逃避到一个安全的,温暖的避风港,我也忍不住停下来欣赏,欣赏这雄伟的奇观,哪怕这让我显得有些古怪。这的确是罕见的奇观。想想平淡的生活,想想庸碌的日子,突然来那么一场大雨,感觉就像帆船被推开了航道,却发现新的岛屿一样。看看那飞溅的雨珠,看看那呼啸的狂风,看看那遮天的阴云,无不是平日难得一见的异象!纵使是炎日下中午所做的白日梦,也断断梦不见这般奇异的景象。
10 |
11 | 不过现在,我却厌恶那连日不停的大雨。雨后那清澈的阳光,代替了那狂风暴雨,成为我心中的渴望。
12 |
13 | 写下此文的时候,窗外的大雨正刚刚消弭,阴云已经散尽。阳光倾注到大地上,把阴暗和潮湿一扫而光。
14 |
15 | 我不知道这种转变是何时发生的。也许是我不再孩子气了?也许是我成熟了?或者也许,是我老了?但是,厌恶下雨跟这些又有何相干?不应该仅仅是一个气候变化的问题么?
16 |
17 | 我不再驻足旁观那疯狂的大雨,我渴望天晴更甚于阴雨。因为天晴了,可以做很多有趣的事。或者即使不是有趣的事,也好过纠结于那狂怒的暴雨而徘徊踌躇,好过因恐惧那险恶的天气而畏缩不前。现在我要担心衣服会不会又因为天气原因而连日不干,不干之后会不会没有衣架可以拿来晾,或者更糟糕的是,连衣服都没得穿。以前,这是我爸妈在意的事情。即使外面狂风暴雨,只要有洗衣机、烘干机,衣服就不会不干。但是现在我孤身在外,而且既没有洗衣机,又没有烘干机,最多拿个风筒吹一吹。在这种环境下,怎么能欣赏下雨的美呢?
18 |
19 | 广州的暴雨可以持续数日。嗯,其实不是一直下个不停,大概是下三个小时,然后歇上半天,再下多几个小时的节奏。连续几天的暴雨,可以破坏很多计划,比如精心策划的活动,比如期待已久的出游,或者只是突然心血来潮的散步。连绵不绝的阴郁,会让人心情变糟,让人萎靡不振,甚至让人生成病来。这时候,又怎么会有心情欣赏下雨的美呢?
20 |
21 | 就是这样,我再也不能欣赏起下雨的美了。也许是因为我牵挂更多了?也许是因为我的烦恼更多了?也许是因为我要做的事情更多了,不得不为许多事情担当起责任。所以,不再旁观那壮观的雨景,而是退而担忧那阴郁的前景。
22 |
23 | 无法再理解过去对雨景的赞美和喜爱,这是成长所带来的隔阂么?我不知道。
24 |
--------------------------------------------------------------------------------
/lvthw.md:
--------------------------------------------------------------------------------
1 | Learn Vimscript The Hard Way翻后感
2 | =====
3 |
4 | 首先,要感谢我的队友,是他们开始了对Learn Vimscript The Hard Way的翻译。而且他们
5 | 也审读了我的译稿,虽然没有批评什么,但是想到会有人看着你,平时吊儿郎当的我对译稿
6 | 的质量十分珍视,甚至有的地方到了字斟句酌的地步(不过估计还是会有许多待完善的地方
7 | :))。
8 |
9 | 所以,这里要感谢@Gong Yong, @iSayme, 尤其是发起翻译项目的iSayme,如果不是他提供的网
10 | 站,恐怕我对最终的项目成果会怎样恐怕也没多大信心呢。
11 |
12 | 翻后感
13 | -----
14 |
15 | 一般来说,写读/观后感的情况大概有其中几种:
16 |
17 | 1. 来自上级的任务要求
18 | 2. 有感而发,类似于游记等等
19 | 3. 给自己留下一个纪念
20 | 4. 职业病
21 |
22 | 这次,我写翻后感的冲动(啊,有冲动么?),来自于给自己一个纪念。
23 |
24 | 记得几乎每本译著都要有一个译者序或者译后记这类的东西。大概是因为译者花费了夜以继日的
25 | 精力,以及目不窥园的毅力,终于把一份译稿完成了,而且还不算是“犯罪”。(作者注:写
26 | 一本烂书没什么所谓,把一本好书翻译成一本烂书就是犯罪。类似这样的犯罪行为其实真不
27 | 少见呢) 因此内心大发感慨,于是趁着夜未央,天未白的间隙里一笔挥就,一吐心中块垒。
28 |
29 | 我原本也是这么打算的。这样挺文艺的吧?
30 |
31 | 可惜不知怎的,翻译完Learn Vimscript The Hard Way后,我并没有太多的感慨,仅仅就像
32 | 完成了一项作业……我也不知为何,也许是因为翻译的过程一点都不painful吧。
33 |
34 | 不过,在翻译完成的三天后,我还是抽出时间来完成这个翻后感。原因无它,给自己留下一
35 | 个纪念,就像在旅游景点拍下达到硬盘容量的照片一样。
36 |
37 | 翻后感
38 | -----
39 |
40 | 爱恶作剧的作者用了同样的题目,这样就可以把读者搞糊涂了,搞糊涂了就好忽悠了。
41 |
42 | 好吧,这里是翻后感的正文部分。(⊙o⊙)嗯,翻后感……让我把思绪沉淀一下。
43 |
44 | Vimscript 是一门罕见的语言,几乎可以说是只有Vim用户才会学习的方言。作为一门语言
45 | ,它更多的是对外部提供规范的接口,用于调用Vim的功能(或者外部命令)。大体上说,如
46 | 果你认为Python/Ruby是一门正常的语言,那么Vimscript也是一门正常的语言,除了古怪的
47 | 正则表达式部分和对字符串的(难以认同的)强制转换算是一种怪癖。如果你喜欢Elisp或其
48 | 他的函数式语言,Vimscript恐怕会让你心生厌烦。因为它类似于传统的命令式语言,甚至
49 | 缺乏一些诸如“一切都是对象”、“匿名函数”这样的好东西。
50 |
51 | 不过作为一门用于控制Vim的语言,Vimscript恰到好处,它直白干脆,寥寥数语之间就能把
52 | 想要的功能粘合起来。如果你觉得Vimscript的功能太少,Vim同样也支持使用Python、Ruby
53 | 或Lua进行拓展,然后把Vimscript当作胶水和兼容层。
54 |
55 | 谈完了Vimscript,让我们谈谈书本身。
56 |
57 | 由于原作者弃坑,导致书中有些前后不一致的地方得不到解释。(我在GitHub上提交了
58 | issue,但是作者在一年多之前就不理了,前面已经积了60多个issue,说不定我提到的东西
59 | 之前就有人提出来了)
60 |
61 | 不过尽管这样,我还是相当佩服作者的编程功力和文字功力的。编程功力暂压下不论,到时
62 | 各位看译文的时候就知道了。由于英文翻译成中文后,本人水平较次,不能把其中精妙的意
63 | 思一一述尽,所以阅读体验可能会在文学价值上打个折扣。这里我就不厚道地推荐大家去看
64 | 英文原版,可以学到不少英语的表达方式呢。
65 |
66 | 当然,如果一本好书经过我们的翻译后打了折扣,那是不可能的,虽然为了谦虚,还是得指
67 | 出自己的不足。不过谦虚完后,该是时候指出我们的成就的。
68 |
69 | 首先,看中文显然比看英文舒服多了。
70 |
71 | 其次,英文的内容中有不少typo,在中文译稿里,我们一概已加以修订。考虑到原作者已经
72 | 弃坑,如果直接去阅读原文,恐怕会一不小心踏坑里。
73 |
74 | 最后,虽然有些语言上的内容无法完全准确地翻译出来,但是怀着不正经掉节操的心态,我
75 | 们的译文在幽默风趣的方面对于原文是有过之而不不及。到时各位阅读的时候就知道了。
76 |
77 | 最后
78 | -----
79 |
80 | 说了那么多,我发现还没有说明怎么才能阅读我们的译文呢。
81 |
82 | [Learn Vimscript The Hard
83 | Way](http://learnvimscriptthehardway.onefloweroneworld.com)
84 |
85 | 不用多谢。
86 |
87 | 如果有错别字,病句或其他会导致语文老师扣分的问题,请到
88 | 提出issue来帮助我们
89 | 做得更好(或者改善你郁闷的心情)
90 |
91 | 当然,如果你对于内容有什么感到纠结之处,不要憋在心里,赶紧向我们指出来。
92 |
93 | 鸣谢
94 | -----
95 |
96 | 最后的最后,当然还是重新感谢@iSayme,谢谢他以练习的名义开拓了这个翻译项目,然后
97 | 还提供了一个网域来放置我们翻译出来的成果,当然还有在一个多月来不断地审看我的译文
98 | 。如果没有他,嗯,我觉得我们的项目很可能不会有成果。
99 |
100 | 我的感谢列表上还有@Gong Yong, 还有本书英文版原作者@SteveLosh, 还有许许多多别的人……
101 |
--------------------------------------------------------------------------------
/man.md:
--------------------------------------------------------------------------------
1 | man攻略 read,write,post
2 | =====
3 |
4 | 正如题目所言,这篇文章是讲UNIX中的man命令的。
5 | man命令是manual的缩写,通过这个命令可以查阅UNIX系统手册。
6 |
7 | 可能有人已经注意到,讲UNIX的书,在提到某些命令或系统调用时,总会在其后添加一个数字序号。
8 | 这个序号表示的是这个命令(或调用)在UNIX系统手册的第几部分。
9 |
10 | 在过去,UNIX用户手册的确是一本书,书里分几个章节。后来不再随系统附带说明手册,改把说明手册附到系统里,使用工具来查阅对应的条目。
11 | 即使现在同一个章节内的条目已经不一定放到一块,UNIX用户手册依然照过去的样子分成下面几章:
12 |
13 | 1. 通用命令
14 | 2. 系统调用
15 | 3. 库函数,主要是C标准库函数
16 | 4. 特殊文件比如设备,和驱动等等
17 | 5. 文件格式和约定
18 | 6. 游戏和屏保(你没看错,的确会有这种东西)
19 | 7. 杂项
20 | 8. 系统管理员命令和守护进程。
21 |
22 | 居然不从0开始...许多书上会讲,UNIX用户手册一共分八个部分(包括APUE也是这么说)。
23 | 但是,实际上有些系统(比如Linux和Mac OS X)就不太传统,在基本的八个部分上增加了新
24 | 的章节。
25 | 具体情形比较复杂,可以参照[维基百科](http://en.wikipedia.org/wiki/Man_page#Manual_sections)条目下的Manual sections。
26 |
27 | 在大部分情况下,不需要指定特定的章节,只需简单地使用`man xxx`。但是有些情况下需
28 | 要加以区分,比如`man read`,如果是想要查系统调用的那个,需要显式指明`man 2 read`。
29 | 当然你也可以指定man page所在的路径,如`man ./xxx/yyy/zzz.1 `。
30 |
31 | Read
32 | -----
33 |
34 | 在man里打开一个文件后,可以通过d或u来往下翻半页或者往上翻半页。如果想要翻一整页,使用z向下,或者w向上。
35 | 如果想要搜索某个词,使用/进入搜索模式,用n到下一个匹配处,用N到上一个匹配处。
36 | 如果想要直达文件头/尾,使用g/G。详情可以使用h来打开帮助页面。总之,如果你使用过Vim,就不会感到陌生。
37 |
38 | 其实man页面之所以可以这样浏览,是因为它调用了less作为自己的默认浏览程序。
39 | 你可以使用`man xxx -P yyy`来指定别的程序打开man页面,比如`man xxx -P cat`。
40 |
41 | write
42 | -----
43 |
44 | 既然已经讲完了read,是时候讲讲write。
45 |
46 | 假如你想为自己的程序写一个man page的说明,应该怎样?
47 |
48 | 方法大概有三:
49 |
50 | 1. 找一个类似的man页面,复制然后定制。这个就不用详细说了。不过你需要看看下面的manual路径,方便你找到所需的页面。
51 |
52 | 2. 参照man的格式(groff),自己写一个。额,不提倡。所以这里就同不说了。
53 | 不过假如你真想这么做,推荐[这篇文章](http://www.schweikhardt.net/man_page_howto.html)
54 |
55 | 3. 使用文档格式转换工具,把别的格式的文本文件转化成man page。这是本人推荐的方式
56 | 。比如[help2man](http://www.gnu.org/software/help2man/)或者[ronn](https://github.com/rtomayko/ronn),还有著名的pandoc。
57 |
58 | 如果想用pandoc,先看看这个demo: 里
59 | 面关于生成man page的那一条。
60 |
61 | 如果想要用ronn,那么就往下看吧:
62 |
63 | ### ronn
64 |
65 | 安装:
66 |
67 | gem install ronn
68 | # ronn 需要安装ruby和gem
69 |
70 | 使用:
71 |
72 | ronn xx.x.ronn
73 |
74 | ronn需要用ronn格式的文本来转化成man page。
75 | Don`t Panic. ronn是一种拓展的markdown文法,懂markdown的人看一下就知道如何编写ronn格式文本了。
76 | 其实pandoc也不能直接将普通的markdown转化成man page,它也需要使用它自己的markdown拓展。
77 |
78 | 废话不说了……如果想了解ronn文法的话,看下man文件夹里的几个示范吧。
79 | 一如普通的markdown文法,就是生成的man page的样式跟markdown对应的html不一样而已。博主只把两个示例看了半遍,就能写成所需的ronn文本了。
80 |
81 | 放上自己的demo,地址:
82 |
83 | ---
84 |
85 | 这里就不讲help2man怎么用了……感兴趣的童鞋到对应的项目主页看看吧。
86 |
87 | post
88 | ------
89 |
90 | 假如你已经写好了一个man page,那么怎么样才能让man命令找到你的man page呢?
91 | 让我们先从man的查找方式说起:
92 |
93 | ### manual路径
94 |
95 | man到底是怎么查找到这些manual呢?
96 |
97 | man会在目标路径里查找。
98 | 这个可以通过`man -w`(或`man --path`,取决于你的喜好)来获取。
99 | 如果`-w`选项后面没有加参数,就输出系统定义的搜索manual路径;否则输出参数所在的man页面所在的文件位置。
100 |
101 | ### 发布你的man page
102 |
103 | 既然能够获知man的搜索路径,那么可以考虑直接复制文件进去……当然肯定不只有这种“不负责任”的办法。
104 |
105 | 使用`man man`,然后`\SEARCH PATH FOR MANUAL PAGES`,就能找到一段关于manpath的介绍。
106 | 由于本文已经显得比较冗长,这里就不复制对应的内容了。
107 | 简而言之,就是可以修改环境变量中的`$MANPATH`来改变man的搜索路径。
108 | 这样一来,把你的文件所在目录加入到搜索路径就OK了。
109 |
--------------------------------------------------------------------------------
/tips/style.md:
--------------------------------------------------------------------------------
1 | Style里使用placeholder实现用户选择样式
2 | =====
3 |
4 | 嗯,类似于笔记的一篇。
5 |
6 | 这里的Style,指的是一个可以让用户添加自定义CSS样式的[插件][]。
7 |
8 | Style提供一个功能,CSS样式制作者可以提出一些选项,让用户进行选择。
9 | 当然这一功能不太完善,没有像想象当中那么可以自由地自定义各类属性。其实这个功能类
10 | 似于预编译指令,一旦你选择了对应的选项,生成的CSS就不能再改动了。而且目前可支持
11 | 的选项也有限,不能承载用户无穷的想象力和需求……
12 |
13 | 吐槽完毕,回到正文。那么作为CSS样式制作者,可以怎么使用这一功能呢?官方提供了[帮
14 | 助文档](http://userstyles.org/help/coding)。
15 |
16 | 这里再解释一下:第一步,按"Style Settings (Optional)"按钮,选择新的条目。其中
17 | Label是用户可以看到的选项名,比如"背景色"等等;而install key是用在CSS中的
18 | placeholder,比如"bg_color"。
19 |
20 | 那么怎么用呢?其实很简单,就是用`/* [[install key]] */`代替你需要让用户选择的值
21 | 。比如使用`/* [[bg_color]] */`代替原来的颜色名。在用户安装的时候,他们安装的是解
22 | 析后的CSS文件,也即所有的install key被替换成用户选择的值的CSS文件。
23 |
24 | [插件](http://userstyles.org/)
25 |
--------------------------------------------------------------------------------
/tools/goodinputmethod.md:
--------------------------------------------------------------------------------
1 | 换了fcitx,输入中文从此更轻松
2 | =====
3 |
4 | Ubuntu自带的是iBus输入框架,所以之前7个多月,我都是使用着它。准确来说,是iBus输
5 | 入框架下的sunpinyin输入法。
6 |
7 | 但是,不久之后我就开始为此头疼起来。首先,iBus输入框架跟许多GUI程序不兼容,比如
8 | 使用iBus时,输入框总是在WPS Word和git-cola的底部。这两个程序是我经常使用的,由于
9 | 它不能正确地悬浮在焦点上方,导致打字效率下降,打错字的次数也增多了。
10 |
11 | 还有一个严重的问题,sunpinyin不能模糊s和sh,c和ch,以及z和zh。作为一个南方人,而
12 | 且是拼音学不好的南方人(高考拼音基础题我可是对了一半的哦),这真是一个煎熬。经常有
13 | 来回翻了好几页都找不着某个字,结果突然意识到原来是拼音拼错了。当我打算输入的是一
14 | 个词组时,这种痛苦真是无与复加。
15 |
16 | 如果这些都能忍,那……真大丈夫也!可是,在最近翻译《learn vimscript the hard way》
17 | 的时候,每次输入法切换到除了终端以外的窗口,再回过头来使用Vim……就会出问题。输入
18 | 法简直是叫天天不应,叫地地不灵,必须切换到别的终端窗口,再重新启动才行。
19 |
20 | 输入法你够了!我再也无法忍受你的傲娇了!
21 |
22 | 由于早有所闻fcitx的兼容性比较好,所以打算换成fcitx。还有一个原因是fcitx支持搜狗
23 | 输入法。虽然搜狗输入法曾经因为频繁弹窗而被我卸载过,但是用了许多别的输入法(包括
24 | 不争气的Google输入法),不得不承认搜狗输入法是最棒的。而且在Mac上面,搜狗输入法也
25 | 不会有弹窗,在Linux上面就更不会了。(也许现在搜狗学乖了,不再弹出秒杀用户体验的弹
26 | 窗了)。
27 |
28 | 换fcitx的过程很快捷。
29 | 我参考的是Linux公社上的[这篇文章](http://www.linuxidc.com/Linux/2013-07/87062.htm)
30 | 输入几个命令,等了相关软件下载安装完毕,最后重启一下就OK了。这时也体现了Linux装
31 | 软件的便捷性。
32 |
33 | 最后我终于换上了如愿以偿的fcitx框架(当然还有酷狗输入法)。
34 | 然后我先到之前有冲突的GUI软件上试试,结果让人心安,原来痛苦的焦点无法对准的问题
35 | 终于解决了!而且也不会在切换到别的窗口时影响到Vim的中文输入了!另外不得不说,
36 | fcitx的选项比iBus多多了,iBus简直是不能让你选择任何东西,只能接受默认状态。而在
37 | fcitx下,你甚至可以把键盘布局设置成Mac类型的。而且,原来sunpinyin也有模糊拼写的
38 | 设置的,之前我一直使用iBus,错怪了sunpinyin这么久,真是对不起啊!
39 |
40 | 不过说真的,sunpinyin的词组拼写能力还是不如搜狗好啊,所以我现在就用搜狗啦!
41 | 另外,fcitx还可以换皮肤哦!换成dark皮肤,跟暗色调的Vim真是绝配啊!我现在非常喜欢
42 | 输入中文,赶紧又翻译了几十行的《learn vimscript the hard way》。
43 |
--------------------------------------------------------------------------------
/tools/idea.md:
--------------------------------------------------------------------------------
1 | # 从eclipse切换到IDEA
2 |
3 | 几天前,因为要为下学期的JEE课程预热,我打算重新拾起Java。下了最新版的eclipse后,却无奈地发现,每次新建一个Java工程后,它都会崩溃。无论是Java版本还是J2EE版本,都存在同样的问题。看来我的系统跟eclipse不合。没办法,虽然知道旧版本是能够跑起来的,但是总不能一直沿用旧版吧。于是决定开始切换到传说中最好的Java IDE——Jetbrain家的IDEA上去了。(之所以说是最好的Java IDE,是因为最好的IDE这一名头已经被VS占去了,呵呵)
4 |
5 | ## IDEA初体验
6 |
7 | IDEA的使用体验,给我最大的感受就是稳定。如丝一般地顺滑。之前使用eclipse的时候,总是担心程序会不会突然就崩溃了,所以每写一段就会保存一下。但是自从使用了IDEA后,妈妈再也不用担心我的IDE崩溃了。用了几天的时间,如果是eclipse的话,应该已经发生了几次失去响应,甚至有一两次崩溃,但是这些问题都不在IDEA上发生了。
8 |
9 | 看来,这次切换真的值!
10 |
11 | 当然,刚切换到IDEA还是有些不习惯。抛开快捷键的重新熟悉不谈,IDEA的智能,并不比eclipse高出多少。
12 |
13 | 也许是之前听了太多安利,总感觉IDEA是无所不能的,能够随心所欲、收放自如。但是实际用起来,其实也不比eclipse高到哪里去。应该是IDE的视觉效果过于华丽,让人产生了它复杂而聪明的错觉。看来,IDE并不是像传说中那么牛逼,IDE党的言论还是不能全信。
14 |
15 | ## 迁移
16 |
17 | 之前用eclipse的时候,我定义了一批模板,同时也按照个人的习惯,重新修改了一些代码格式、快捷键绑定和界面配置。这些东西还需要重新在IDEA上配置一番。在Settings窗口内进行一顿折腾后,IDEA终于被调教到七七八八了。
18 |
19 | 另外在使用eclipse的时候,我把26个字母及其大写形式、数字及一些特殊符号放到了trigger关键字符里,结果是,每次敲入新的字符时,eclipse都会试图进行自动补全。现在无须对IDEA重新配置了,因为IDEA默认就是每次击入新的内容时就触发自动补全。再配合其他补全的快捷键,IDEA的补全能力并不逊于eclipse。
20 |
21 | 接下来说说插件:在用eclipse的时候,我是通过Vrapper这个插件来实现Vim模拟(对于Vimer来说,Vim的习惯是走到哪里都要保持的XD)。在用IDEA的使用,我也可以使用IdeaVim这个插件模拟Vim操作。基本上,在eclipse上用到的插件,在IDEA上也能找到对应的插件。这里就不详说了。
22 |
--------------------------------------------------------------------------------
/tools/installWPS.md:
--------------------------------------------------------------------------------
1 | 安装WPS
2 | =====
3 |
4 | 在升级到Ubuntu 13.10之后,原本准备打开操作系统的实验报告,开始做作业,结果发现打开WPS没有反应。
5 |
6 | 呃,是无论你怎么打开,它都不会有一个启动动画跳出来。
7 |
8 | 于是就切到命令行下运行……结果运行WPS后,显示:
9 | > /opt/kingsoft/wps-office/office6/wps blabla…… 无法链接到libgthread.so …… no such file ……
10 |
11 | 嗯,真是奇怪,应该是升级带来的问题吧。
12 |
13 | 32位
14 | -----
15 |
16 | 于是就上网查一下。发现原来是32位的兼容性问题。WPS在打包的时候是打出32位的包,然而大多数人的Linux系统都是运行64位的。
17 |
18 | 要想填平这条鸿沟,就得安装32位下的系统运行库。
19 |
20 | 之前我曾经下过这样的链接库(因为打包成32位的软件并不只有WPS一家),但是可能在升级的过程中,系统把它们当做已经没用的库删掉了。
21 |
22 | 于是乎开始寻找缺少的库。
23 |
24 | 找啊找啊找lib
25 | -----
26 |
27 | 在搜索了一下后,发现需要下载一个`ia32-libs`,据说只要下载了这玩意,所有缺少的32位库都会装上。
28 |
29 | 但是在包管理源里,没用这个东西……估计是年代久远,已经泯灭在历史的尘埃里了。
30 |
31 | 遇到同样的问题的人显然不止我一个。有人也遇到同样的问题,他声称转为安装`g++-multi`(应该是这个名字,记不得了)就可以解决了问题。
32 | 但是却没有讲到底为什么可以解决问题。一般遇到这种情况,这样的解决方案是不可相信的。不过抱着死马当活马医,我还是试了一下。
33 | 反正也不麻烦,不是吗?
34 |
35 | 试了之后,好像有点效果,现在显示的是:
36 | > /opt/kingsoft/wps-office/office6/wps blabla…… 无法链接到libSM.so.6 …… no such file ……
37 |
38 | 嗯,看来并没有解决问题啊……下一个是解决`libSM.so.6`这个库了。
39 |
40 | 链接libSM.so.6
41 | -----
42 |
43 | 用了一下`locate`,发现`libSM.so.6`这个库是存在的。于是用`ln`在wps所在的目录下制造一个`libSM.so.6`的符号链接。
44 | 嗯,感觉wps被骗过了,不再提示找不到`libSM.so.6`。不过显示了`ELFCLASS64`的错误,看来这个`libSM.so.6`是64位的。
45 |
46 | 安装libSM.so.6
47 | -----
48 |
49 | 那么继续上网查查看吧。在网上翻查了半天之后,终于发现如何安装libSM.so.6了。
50 | 只要使用`sudo apt-get install libsm6:i386`。
51 |
52 | 这当然是Debian/Ubuntu系的用法。在不同的发行版的包管理源中,可能使用不一样的命名规则。
53 | 比如`Arch`中,这个库叫做`lib32-libsm6`。
54 |
55 | 安装剩余库
56 | -----
57 |
58 | 既然知道了库的命名规则,那么剩下的事情就简单多了。
59 | 只要运行wps,把它缺少的链接库按照同样的命名规则下载对应的就完成了。
60 |
61 | 于是在接下来的十几分钟中我体验到一种"神挡杀神,佛挡杀佛"的飙车快感。
62 | 在怒下了好几个库之后,我终于用WPS打开了文档。
63 |
64 | 哦也!
65 |
66 | 不过时间已经到了凌晨零点多了……快一点了。太困了以至于不想再写文档了。
67 | 我差点忘了一开始打开WPS是想干什么来的……
68 |
69 | _____
70 |
71 | 最后
72 | -----
73 |
74 | 最后附上我在微博的吐槽:
75 |
76 | >经过一番神挡杀神,佛挡杀佛的寻找 - 安装32位库之后,我终于重新用上了WPS。
77 | >话说WPS打包的时候不要那么坑啊,明明大多数人都是使用64位系统,就不要打成32位的包,逼得用户不得不去寻找32位的系统链接库……
78 | >而且32位的库只会越来越难找了。本来还想做些什么,但是天色已晚,洗洗睡吧。
79 |
80 |
--------------------------------------------------------------------------------
/tools/pandoc.md:
--------------------------------------------------------------------------------
1 | #pandoc
2 |
3 | Pandoc是一个神奇的软件。
4 | 它包括一个Haskell库,
5 | 可以将一种标记格式转换成另一种标记格式。
6 | 还有一个命令行接口来调用这个库。
7 |
8 | ##目前Pandoc支持的标记类型包括:
9 |
10 | * 输入:
11 |
12 | 1. markdown
13 | 2. reStructedText
14 | 3. HTML
15 | 4. LaTex
16 | 5. DocBook
17 | 6. etc...
18 |
19 | * 输出:
20 |
21 | 1. markdown
22 | 2. reStructedText
23 | 3. HTML
24 | 4. LaTex
25 | 5. DocBook
26 | 6. ODT
27 | 7. Emacs OrgMode
28 | 8. RTF
29 | 9. etc...
30 |
31 | 如果系统上安装了LaTex,那么还可以输出PDF。
32 |
33 | 详细地调用方式可以查看man pandoc.
34 | 或者到Pandoc的[官网](http://johnmacfarlane.net/pandoc/README.html).
35 |
36 | ##为什么说Pandoc是神奇的软件呢?
37 |
38 | 首先,pandoc居然是用haskell写的...
39 |
40 | 这不是开玩笑啦。
41 | 我对这一个神奇的函数式编程语言一直久仰大名,
42 | 不过却怀着“虽然好玩但是不太实用的样子”的偏见。
43 | 直到我遇到这个软件,才知道原来haskell还能写出这么神奇的东西。
44 |
45 | 其次,pandoc支持的文件类型之多,超出我的想象。
46 | 嗯,几乎我能叫得出名字的轻量级标记语言它都支持了,还包括我叫不出名字的。
47 | 可以说是,文件格式转换的集大成者。
48 |
49 | 另外,按照官网上的说法,pandoc在各种标记文档间转换自如,
50 | 不是靠简单的正则等价替换,而是使用了不同的reader来生成native表示,
51 | 然后再使用不同的writer来把native表示转换成不同的标记文档。
52 |
53 | 使用这种架构,可以通过增加reader和writer来支持一门新的标记格式。
54 |
55 | 这意味着,这个软件包括了一个插件系统。
56 |
57 | 一般来说,如果一个软件包括了一组快捷键,那么它会比同类软件效率更高。
58 | 但是如果一个软件包括了一个插件系统……嗯,就意味着它已经不是一个单纯的软件,
59 | 更应该称之为“平台”了。
60 | 同类的软件,就如士多比超市,已经无法比拟。
61 |
62 | 在官网的user guide还讲到,pandoc可以使用著名的“嵌入式语言”*lua*进行拓展。
63 | (pandoc自身已经包括了一个lua解释器,所以无须单独安装lua)
64 | 具体的使用方式可以查看**Pandoc User`s Guide#Custom writers**[一节](http://johnmacfarlane.net/pandoc/README.html#custom-writers)。
65 |
66 | 最后,不能不提到的是,pandoc是在GPL协议下发布的开源软件哦!
67 |
68 | 现在就来尝试吧!
69 |
70 | pandoc -f markdown -t rst pandoc.md > pandoc.rst
71 |
72 |
--------------------------------------------------------------------------------
/tools/vimium.md:
--------------------------------------------------------------------------------
1 | chrome 插件 vimium 介绍
2 | ====
3 |
4 |
5 | **vimium是一个chrome插件,用于在chrome中提供像vim这样的纯键盘的快捷操作方式。**
6 |
7 | chrome webstore [链接](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb)
8 |
9 | 该插件是开源的,使用coffeescript创作。
10 | [github地址](https://github.com/philc/vimium)
11 |
12 | 通过使用vimium,我们可以在浏览网页的时候也可以使用“键盘流”,把使用vim时的体验移植到浏览器上。
13 | 就我个人的体验而言,vimium虽然不能完全替代掉触摸板/鼠标,但是已经相当不错了(对一个键盘党而言哈)。
14 |
15 | 所以,在这里我想介绍一下vimium的一些命令,方便大家熟练地使用键盘浏览网页,从此抛弃长长的鼠标线。
16 |
17 | vimium 命令详解
18 | ====
19 |
20 | 首先,vimium的命令是可以在"advanced option"这一项下进行自己的mapping。
21 |
22 | 其次,vimium的具体命令的意思可能会与同名的vim命令不同,毕竟两种命令是应用在不同的任务下的。
23 |
24 | 好,让我打开vimium的配置页,点开右侧的"Show available commands",
25 | 看看有哪些内置命令:
26 |
27 | Navigating the page
28 | ----
29 |
30 | j, : 向下滚动
31 | k, : 向上滚动
32 | h : 向左滚动
33 | l : 向右滚动
34 | gg : 回到顶部
35 | G : 回到底部
36 | d : 向下滚动一页
37 | u : 向上滚动一页
38 | r : 重新载入页面
39 | gs : 显示网页源代码
40 | yy : 复制当前网页url
41 | yf : 复制链接url
42 | p : 在当前页打开刚复制的url(注意不是简单的粘贴!)
43 | P : 在新的一页打开刚复制的url(注意不是简单的粘贴!)
44 | i : 进入插入模式
45 | f : 在当前页打开链接
46 | F : 在新的一页打开链接
47 | o : 打开url,书签或历史记录
48 | O : 打开url,书签或历史记录(在新的一页)
49 | T : 在打开的标签页中搜索
50 | b : 在当前页打开书签
51 | B : 在新的一页打开书签
52 | gf : 到页面上的下一个frame
53 |
54 | Using find
55 | ----
56 |
57 | / : 进入查找模式
58 | n : 到下一个匹配位置
59 | N : 到上一个匹配位置
60 |
61 | Navigating history
62 | ----
63 |
64 | H : 在浏览历史中倒退一步
65 | L : 在浏览历史中前进一步
66 |
67 | Manipulating tabs
68 | ----
69 |
70 | K,gt : 到右边的tab
71 | J,gT : 到左边的tab
72 | g0 : 到第一个tab
73 | g$ : 到最后一个tab
74 | t : 打开新的一页
75 | yt : 复制当前页
76 | x : 关闭当前页
77 | X : 重新打开关闭页面
78 |
79 | Miscellaneous
80 | ----
81 |
82 | ? : 帮助
83 |
84 | That's All
85 | ====
86 |
--------------------------------------------------------------------------------
/translation/pythonFAQPassing.md:
--------------------------------------------------------------------------------
1 | Python FAQ : 参数传递
2 | ====
3 |
4 | [原文出处](http://me.veekun.com/blog/2012/05/23/python-faq-passing/)
5 |
6 | **我怎样才能传引用?Python中是传值还是传引用?**
7 |
8 | 这个问题最常被从C++社区迁移过来的人问起,因为他们惯于记住这两种传递的泾渭分明和一串微妙的不同之处。
9 |
10 | 所以,Python是传值还是传引用的?
11 |
12 | 简单的答案:对象大致上是不加复制地传引用。如果你在一个函数中修改了一个对象,它将在调用时改变。
13 | 但是!你不能赋值给一个参数名并魔法般改变它在调用时的值。
14 |
15 | 详细的答案:都是,或者都不是。嗯……这需要一些篇幅来解释。
16 |
17 | 引用和值
18 | ----
19 |
20 | 在C和C++,变量声明就是储存声明。考虑下面无足轻重的语句:
21 |
22 | int x;
23 |
24 | 这里不是真的创建了名为x的东西。它只是确保,在运行时将会分配出一块足够储存整型的空间,
25 | 而且每当代码中用到x时,它将会到那块空间中查找值。
26 | 至于那块空间是在RAM里还是在交换区里还是躺在床上睡大觉甚至在月球上某个地方,你不需要在乎。
27 | 如果你使用了寄存器,它甚至压根不在系统储存空间中。
28 | 所有的x的储存位置是你跟你的编译器的私下约定——
29 | 承诺每一次你提到x,你都是谈及同样的地方,就像其他任何时候一样。
30 |
31 | 到了函数调用的时候……
32 |
33 | void do_the_needful(some_bigass_struct foo){
34 | /* ... */
35 | }
36 |
37 | `some_bigass_struct foo`依然是一个变量声明。
38 | 在运行时,你将有一块等同于结构体大小的空间,而且在函数中每次提到`foo`,你会确保谈及同样的空间。
39 |
40 | 所以,函数的任何参数都是复制的。当函数调用时,`foo`包括了作为参数逐字节复制进来的结构体。
41 | 这就是传值——函数接受等价的值,但参数有着不一样的本体(或者储存位置)。
42 |
43 | 显然这不适合notrivial类型(译注:比如类类型)。
44 | 你浪费了太多时间来复制整个结构,而且你的函数居然不能修改调用栈任何东西,因为你拥有的仅仅是一个副本。
45 |
46 | C中的修复方法是传指针。从技术上来说,它还是传值,不过这里的“值”是内存地址(仅仅几个比特)。
47 | 尽管指针本体不一样,它依然指向同样的结构体,所以若你乐意,现在可以“弄脏”这个结构体了。
48 |
49 | 再来看看C++。C++觉得指针是令人费解的,
50 | 因为大学费力地在CS102课堂上向连编译器都不甚了解的学生们灌输指针的知识,而他们当然搞不懂。
51 | 好吧,让我们不用指针解决这个问题。
52 |
53 | C++的解决之道是引入references(引用)
54 |
55 | void do_the_needful(some_bigass_struct &foo){
56 | // whoa, inline comment
57 | }
58 |
59 | 现在你可以毫不犹豫地调用`do_the_needful(bar)`。
60 | 看上去整个结构体都传递进去了,但`&`使得`foo`成为`bar`的一个别名。
61 | 换句话说,`foo`不再是运行时的一块储存空间,而是调用栈中的一块空间的另一种说法。
62 | 因为`foo`是`bar`,你甚至可以赋值给`foo`并覆盖`bar`——在C中做这样的事,你不得不使用双重指针来避免复制。
63 |
64 | 这就是传引用:同样的储存空间由两个不同的变量共享,一个在C中不可能的技巧。
65 |
66 | 回到Python
67 | ----
68 |
69 | 经过这些(希望比较清晰的)定义后,让我们再看看Python的做法。
70 |
71 | def do_the_needful(foo):
72 | pass
73 |
74 | obj = SomeBigassClass()
75 | do_the_needful(obj)
76 |
77 | `foo`是传值还是传引用?
78 |
79 | 简单的回答是,都不是。但是完整的答案是这个问题对于Python是个伪命题!
80 | 变量名并不像C/C++中一样对应着预先分配的储存空间。Python变量名仅仅是:变量名。
81 |
82 | 比较:
83 |
84 | * 在C中,`int x = 3;`声明了一块叫`x`的储存空间,并写入`3`。
85 | * 在Python中,`x = 3`创建值`3`并以`x`作为它的名字。所有的值都是对象;它们可以拥有许多绰号或者默默无名。
86 |
87 | 比个喻:C变量就像写入值的盒子。Python名字是你贴在值上的标签。
88 | 这里有个酷的[示例](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables)。
89 |
90 | 很像C的一点,参数传递就像是赋值。函数中`foo`参数就像`foo = obj`那样被赋值;效果是一样的。
91 |
92 | 这不是传值,因为没有产生复制,而且函数拥有和调用者同样的对象。
93 | (Python从不隐式复制任何东西) 它是传引用么?至少目前看来就像C++的引用。
94 |
95 | def increment(n):
96 | n = n + 1
97 |
98 | i = 1
99 | print i
100 | increment(i)
101 | print i
102 |
103 | 不,仅仅是输出两次1!在函数中,赋值给`n`不会影响`n`所引用的值;它只是让`n`这个名字引用另外别的东西。
104 | 所以`n`将会是`2`。然后函数结束了,`n`随风而逝。结果`i`没有改变因为你没有对`i`做任何事情。
105 |
106 | 这跟改变一个现有的值不一样:
107 |
108 | def lengthen(n):
109 | n.append(2)
110 |
111 | i = [1]
112 | print i # [1]
113 | lengthen(i)
114 | print i # [1,2]
115 |
116 | 这一次,`n`不再被重新赋值;相反,方法调用直接修改了`n`的值。
117 | 还是熟悉的列表,`n`和`i`依然引用它,但是列表的内容改变了。
118 |
119 | 懂了没?
120 | 还有另外一个小技巧:操作符重载在这里起到不可思议的作用。
121 | 举个例子,你可以用**+=**重写这两函数。在`increment`中,`i`不会改变,但在`lengthen`中,它变了!
122 | 这是因为ints(还有strs,tuples,以及其他类型)是不可变的,所以它们通过创建一个新对象并赋值给原对象来实现+=。
123 | 但是lists是可变的,所以作为简写法,+=表现得如同`.extend()`并原地(in-place)修改列表。
124 | 这种古怪之处与传递无关,仅仅是因为对+=不同的重载。
125 |
126 | 总之,嗯,这当然也不是传引用。
127 |
128 | 如果有区别的话,Python走的是第三条道路:pass-by-object。
129 |
130 | 替代的做法
131 | ----
132 |
133 | 等等,当你写下`increment`时,你想做什么?
134 |
135 | * **返回原料**
136 |
137 | 在C/C++中指针/引用参数的大多数用法是获取一些状态值,并且函数的结果通过修改特定的输入变量表现出来。
138 |
139 | 但这不是C,所以为什么我们要这样做呢?你可以仅仅返回多个值。
140 |
141 | def foo():
142 | return True,"abc"
143 |
144 | status,value = foo()
145 |
146 | 或者,在错误的时候抛出异常。当调用者忘记检查状态码时,也不会大吃一惊。
147 |
148 | * **使用方法**
149 |
150 | 如果你*真的*想修改调用者的值,你就可以使用一个对象来储存关联的值,并把函数变为方法。
151 | 方法可以跟所需要的调用者的属性打交道,并把修改后的状态封装起来。
152 |
153 | class Increment(object):
154 | def __init__(self,count):
155 | self.count = count
156 |
157 | def increment(self):
158 | self.count += 1
159 |
160 | i = Increment(1)
161 | print i.count # 1
162 | i.increment()
163 | print i.count # 2
164 |
165 | * **使用可变对象**
166 |
167 | 最后一招,你可以把值包装在list(或dict,object,etc.),传递到函数去,让函数修改它的值,并在输出端提取新的值。
168 |
169 | 我开玩笑而已,千万不要这么做。
170 |
171 | 寻根究底
172 | ----
173 |
174 | 如果你想要知道的话!在CPython中,每一个Python的值实际上是`PyObject*`。所以参数传递,赋值还有别的表现得跟C语言中的是差不多的,
175 | 如果你写的C中所有的东西都是指针(并且不用双重指针来表演障眼法)。
176 |
177 | void increment(int *n){
178 | int newval = *n + 1;
179 | n = &newval;
180 | }
181 |
182 | int i = 1;
183 | increment(&i);
184 |
185 | 这跟上面的Python函数等价的。(请忽略接下来的segfault)
186 | 赋值给`n`不会有什么变化,因为只有指针指向的值是共享的。
187 | 但是如果值类似于列表是可变的,你可以在原地改变它。
188 |
189 | 这就是为什么两个答案都是对的:你可以说Python是传值,当值是指针……你也可以说Python是传引用,当引用是副本。
190 | 你也可以说它是"pass-by-pointer"。不过这就是钻牛角尖了。
191 |
192 | 结论
193 | ----
194 |
195 | * Python函数不会替换调用参数所引用的对象。
196 | * 对一个参数名重新赋值不会起任何作用。
197 | * Python函数可以修改参数,如果这个参数是可变的。
198 | * 在Python中没有什么是被隐式复制的。
199 | * 停止用C++的思维打量Python,你会感觉更良好。
200 |
201 | 拓展阅读
202 | ----
203 |
204 | * Python官方文档没有透彻地诠释传递的语法。我能找到的最好的说明在[这里](http://docs.python.org/reference/expressions.html#calls )
205 | * 这个[示例](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables )真的酷毙了。
206 | * Pass-by-object有时也叫pass-by-sharing.from [维基百科](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing)
207 |
208 |
--------------------------------------------------------------------------------
/translation/受检异常带来的问题.md:
--------------------------------------------------------------------------------
1 | 受检异常带来的麻烦
2 | ====
3 |
4 | **与Anders Hejlsberg的一次会谈,第二部分**
5 |
6 | 采访人 Bill Venners , Bruce Eckel
7 |
8 | 2003年8月18日
9 |
10 | ##摘要
11 | ----
12 |
13 | **Anders Hejlsberg,C#的首席架构师,跟Bruce Eckel和Bill Venners讨论了由受检异常(checked exception)带来的版本(versionability)和拓展性(scalability)的问题。**
14 |
15 | (以下略去人物介绍和访谈背景)
16 |
17 | ##访谈内容
18 | ----
19 |
20 | (跳过第一部分)
21 |
22 | Bruce Eckel: C# 没有受检异常。
23 | 你为何决定不在C#中加入受检异常呢?
24 |
25 | Anders Hejlsberg: 在我看来,受检异常有两个大问题:拓展性和版本。
26 | 我听说你也写过一些关于受检异常的东西,并且倾向于同意我们的观点。
27 |
28 | Bruce Eckel: 我曾认为受检异常是好的。
29 |
30 | Anders Hejlsberg: 的确。坦白来说,受检异常看上去是个不错的点子。
31 | 我完全同意受检异常是个好特性。
32 | 只是某些实现存在问题罢了。
33 | 比如它在Java中的实现,我认为只是拿一堆问题来取代另一堆问题。
34 | 到了最后,我还是搞不懂这一切是否变得更简单了。也许变得更复杂呢。
35 |
36 | Bruce Eckel: 在C#的设计团队中,普遍存在对受检异常的反对吗?
37 |
38 | Anders Hejlsberg: 不,我认为我们的设计团队对此是一致的。
39 |
40 | C#基本上对受检异常不置可否。
41 | 一旦有更好的解决方法———相信我,我们依然在考虑——我们会回头添加一些特性。
42 | 我深信,如果你不知道什么是正确的,或该如何改进,就应该保持沉默和中立,而不是草率推出一个框架。
43 |
44 | 如果你让菜鸟程序员写一个日历控件,他们多半会这么想:“
45 | 我要写一个世上最好的日历控件!
46 | 它将会通过多态展示不同的类型。
47 | 它将有显示器(displayers)和mungers,还将有这个、那个……
48 | 他们需要两个月才能发布这个日历应用。
49 | 他们把所有的基础设施留在控件里,并花上两天在上面堆砌一个糟糕的日历。
50 | 他们甚至会认为,下一版还要这么做。
51 |
52 | 一旦他们开始反思如何具体实现他们的抽象设计,
53 | 就会意识到设计彻头彻尾地错了。
54 | 现在,他们无路可走,只好从头再来。
55 | 对此,我已经见怪不怪了。
56 | 我坚信最小主义(minimalist)的原则。
57 | 除非你真的是要解决通用的问题,不要为解决一个特例而推出一个框架,
58 | 因为你不知道那个框架会是什么样。
59 |
60 | Bruce Eckel: 极限编程认为,“做可以运行的最简单的事情”。
61 |
62 | Anders Hejlsberg: 是呀,爱因斯坦曰:“尽可能最简单,而不是更简单。”
63 | 我顾虑的是,受检异常是程序员的镣铐。
64 | 你会看到程序员使用着包裹了重重throw语句的新API,
65 | 然后你会发现到他们的代码多么地复杂,
66 | 并且意识到受检异常根本帮不上什么。
67 | 问题在于专断的API设计者要求你怎样去处理异常。他们本不应该这么干的。
68 |
69 | ---
70 |
71 | ###版本(versionability)
72 |
73 | Bill Venners: 你提到了受检异常带来的拓展性(scalability)和版本(versioning)上的顾虑。
74 | 你可以解释一下提到的这两点吗?
75 |
76 | Anders Hejlsberg: 从版本开始吧,因为这一点相当显而易见。
77 | 假设我写了个抛出异常A,B,C的方法*foo*。
78 | 在*foo*的第二版,我加入了新的特性,现在*foo*抛出了异常D。
79 | 由于当前的调用者几乎不会去处理异常D,我不可能声明抛出异常D。
80 |
81 | 在新的版本里加入新的异常声明将会破坏客户代码。
82 | 好比在接口中加入新的方法。
83 | 在你发布(publish)一个接口后,实际上它是不可变的,因为一旦加入新的方法,所有的实现都会受株连。
84 | 你不得不创建一个新的接口。
85 | 同样地,应对新的异常D,要不创建新的方法*foo2*,要不在*foo*里面捕获异常D,并将D转换成A/B/C。
86 |
87 | Bill Venners: 但是即使在没有受检异常的语言里,你不也可能因此破坏客户代码?
88 | 如果新的*foo*将抛出新的交由客户去处理的异常,他们的代码不也会由于缺乏对新异常的预见,而遭受破坏吗?
89 |
90 | Anders Hejlsberg: 不,因为在大多数情况下,人们不在乎。
91 | 他们不会处理这样的异常。
92 | 在信息循环中,会有底层的异常处理器。
93 | 异常处理器会诊断出哪里出错并保持运行。
94 | 程序员到处写下try...finally来保护代码,一旦异常发生,他们可以回到出错的地方,但他们并不对处理异常感兴趣。
95 |
96 | throws语句,至少在Java的实现中,不是必须强迫你处理异常,但若不去处理,它将强迫你注意到有异常抛出了。
97 | 它要求你要不捕获异常,要不把异常加入到你自己的throws语句中。
98 | 为了满足这个要求,人们不得不做些可笑的事。
99 | 比如,他们用“throws Exception”来修饰每一个方法。
100 | 这仅仅让受检异常的美好预期落了个空,还让程序员写出僵化的代码(gobbledy gunk)。
101 | 这一点都帮不上什么忙。
102 |
103 | Bill Venners: 所以你认为更普遍的做法是调用者将异常交由调用栈上的通用catch语句处理,而不需要显式处理它?
104 |
105 | Anders Hejlsberg: 人们总肤浅地认为,异常是为被处理而生的。
106 | 在我看来,事实上,在一个良好的应用中,十次有一次是由try...finally来完成try...catch做的事。
107 | 或者在C#中,使用类似于try...finally的语句。
108 |
109 | Bill Venners: finally里的是什么?
110 |
111 | Anders Hejlsberg: 在finally里,你不需要处理异常就能保护你的代码。
112 | 你只需要在一些地方处理错误。
113 | 显然在一些事件驱动型应用,你一般只在主要的信息冒泡出放置异常处理,来对付那些发生的异常。
114 | 当然你需要彻底地回收(deallocating)所有的获得的资源,等等。
115 | 你在最后才打扫战场,所以你总保持一个确定的状态。
116 | 你不会想要一个在100个不同的地方处理异常,冒出一个错误报告框的程序。
117 | 假如你想改变产生对话框的方式呢?
118 | 那将会很糟糕。
119 | 异常处理应该凝练,并且一旦异常产生,你应该优先保护好自己的代码。
120 |
121 | ---
122 |
123 | ###拓展性(scalability)
124 |
125 | Bill Venners: 受检异常在拓展性上的问题呢?
126 |
127 | Anders Hejlsberg: 这个问题一定程度上跟版本上的问题有关。
128 | 即使是在小范例中,你也会看到你需要捕获一个FileNotFoundException,这是不是过头了?
129 | 嗯,这仅仅是想要调用一个API的结果。
130 | 当你开始建造一个与四五个不同的子系统交互的大型系统,问题越发严重。
131 | 每个子系统会抛出四到十个异常。
132 | 现在,每一次当你在梯状的架构中蹒跚时,埋在脚下的是指数增加的需要处理的异常。
133 | 最后,你不得不以抛出四十个异常的声明告终。
134 | 然而,一旦你把它加入另一个子系统,你可能需要的是八十个异常抛出声明。
135 | 就像失去控制的气球,异常们一跃而出。
136 |
137 | 从大的方面说,受检异常如此恼人以至于人们开始敷衍对待。
138 | 他们不是每次都用"throws Exception",就是——我都不能想清楚有多少次了——用毛茸茸的try...catch包裹起来。
139 | 他们想,“我终究会回来的解决这些空catch语句的”,然后就没有然后了。
140 | 这种情况下,受检异常实际上损害了系统的质量。
141 |
142 | 当你谈到所有这些问题时,对我来说,为C#加入受检异常机制需要更慎重的考虑。
143 | 也就是说,了解什么异常可以抛出,并且有一系列方法来检查是至关重要的。
144 | 我不认为我们可以构造严格的而且快的准则来发现一个编译错误。
145 | 但我认为我们可以尽力改善分析工具来发现可疑代码,包括未捕获的异常,并且向你指出潜在的漏洞。
146 |
147 | **END**
148 |
149 | [原文在此](http://www.artima.com/intv/handcuffs.html)
150 |
--------------------------------------------------------------------------------
/tucao/2014-5-7.md:
--------------------------------------------------------------------------------
1 | 2014 5 7
2 | =====
3 |
4 | 虽然题目写的是2014年5月7日,但是记的是昨天发生过的事。
5 |
6 | 昨天,我终于下定决心开始写js部分。
7 | 本着工欲善其事,必先利其器的原则(其实是恐惧拖延症又复发了,所以找了个借口),
8 | 我开始完善原来的Vim的JS编辑功能。
9 |
10 | 嗯,之前就已经给Vim安装了语法高亮的插件,在高亮方面已经没有了缺陷。
11 |
12 | 那么接下来是要提供一个lint工具。特别是像我这种容易产生typo的人,一个语法检查的工具自然是必不可少的。
13 |
14 | 著名的Vim插件`syntastic`几乎提供了每种Vim支持的编程语言的语法检查功能。
15 | 事实上,`syntastic`只是提供了一个接口,把外部的语法检查工具与Vim内部的缓冲区文本连接在一起了。
16 | 不过`syntastic`不能对JS进行语法检查。
17 |
18 | 在没有任何第三方插件的帮助下,`syntastic`一般是通过调用编译器/解释器的自带语法检查选项来检查语法问题的。
19 | 不过,虽然我安装了Node,但是貌似Node没有检查输入的JS文件的语法问题的选项。
20 | 这就导致了,如果不引入第三方的插件,`syntastic`是无法检查JS中的语法问题的。
21 |
22 | 所以我开始找JS的语法检查器。
23 |
24 | 在网上淘了一下,大概有三个可以入我的候选名单:
25 | 1. eslint
26 | 2. gslint
27 | 3. jshint
28 |
29 | 首先试用第一个:
30 |
31 | eslint
32 | -----
33 |
34 | 嗯,这个东东看起来好强大,不过有一个问题,就是它的代码洁癖太厉害了,一上来就报了个`use strict`的错误。
35 |
36 | 什么意思呢?在JS里面,如果我们设置了"use strict"的声明,浏览器就会依照strict mode的标准解析我们的代码。
37 | 而eslint默认按照strict mode来评判JS代码,而且它还会要求你提供一个`use strict`的声明。
38 |
39 | 有没有搞错!我没有声明用`use strict`就是指在宽松模式下嘛!
40 | 如果使用了`strict mode`,即使像jQuery这种久经考验的类库也会导致浏览器报错。
41 | 不过这也许是jQuery为了兼容各种浏览器所作出的妥协。
42 | 当然在Node里就没有这种问题了,因为在Node里所有的包都需要经过`strict mode`的考验。
43 |
44 | 那么就必须设置eslint忽略掉`strict mode`。
45 | 这个是可以设置的。
46 | 在经过一番折腾之后,我终于明了eslint的配置方法,就是在`syntastic`的配置中指定eslint的配置路径。
47 | eslint的配置文件是JSON文件,在里面的rules元素中设置`'strict' : 0` 就好了。
48 |
49 | 但是eslint还是不肯放开我的JS代码。
50 |
51 | 现在可以看到一个严重的问题。就是eslint会把`window`,`localStrage`等浏览器环境里的对象当作`undef variable`。。。
52 | 呃,不过这也可以配置的,可以设置eslint的目标运行环境为brosewer,这样它就会放过浏览器定义的全局对象了,除了——
53 |
54 | 除了`console`。这怎么能行呢?`console`可是前端调试神器。
55 | 翻看了官方文档,他们居然把`no-console`当作一个rule。
56 | 给出的理由是不应该使用`console`把程序运行的细节暴露给用户。
57 | 嗯,这可不是个好理由啊。我可以在调试时使用`console`,然后在调试后删掉。你犯不着产生一大堆错误提示恶心我吧?
58 | 或者,我也可以选择不删,使用debug mode包装每一个调试函数,在启动debug的时候调用`console`,其余状态下什么都不干。
59 | 这也不会向用户暴露程序执行的细节。
60 |
61 | 当然也许存在取消`no-console`这个规则的设置。但是这帮“代码洁癖爱好者”,我还是适应不了,果断换!
62 |
63 | 下一个:gslint
64 |
65 | gslint
66 | -----
67 |
68 | gslint是google前端团队的出品。但是这并不一定代表什么……
69 | 尤其是,当我看到他们的项目主页是2012年时更新的,而且该项目的最后一次commit是去年秋天。
70 |
71 | 虽然如此,不过能用就行……
72 |
73 | 等到我看到install guide的时候,我的信心又少了一些。
74 | 比起其他的lint工具,gslint居然不是用js写的,而是用python写的。
75 | 而且它的安装方式还是用easy\_install。
76 | 而如今,easy\_install的唯一的作用,就是下载pip。这让人怀疑,这个软件的开发时间,似乎比2012年之前吧。
77 | 恐怕是一笔代码债务……
78 |
79 | 虽然怀着一颗忐忑的心,我还是下下来试试看。
80 | 结果果然不出我所料,虽然它给我提出了一大堆编程风格上的问题,但是真要指出一些语法上的错误,一点都不中用。
81 | 唉,又是一个Google的弃宠。
82 |
83 | 下一个:jshint
84 |
85 | jshint
86 | -----
87 |
88 | 为了不显得罗嗦,我就写下最终的结局吧。
89 | 在故事的最后,jshint和syntastic幸福快乐地生活在一起。
90 |
91 | 在我看来,jshint是恰到好处,既不会太唠叨,也不会太粗笨。
92 | 于是乎,js的语法检查就托付给它了。
93 |
--------------------------------------------------------------------------------
/whatWillTheNumIsInC.md:
--------------------------------------------------------------------------------
1 | 在C语言里,一个数是什么类型的?
2 | ====
3 |
4 | 之前我一直在做一个测试计算LU分解的最佳方法的实验。但是有一个诡异的错误,总在算到30000行矩阵时出现,程序会停留在那里并一直卡着不动,有时又会产生segment fault。
5 |
6 | 由于这个3万行矩阵问题,我大胆探索、小心求证的道路被隔断了。
7 | 我把这个问题命名为“3万矩阵陷阱”。虽然我苦思冥想多日,但是依然不得其解。
8 | 这个问题一直缠绕在我的心头。
9 |
10 | 一天晚上,我躺在床上时,突然意识到30000行float类型矩阵,其大小已经超过int类型可以表示的范围!会不会是malloc的参数问题?
11 |
12 | 果然,我检查了malloc的参数,虽然malloc的形参是size_t类型(在64bit系统上是64bit大小),但是我传入的是int,显然不会帮我提升类型。
13 | 也就是说,malloc现在接受的是一个由于溢出而产生的负数。
14 |
15 | 那么,malloc会对负数做什么处理呢?于是我写了个test.c
16 |
17 | #include
18 | #include
19 | int main()
20 | {
21 | int overflow = 30000 * 30000 * 4;
22 | int *c = (int*)malloc(overflow);
23 | printf("%x\n",c);
24 | }
25 |
26 | 答案是很坑爹的:有警告(当然是因为计算溢出而出现警告,不是因为malloc的参数问题而出现警告),
27 | 无编译错误(shit!),
28 | 而且malloc还很安静地执行了,不抛出任何异常(当然没有)或者segment fault.
29 | 不过执行结果很蛋疼:c是一个空指针。
30 | 空指针是C/C++中邪恶的精灵,因为它带来的后果是不可预期的。
31 | 而且当bug出现时,你会找错病因所在。
32 | 这就解释了为什么3万矩阵问题会如此古怪。
33 | 看来这又是C语言的又一个设计缺陷。难怪有经验的程序员会检测每一次内存分配后指针的值。
34 |
35 | 为什么起一个这样的题目?
36 | ----
37 |
38 | 现在你应该会感到奇怪,既然是malloc的问题,为什么题目会提到C语言中数字的类型呢?
39 |
40 | *在发现malloc的问题,我又想起已经曾感到好奇的事:在C语言中,字面量数字是什么类型的?*
41 |
42 | 为了查证这个问题,我又写了个t2.c:
43 |
44 | printf("%d\n",30000 * 30000 * 4);
45 |
46 | 猜猜我得到什么?一个负数。
47 |
48 | 这能说明什么问题么?不能,因为我用了%d,这个标记只能够输出int类型。
49 | C/C++中古怪的类型自动转换偷偷的帮我把字面量类型转换成int类型。
50 | 不信你可以试试这个:
51 |
52 | printf("%d\n",(unsigned int)(30000 * 30000 * 4));
53 |
54 | 那么说printf函数是用不了的。
55 | sizeof呢?也不行,sizeof返回一个unsigned long。而且无论是unsigned int 或者int都是4个字节。
56 | 顺便说一下,unsigned long 和 long都是8个字节。而且在64bit的系统中,long long和long都是8位的,没想到吧!
57 |
58 | 最后我想到了办法,用if判断语句。
59 |
60 | int n = 1024 * 1024 * 1024;
61 | if(1024 * 1024 * 1024 * 2 < n)
62 | {
63 | printf("You are right!");
64 | }
65 |
66 | 输出结果是“You are right!”。
67 |
68 | Oh,yeah!当然你也许会质疑,不过是自动类型转换的又一个恶作剧罢了。
69 | 那么看看这个:
70 |
71 | unsigned int n = 1024 * 1024 * 1024;
72 | if(1024 * 1024 * 1024 * 2 < n)
73 | {
74 | printf("You are right!");
75 | }
76 |
77 | 输出结果是“You are right!”。
78 |
79 | 这下你可质疑不了了吧!
80 |
81 | 显然,在C语言中,数字字面量的类型是int类型,不过由于自动类型转换的存在,使得这一事实相对模糊。
82 |
83 | 于是乎有了下面的结果:
84 |
85 | if(1024 * 1024 * 1024 * 2 < 0)
86 | {
87 | printf("You are right!");
88 | }
89 |
90 | Of course, I am right again!
91 |
--------------------------------------------------------------------------------