断断续续花了很久才把这本书读完,内容比较杂,也不是特别深入,应该是从日常的文章汇总而成,有些内容还是值得一读。而且可以看出作者并没有仔细的整理这些内容,关于对象和块的章节重复和累赘部分很多,关于 Schewarzian Transform 也讲了很多次。
1 我为什么开发 Ruby
- 语言可以影响说话者的思想;
- 一个程序员不管他使用什么编程语言,他在一定时间里编写的程序行数是一定的。
2 面向对象
- 引入有限制的多重继承应该是一个好方法。
- 与继承有关的内容。
用语 | 内容 |
---|---|
单一继承 | 只有一个父类,单纯但存在几个问题 |
多重继承 | 多个父类,但引入了单一继承没有的新问题 |
静态语言(Java) | 区分规格继承和实现继承 |
动态语言 | 只有实现继承 |
规格多重继承的问题 | Java 的接口可以解决 |
实现多重继承的问题 | Mix-in 可以解决 |
Mix-in | 所有支持多重继承的语言都可以考虑使用 |
Ruby 的 Mix-in | 强制使用模块,来解决多重继承的问题 |
- 静态语言中可以实现多态性的只是限于拥有共通父类的对象。
- 数据要记录与自己数据类型有关的信息。这样的数据类型称为动态类型。
- 静态类型,直接执行,速度快。
- 动态类型,边解释源代码边执行速度慢。优点,灵活性。
3 程序块
- C 语言是通过函数指针来把函数作为一种对象来处理的。
- 在块中可以引用外部局部变量的方法,说明块不知是简单的程序代码,而且把外部“环境”也包括了进来,想这样的块称为闭包。
- 在被调用的方法中有两种方式来使用传递来的块。一种是用“块参数”的方式明确声明接受块作为参数,另一种是使用yield这个Ruby的保留词。
def each(&block)
i = 0
while i < self.size
block.call(self[i])
i+=1
end
end
def each()
i=0
while i < self.size
yield self[i]
i+=1
end
end
块作为参数的优点:
- 明确表示了块处理;
- 块和对象一样被统一处理了;
- 检查参数是否为 nil 就可以判断是否传递了块参数。
yield 的优点:
- 没有用到闭包,执行速度稍快;
- 错误信息比较用一理解。
- sort_by 用执行的代码块生成的结果拍续,对每个元素只执行一次块的调用。与其说是比较两个元素,更多的时候是对每个元素进行某种处理,用处理的结果来排序。(原来如此)。
- 用块来保证程序的后处理。
3.2.5 Enumerable 的局限(赞)
Enumerable 的两个主要缺点:
- 循环都依赖 each 方法,而且不能并行执行;
- 从多个对象取出元素进行处理比较难写。
用 Ruby 来定义 zip 方法的话,到目前为止,因为没有提供外部迭代器,所以只能在内部把参数变换成数组来对应。把参数作成数组,有以下两个问题:
- 大量的数据变换成数组会造成资源的浪费;
- 不能处理无限循环的 Enumerable。
代码部分:
module Enumerable
def zip(*args)
n = 0
args = args.map{|a| a.to_a }
self.each do |x|
yield [x, *args.map{|a| a[n] }]
n += 1
end
end
end
可以修改为:
module Enumerable
def zip(*args)
args = args.map{|a| a.enum_for(:each) }
self.each do |x|
yield [x, *args.map{|a|
a.next rescue nil
}]
end
end
end
- 不要变换成数组,而是用 enum_for 方法变换成以 each 为基础的 Enumerator。如果是 Ruby 1.8.7 ,这部分可以通过调用块的 each 方法来实现,但是如果这个类没有 each 方法,可能不返回 Enumerator。所以用 enum_for 方法才是安全的。
- 如果参数用数组可能会消耗很大内存。
4 设计模式
- 设计模式的本质,并不是介绍至今没有用过的新模式,而是通过给屡屡使用过的模式起一个合适的名字,从而提供了设计时的词汇。
- 旧约全书里记载了巴比伦塔的故事,描写了人与人之间因为语言不通,而中止了塔的建设,人们纷纷散去的场面。语言的重要性可见一斑。(沟通的重要性)。
5 Ajax (建议粗读,内容有点老,而且也比较浅)
6 Ruby on Rails
6.2.3 猴子补丁技巧
** undef **
undef 有把方法定义取消的功能。用 undef 不仅可以取消本类中的方法,也可以取消父类中的方法。
** remove_method **
remove_method 仅取消本类中的方法。
alias
用 undef 或 remove_method 删除了以前方法后,别名的方法依然可以使用。别以 alias 只是起别名,而是重新定义了一个方法。
7 文字编码(不感兴趣可以跳过)
文字编码的难度还是很大的。
正则表达式(赞)(要比Ruby镐头书和元编程介绍的详细)
锚点 | 匹配位置 |
---|---|
^ | 行首 |
$ | 行尾(若含换行,则是其前面的字符) |
\A | 字符串头 |
\Z | 字符串尾(若含换行,匹配前一字符) |
\z | 字符串尾 |
\b | 词头或词尾([] 外) |
(?=) | 用模式指定位置 |
(?!) | 用否定模式制定位置 |
*贪婪与懒惰 **
这是一个经常讨论的问题,记得加 .
分组
使用向后引用的时候,因为要在内部保存数据,效率会受影响。如果仅仅为了分组,而不需要使用向后引用,可以使用没有向后饮用的模式括号(?:)。
锚点
锚点 | 匹配位置 |
---|---|
^ | 行首 |
$ | 行尾(若含换行,则是其前面的字符) |
\A | 字符串头 |
\Z | 字符串尾(若含换行,匹配前一字符) |
\z | 字符串尾 |
\b | 词头或词尾([] 外) |
(?=) | 用模式指定位置 |
(?!) | 用否定模式制定位置 |
选项 | 含义 |
---|---|
i | 不区分大小写 |
m | 复数行匹配 |
o | 只展开一次 |
x | 无视正则表达式的空格,注释有效 |
选项
选项 | 含义 |
---|---|
i | 不区分大小写 |
m | 复数行匹配 |
o | 只展开一次 |
x | 无视正则表达式的空格,注释有效 |
注释
/\d{4}-? #year
\d{1,2}-? #month
\d{1,2} #day
/x
8.1.7 特殊变量
$& 最后匹配字符串
8.1.9 split 的本质
- 用固定字符串分割字符串
- 用正则来分隔
- 如果不想去掉标签,而是将其保存下来,可以用括号将模式包起来。
str = "<ul><li>a</li>b</ul>"
str.split(/(<.*?>)/)
# ["", "<ul>", "", "<li>", "a", "</li>", "b", "</ul>"]
8.1.10 字符串扫描
"afdasfasdfads".scan(/fa./){|s| p s }
下面代码执行同样的动作。它不生成无用的数组,效率稍高一点。(谁能告诉我为什么?)
"afdasfasdfads".scan(/fa./).each{|s| p s }
8.1.11 置换
置换字符串
a = 'abbbcd'
a.gsub(/a(b+)/, "#{$1}") #wrong
a.gsub(/a(b+)/, "\1") #wrong
a.gsub(/a(b+)/, "\\1") #right
a.gsub(/a(b+)/, '\1') #right
a.gsub(/a(b+)/, '\\1') #right
a.gsub(/a(b+)/){ $1 } #right
居然'\1'和'\1'都可以!
网友评论