Oh!Coder

Coding Life

读《Ruby编程语言》笔记(一)

| Comments

这两天在重新读《Ruby编程语言》。虽说之前也看过一遍,但很多语法细节已经没有太多印象。为了重新巩固一下语法知识,这次想重新读一遍,顺便摘录一些不熟悉的语法点,算是作为笔记,同时也为了便于平时翻阅。

本次笔记顺序摘录了书中的前三章,共有二十条,并标出了每条笔记在书中的页码。

一、 Ruby对于这种空白符依赖性问题的解决办法很直接(P.33)

  • 永远不要在方法名和其后的左圆括号之间留白。
  • 如果一个方法的第一个参数以圆括号开头,那么在此方法的调用中,请一直使用圆括号,比如f((3+2)+1);
  • 请一直使用Ruby解释器的-w选项,这样它就会在你忘记了上述规则时发出警告。

#### 二、Ruby的除法操作(P.44)

  • 比如,-7/3的商,可以用浮点数表示为-2.33。但是,由于整数除法的结果必须为整数,所以必须对结果进行圆整。Ruby采取的是向负无穷大圆整,得到的结果为-3,但C及其相关语言的做法是向0取整而得到-2

三、Ruby的取模操作(P.45)

  • 在Ruby中,-7%3的结果是2,但在C和Java中的结果却是-1。由于两种操作的商不同,所以其结果的量当然也不同。此外,两个结果的符号也不同。在Ruby中,结果的符号始终和第二个操作数的符号保持一致。在C和Java里,结果的符号始终和第一个操作数的符号保持一致(P.45)。

四、Ruby的指数操作(P.45)

  • 指数不必是整数。例如:
    x\*\*4 # This is the same thing as x*x*x*x
    x\*\*-1 # The same thing as 1/x
    x\*\*(1/3.0) #The cube root of x
    x\*\*(1/4) # Integer division means this is x**0, which is always 1
    x\*\*(1.0/4.0) #This is the fourth-root of x
    当表达式含有多个指数操作时,它们按照从右向左的顺序被执行,因此,4\*\*3\*\*3的值与4\*\*9相同,而不同于64\*\*2

五、单引号(P.47)

  • 在一个单引号引用的字符串里,如果一个反斜线后面的字符不是单引号,也不是反斜线,那么该反斜线就没有任何特殊作用,因此,大多数情况下,在字符串字面量里不需要成对地出现反斜线(尽管它们可以成对出现)。

六、%q%Q(P.51)

  • %q开头的字符串字面量将遵循单引号引用字符串的规则,而以%Q(或%)开头的字符串字面量将遵循双引号引用字符串的规则。

七、Here document(P.51)

  • Here document以<<<<-开头,后面紧跟(为了避免与左移位操作符<<相混淆,不允许有空格)一个用于指定结尾分界符的标识符或字符串,从下一行开始直至该分界符单独出现在一行为止,期间的文本都被作为该字符串字面量的内容。Here document的结尾分界符必须单独出现在一行上,该分界符的后面甚至不能接注释。

八、Ruby字符串转换(P.55)

  • Ruby里的+操作符不会将其右侧操作数自动转换成字符串,你必须亲自手动:"Hello planet #" + planet_number.to_s # to_s converts to a string
  • 在Ruby中,采用字符串内插通常要比采用+操作符进行字符串链接更简单一些,在字符串内插时,对to_s的调用是自动进行的:"Hello planet ##{planet_number}"
  • +类似,<<操作符也不会对右侧操作数做任何的类型转换,但是,如果右侧操作数是一个整数,那么它将被作为一个字符编码来处理,对应的字符将被添加到左侧操作数上。
  • 如果左侧的操作数是一个字符串字面量,那么任何内插操作都只会在重复操作之前被执行一次,这意味着下面这段弄巧成拙的代码不会按照所期望的那样运行: a = 0; "#{a=a+1} " \* 3 # Returns "1 1 1", not "1 2 3"

九、字符串索引(P.56)

  • 如果从字符串的末尾开始计算索引,那么数组索引就是负值,而且从-1开始,自右向左依次减小。还有一点值得注意的是,如果你试图访问一个超出了字符串末尾的字符,Ruby并不会抛出异常,只是简单地返回nil

