mirror of
https://github.com/oldratlee/translations.git
synced 2026-04-05 03:28:11 +08:00
improve wording
This commit is contained in:
@@ -81,7 +81,7 @@ Chinese translations for classic IT resources.
|
||||
# `Erlang`/`Elixir`
|
||||
|
||||
1. [`Erlang`之父学习`Elixir`语言的一周](a-week-with-elixir/README.md)
|
||||
作为`Erlang`之父 _Joe Armstrong_,对`Erlang VM`上的新语言`Elixir`做了很精彩的评论和思考。『特定领域专家的专业直觉』、『编程语言设计的三定律』、『管道运算符避免恶心代码』、『`Elixir`的`sigil`引出的程序语言如何定义/解释字符串』等等问题的讨论,个性鲜明又幽默诙谐的行文风格,都能强烈感受到 _Joe Armstrong_ 深入广博的老黑客风范。
|
||||
作为`Erlang`之父 _Joe Armstrong_,对`Erlang VM`上的新语言`Elixir`做了很精彩的评论和思考。『特定领域专家的专业直觉』、『编程语言设计的三定律』、『管道操作符避免恶心代码』、『`Elixir`的`sigil`引出的程序语言如何定义/解释字符串』等等问题的讨论,个性鲜明又幽默诙谐的行文风格,都能强烈感受到 _Joe Armstrong_ 深入广博的老黑客风范。
|
||||
|
||||
# `Lisp`
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## 译序
|
||||
|
||||
作为`Erlang`之父 _Joe Armstrong_,对`Erlang VM`上的新语言`Elixir`做了很精彩的评论和思考。『特定领域专家的专业直觉』、『编程语言设计的三定律』、『数据的版本化设计』、『管道运算符避免恶心代码』、『静态单赋值』、『`Elixir`的`sigil`引出的程序语言如何定义/解释字符串』、『函数定义和函数字面量在`Shell`的不一致性』等等主题的讨论,个性鲜明又幽默诙谐的行文风格,都能强烈感受到 _Joe Armstrong_ 深入广博的老黑客风范。
|
||||
作为`Erlang`之父 _Joe Armstrong_,对`Erlang VM`上的新语言`Elixir`做了很精彩的评论和思考。『特定领域专家的专业直觉』、『编程语言设计的三定律』、『数据的版本化设计』、『管道操作符避免恶心代码』、『静态单赋值』、『`Elixir`的`sigil`引出的程序语言如何定义/解释字符串』、『函数定义和函数字面量在`Shell`的不一致性』等等主题的讨论,个性鲜明又幽默诙谐的行文风格,都能强烈感受到 _Joe Armstrong_ 深入广博的老黑客风范。
|
||||
|
||||
[自己](http://weibo.com/oldratlee)理解粗浅,而本文讨论是语言设计,且作为老一代黑客的作者对计算机领域中那些现在我们在日常编程中不再要去使用理解的主题或是思想又真是信手拈来(如`Prolog`/`DCG`、`Lisp`/宏、`sigil`、不可变闭包、语言设计的兼容性),翻译中肯定会有不少不足和不对之处,欢迎建议([提交Issue](https://github.com/oldratlee/translations/issues))和指正([Fork后提交代码](https://github.com/oldratlee/translations/fork))!
|
||||
PS:为什么要整理和审校翻译 参见 [译跋](translation-postscript.md)。
|
||||
@@ -28,13 +28,13 @@ PS:为什么要整理和审校翻译 参见 [译跋](translation-postscript.md
|
||||
- [2. `fun`和`def`不同](#2-fun%E5%92%8Cdef%E4%B8%8D%E5%90%8C)
|
||||
- [3. 函数名称中有个额外的点号](#3-%E5%87%BD%E6%95%B0%E5%90%8D%E7%A7%B0%E4%B8%AD%E6%9C%89%E4%B8%AA%E9%A2%9D%E5%A4%96%E7%9A%84%E7%82%B9%E5%8F%B7)
|
||||
- [4. 发送操作符](#4-%E5%8F%91%E9%80%81%E6%93%8D%E4%BD%9C%E7%AC%A6)
|
||||
- [5. 管道运算符](#5-%E7%AE%A1%E9%81%93%E8%BF%90%E7%AE%97%E7%AC%A6)
|
||||
- [5. 管道操作符](#5-%E7%AE%A1%E9%81%93%E6%93%8D%E4%BD%9C%E7%AC%A6)
|
||||
- [6. `Elixir`有`sigil`](#6-elixir%E6%9C%89sigil)
|
||||
- [7. `docstring`](#7-docstring)
|
||||
- [8. `defmacro`的引用和反引用](#8-defmacro%E7%9A%84%E5%BC%95%E7%94%A8%E5%92%8C%E5%8F%8D%E5%BC%95%E7%94%A8)
|
||||
- [9. 额外的符号](#9-%E9%A2%9D%E5%A4%96%E7%9A%84%E7%AC%A6%E5%8F%B7)
|
||||
- [10. 奇怪的空白符](#10-%E5%A5%87%E6%80%AA%E7%9A%84%E7%A9%BA%E7%99%BD%E7%AC%A6)
|
||||
- [11. 闭包行为完全正确 —— 哦耶](#11-%E9%97%AD%E5%8C%85%E8%A1%8C%E4%B8%BA%E5%AE%8C%E5%85%A8%E6%AD%A3%E7%A1%AE-%E2%80%94%E2%80%94-%E5%93%A6%E8%80%B6)
|
||||
- [11. 闭包行为完全正确 —— 哦耶](#11-%E9%97%AD%E5%8C%85%E8%A1%8C%E4%B8%BA%E5%AE%8C%E5%85%A8%E6%AD%A3%E7%A1%AE--%E5%93%A6%E8%80%B6)
|
||||
- [结束语](#%E7%BB%93%E6%9D%9F%E8%AF%AD)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
@@ -64,7 +64,7 @@ _Dave_ 对`Elixir`很感兴趣,在他的书里这样写道:
|
||||
|
||||
但得知 _Dave_ 与`Elixir`『看对眼』时,我很想知道他为什么会这样。
|
||||
|
||||
无独有偶,_Simon St. Laurent_ 也出了本`Elixir`的书。_Simon_ 的[《_Introducing Erlang_》](http://www.amazon.com/Introducing-Erlang-Simon-St-Laurent/dp/1449331769)一书表现不俗,我和他还邮件沟通过几次,所以有些事已经在酝酿了。而 _Pragmatic Press_ 和 _O'Reilly_ 出版社都在争着要出版`Elixir`,我知道在`Erlang VM`上的事已经在发生了,而我自己还没注意到。毫无疑问我Out了!
|
||||
无独有偶,_Simon St. Laurent_ 也出了本`Elixir`的书。_Simon_ 的[《_Introducing Erlang_》](http://www.amazon.com/Introducing-Erlang-Simon-St-Laurent/dp/1449331769)一书表现不俗,我和他还邮件沟通过几次,所以有些事已经在酝酿了。当 _Pragmatic Press_ 和 _O'Reilly_ 出版社都在争着要出版`Elixir`,我知道在`Erlang VM`上的事已经在发生了,而我自己还没注意到。毫无疑问我Out了!
|
||||
|
||||
我发封邮件给 _Dave_ 和 _Simon_,他们爽快地借给我了样书,现在可以开始阅读了……谢了二位……
|
||||
|
||||
@@ -81,7 +81,7 @@ _Dave_ 对`Elixir`很感兴趣,在他的书里这样写道:
|
||||
> 【译注】:
|
||||
>
|
||||
> **_`sigil`_** 是指在变量名中包含符号来表达数据类型或作用域,通常作为前缀,如`$foo`,其中`$`就是个`sigil`。
|
||||
> 像本文中说的例子,`sigil`也可以能对常量加上字母符号,`r"abc"`,其中`r`是`sigil`,把字符串转成正则表达式。
|
||||
> 像本文中说的例子,`sigil`也可以能对常量加上字母符号,`r"abc"`,其中`r`是`sigil`,约定成转换字符串成正则表达式的语法糖。
|
||||
> 详见[`wikipedia`词条`sigil`](https://en.wikipedia.org/wiki/Sigil_(computer_programming))
|
||||
>
|
||||
> ---------------
|
||||
@@ -287,7 +287,7 @@ Process ! Message
|
||||
|
||||
这点会使`occam-pi`程序员很难转到`Elixir`。什么?只需要简单地用 **`!`** 而不是`<-`,就可以让一波`occam-pi`的程序员喜大普奔地哭喊着『药 !药!切克闹!!美好生活现在到!!!』然后立马就转到`Elixir`。以后老司机告诉你真是这样的,这个改变会让人开心得像过节一样。
|
||||
|
||||
# 5. 管道运算符
|
||||
# 5. 管道操作符
|
||||
|
||||
这就是之前我说的一个非常好非常好的想法,并且非常非常简单就能掌握,以至于没人会给你称赞。这就是生活。
|
||||
|
||||
@@ -540,7 +540,7 @@ def f(x) do
|
||||
end
|
||||
```
|
||||
|
||||
这个问题完全是可以解决的,我在`erlang2`语言实验并解决了。
|
||||
这个问题完全是可以解决的,我已经在`erlang2`语言中实验并解决了。
|
||||
|
||||
# 结束语
|
||||
|
||||
@@ -552,6 +552,6 @@ end
|
||||
|
||||
_Dave_ 很喜欢`Elixir`,我也觉得很酷,我想我们俩会在使用过程中找到更多乐趣的。
|
||||
|
||||
像`WhatsApp`这个应用和全世界一半手机网络的关键部分都是搭建在`Erlang`之上。当技术变得更加亲和,当新一批热衷者进入阵营,让我现在怀着非常欣喜的心情关注着后续要发生的变化。
|
||||
像`WhatsApp`应用和全世界一半手机网络的关键部分都是搭建在`Erlang`之上。当技术变得更加亲和,当新一批热衷者进入阵营,让我现在怀着非常欣喜的心情关注着后续要发生的变化。
|
||||
|
||||
这是篇即兴的文章。也许会有些不妥之处,欢迎大家指正。
|
||||
|
||||
@@ -163,7 +163,7 @@ regExp.setPatternSyntax(Qt::WildcardSyntax);
|
||||
|
||||
为实现这种类型的`API`,需要借助底层对象的懒创建。例如,对于`QRegExp`的例子,在不知道模式语法(`pattern syntax`)的情况下,在`setPattern()`中去解释`"."`就为时过早了。
|
||||
|
||||
属性之间常常有关联的;在这种情况下,我们必须小心处理。思考下面的问题:当前的风格(`style`)提供了『默认的图标尺寸』属性 vs. `QToolButton`的『`iconSize`』属性:
|
||||
属性之间常常有关联的;在这种情况下,我们必须小心处理。思考下面的问题:当前风格(`style`)提供的『默认的图标尺寸』属性 vs. `QToolButton`的『`iconSize`』属性:
|
||||
|
||||
```cpp
|
||||
toolButton->setStyle(otherStyle);
|
||||
@@ -174,7 +174,7 @@ toolButton->setStyle(yetAnotherStyle);
|
||||
toolButton->iconSize(); // returns (52, 52)
|
||||
```
|
||||
|
||||
提醒一下,一旦设置了`iconSize`,设置就会一直保持,即使改变当前的风格。这 **_很好_**。但有的时候需要能重置属性。有两种方法:
|
||||
提醒一下,一旦设置了`iconSize`,设置就会一直保持,即使改变当前风格。这 **_很好_**。但有的时候需要能重置属性。有两种方法:
|
||||
|
||||
1. 传入一个特殊值(如`QSize()`、`-1`或者`Qt::Alignment(0)`)来表示『重置』
|
||||
1. 提供一个明确的重置方法,如`resetFoo()`和`unsetFoo()`
|
||||
@@ -212,8 +212,8 @@ struct Hsv { int hue, saturation, value };
|
||||
Hsv getHsv() const;
|
||||
```
|
||||
|
||||
> 【译注】:函数的『入参』和『出参』的混用会导致 API 接口语义的混乱,所以,使用指针,在调用的时候,实参需要加上“&”,这样在代码阅读的时候,可以看到是一个『出参』,有利于代码阅读。(但是这样做,在函数内就需要判断指针是否为空的情况,因为引用是不需要判断的,所以,这是一种 trade-off)
|
||||
>
|
||||
> 【译注】:函数的『入参』和『出参』的混用会导致`API`接口语义的混乱,所以,使用指针,在调用的时候,实参需要加上“&”,这样在代码阅读的时候,可以看到是一个『出参』,有利于代码阅读。(但是这样做,在函数内就需要判断指针是否为空的情况,因为引用是不需要判断的,所以,这是一种 trade-off)
|
||||
>
|
||||
> 另外,如果这样的参数过多的话,最好使用一个结构体来把数据打包,一方面,为一组返回值取个名字,另一方面,这样有利用接口的简单。
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ void setAlarm(const QSharedPointer<Alarm> &alarm);
|
||||
// are good examples of other classes you should pass by value.
|
||||
```
|
||||
|
||||
>【译注】:这是传引用和传值的差别了,因为传值会有对像拷贝,传引用则不会。所以,如果对像的构造比较重的话(换句话说,就是对像里的成员变量需要的内存比较大),这就会影响很多性能。所以,为了提高性能,最好是传引用。但是如果传入引用的话,会导致这个对象可能会被改变。所以传入`const reference`。
|
||||
>【译注】:这是传引用和传值的差别了,因为传值会有对像拷贝,传引用则不会。所以,如果对像的构造比较重的话(换句话说,就是对像里的成员变量需要的内存比较大),这就会影响很多性能。所以,为了提高性能,最好是传引用。但是如果传入引用的话,会导致这个对象可能会被改变,所以传入`const reference`。
|
||||
|
||||
## 4.2 虚函数
|
||||
|
||||
@@ -288,7 +288,7 @@ virtual void setOverwriteMode( bool b ) { overWrite = b; }
|
||||
>【译注】:
|
||||
>
|
||||
> 1. 使用虚函数时,你需要对编译器的内部行为非常清楚,否则,你会在使用虚函数时,觉得有好些『古怪』的问题发生。比如在创建数组对象的时候。
|
||||
> 2. 在`C++`中,会有一个基础类,这个基础类中已经实现好了很多功能,然后把其中的一些函数放给子类去修改和实现。这种方法在父类和子类都是一组开发人员维护时没有什么问题,但是如果这是两组开发人员,这就会带来很多问题了,就像`Qt`这样,子类完全无法控制,全世界的开发人员想干什么就干什么。所以,子类的代码和父类的代码在兼容上就会出现很多很多问题。所以,还是上面所说,其实,虚函数应该声明在接口的语义里(这就是设计模式的两个宗旨——依赖于接口,而不是实现;钟爱于组合,而不是继承。也是为什么Java和Go语言使用`interface`关键字的原因,C++在多态的语义上非常容易滥用)
|
||||
> 2. 在`C++`中,会有一个基础类,这个基础类中已经实现好了很多功能,然后把其中的一些函数放给子类去修改和实现。这种方法在父类和子类都是一组开发人员维护时没有什么问题,但是如果这是两组开发人员,这就会带来很多问题了,就像`Qt`这样,子类完全无法控制,全世界的开发人员想干什么就干什么。所以,子类的代码和父类的代码在兼容上就会出现很多很多问题。所以,还是上面所说,其实,虚函数应该声明在接口的语义里(这就是设计模式的两个宗旨——依赖于接口,而不是实现;钟爱于组合,而不是继承。也是为什么`Java`和`Go`语言使用`interface`关键字的原因,`C++`在多态的语义上非常容易滥用)
|
||||
|
||||
### 4.2.2 虚函数 vs. 拷贝
|
||||
|
||||
@@ -312,7 +312,7 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
如果继承`CopyClass`这个类,预料之外的事就已经在代码时酝酿了。一般情况下,如果没有虚成员函数和虚析构函数,就不能创建出可以多态的子类。然而,如果存在虚成员函数和虚析构函数,这突然变成了要有子类去继承的理由,而且开始变得复杂了。**_起初认为只要简单声明上虚操作符重载函数(`virtual operators`)。_** 但其实是走上了一条混乱和毁灭之路(破坏了代码的可读性)。看看下面的这个例子:
|
||||
如果继承`CopyClass`这个类,预料之外的事就已经在编码时酝酿了。一般情况下,如果没有虚成员函数和虚析构函数,就不能创建出可以多态的子类。然而,如果存在虚成员函数和虚析构函数,这突然变成了要有子类去继承的理由,而且开始变得复杂了。**_起初认为只要简单声明上虚操作符重载函数(`virtual operators`)。_** 但其实是走上了一条混乱和毁灭之路(破坏了代码的可读性)。看看下面的这个例子:
|
||||
|
||||
```cpp
|
||||
class OtherClass {
|
||||
@@ -370,7 +370,7 @@ QPointF mapFromItem (const QGraphicsItem *item, const QPointF &point) const;
|
||||
|
||||
非类(`non-class`)的右值总是无`cv`限定类型(`cv-unqualified type`)。虽然从语法上讲,加上`const`也可以,但是没什么意义,因为鉴于访问权限这些值是不能改变的。多数现代编译器在编译这样的代码时会提示警告信息。
|
||||
|
||||
> 【译注】:`cv-qualified`的类型(与`cv-unqualified`相反)是由`const`或者`volatile`或者`volatile const`限定的类型。详见[cv (const and volatile) type qualifiers - `C++`语言参考](http://en.cppreference.com/w/cpp/language/cv)
|
||||
> 【译注】:`cv-qualified`的类型(与`cv-unqualified`相反)是由`const`或者`volatile`或者`volatile const`限定的类型;详见[cv (const and volatile) type qualifiers - `C++`语言参考](http://en.cppreference.com/w/cpp/language/cv)。
|
||||
|
||||
当在类类型(`class type`)右值上添加`const`关键字,则禁止访问非`const`成员函数以及对成员的直接操作。
|
||||
|
||||
@@ -450,14 +450,14 @@ foreach (const QGraphicsItem *item, scene.items()) {
|
||||
|
||||
若返回的是对象的拷贝,那么返回`const`引用是更直接的方案;
|
||||
然而,这样的做法限制了后面想要对这个类的重构(`refactor`)。
|
||||
(以`d-point`的典型做法(`idiom`)为例,我们可以在任何时候改变`Qt`类在内存表示(`memory representation`);但却不能在不破坏二进制兼容性的情况下把改变函数的签名,返回值从`const QFoo &`变为`QFoo`。)
|
||||
(以`d-point`的惯用法(`idiom`)为例,我们可以在任何时候改变`Qt`类在内存表示(`memory representation`);但却不能在不破坏二进制兼容性的情况下把改变函数的签名,返回值从`const QFoo &`变为`QFoo`。)
|
||||
基于这个原因,除去对运行速度敏感(`speed is critical`)而重构不是问题的个别情形(例如,`QList::at()`),我们一般返回`QFoo`而不是`const QFoo &`。
|
||||
|
||||
> 【译注】:参看《Effective C++》中条款23:Don't try to return a reference when you must return an object
|
||||
|
||||
### 4.4.5 `const` vs. 对象的状态
|
||||
|
||||
`const`正确性(`Const correctness`)的问题就像`C`圈子中`vi`与`emacs`的讨论,因为这个话题在很多地方都存在分歧(比如基于指针的函数)。
|
||||
`const`正确性(`const correctness`)的问题就像`C`圈子中`vi`与`emacs`的讨论,因为这个话题在很多地方都存在分歧(比如基于指针的函数)。
|
||||
|
||||
但通用准则是`const`函数不能改变类的可见状态。『状态』的意思是『自身以及涉及的职责』。这并不是指非`const`函数能够改变自身的私有成员,也不是指`const`函数改变不了。而是指函数是活跃的并存在可见的副作用(`visible side effects`)。`const`函数一般没有任何可见的副作用,比如:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user