十、编码兼容(P.61)

  • 将一个UTF-8字符串和一个SJIS字符串进行链接是不可能的:编码方式不兼容,而且会抛出一个异常。你可以使用类方法Encoding.compatible?来测试两个字符串(或一个字符串和一个正则表达式)的编码是否兼容。如果两个实参的编码方式是兼容的,该方法就会返回两种编码方式的超集,否则返回nil

十一、可变的数组(P.64)

  • Ruby的数组是无类型且可变的,数组里的元素不必都属于同一个类型,而且它们可以随时改变。
  • 数组的大小也是可以动态改变的,你可以向数组添加元素,数组会按需增长。如果你向一个超出数组末尾的元素进行赋值,数组将会动态增长,而且用nil来填充那些多出来的位置。(但是,向超出数组开头的元素进行赋值是错误的)。

十二、数组的%w%W(P.65)

  • 如同%q%Q会引入一个String字面量一样,%w%W会引入一个数组字面量。针对%w%W的分界符规则与%q%Q的相同。在分界符所包含的内容里,无须使用引号来引用数组元素字符串,而且元素之间不需要使用逗号来分隔,数组元素之间采用空白来分隔。

十三、使用可变对象作为哈希健会带来一些问题(P.68)

  • 改变一个对象的内容通常会改变其哈希码。如果你使用一个对象作为健,然后又改变了该对象,那么内部的哈希表将被破坏,而且该哈希的行为也将不再正确。
  • 由于字符串是可变的,但是常常用作哈希健,所以Ruby将它们作为特例进行处理。对所有那些作为健的字符串,Ruby会为其生成私有拷贝。然而,这是唯一的特例。

十四、===操作符(P.78)

  • Object类定义了一个默认的===操作符,它会调用==操作符,因此,对于许多类来说,条件相等性和==相等性是一样的。但是某些关键的类重新定义了===,使其不仅仅是一个成员关系或匹配操作符:Range类定义了===,用于测试一个值是否位于某个范围内;Regexp类定义了===,用于测试一个字符串是否与某个正则表达式相匹配;Class类定义了===,用于测试一个对象是否是该类的一个实例;在Ruby 1.9中,Symbol类定义了===,使其右侧操作数和左侧操作数是同一个符号对象时,或者当其右侧操作数是一个持有和左侧符号对象相同文本的字符串时,该操作符返回true。

十五、<=>操作符(P.79)

  • 如果<=>操作符返回nil,那么所有基于它的操作符都将返回false。NaN这个特殊的Float值可以作为它的一个例子:

  • nan = 0.0/0.0; # is not-a-number.The value is NaN
  • nan == nan # false
  • nan.equal?(nan) # true

十六、显示类型转换(P.80)

  • 最为常见的是to_s、to_i、to_f及to_a方法,它们分别将调用对象转传成String、Integer、Float及Array。

十七、隐式类型转换(P.81)

  • 在Ruby 1.9里,内建的String、Array、Hash、Regexp及IO类都定义了一个名为try_convert的类方法。如果这些方法的实参定义了一个合适的隐式转换方法,那么它们就对其进行转换,否则返回nil。如果对象o定义了to_ary方法,那么Array.try_convert(o)将返回o.to_ary;否则,它会返回nil。

十八、布尔类型(P.82)

  • 在布尔表达式里,任何不同于false或nil的值都表现得像true一样(但不是转换成true),nil则表现得像false一样。

十九、拷贝对象(P.83)

  • Object类定义了两个密切相关得方法,用于拷贝对象。clone和dup方法都返回一个调用它们得对象的浅拷贝,如果被拷贝的对象含有指向其他对象的引用,那么只有这些引用被拷贝,而那些被引用的对象本身却不会被拷贝。
  • 如果被拷贝的对象定义了一个initialize_copy方法,那么clone和dup方法就会简单地分配一个新的空实例(该实例所属的类与被拷贝对象的相同),然后在其上调用initialize_copy方法。
  • Object类定义的clone和dup方法存在两处重要的差别。首先,clone方法会拷贝一个对象的被冻结(frozen)和受污染(tainted)状态,而dup方法仅仅拷贝受污染状态,在一个被冻结的对象上调用dup方法将返回一个未被冻结的副本。其次,clone方法会拷贝对象的所有单键方法,而dup则不会。

二十、污染对象(P.84)

  • Ruby可以通过调用其taint方法将任何对象标记成受污染的(tainted)。一个受污染的对象可以通过untaint方法成为未受污染的(untainted)。

Comments