您的位置:首页 > 编程语言 > Ruby

Ruby系列学习资料(四)

2008-01-25 16:59 211 查看

Ruby系列学习资料(四)

6、Syntax Issues
Ruby的解析器是非常复杂和相对宽松的。它试图理解它看到的东西,而不是强迫程序奴隶般地遵循一套规则。然而,这种行为可能采用了一些习惯。这儿列出了你应该知道的Ruby语法:

l
用于方法调用的圆括号是可选的。这些调用都是有效的:
foobar
foobar()
foobar(a,b,c)
foobar a, b, c
l
假设圆括号是可选的,x y z意味着什么,是什么?像它的结果,这意味着, "调用方法 y ,传递z做为参数,然后传递结果做为方法x的参数"。简单说,它与x(y(z))语句的意思一样。
l
让我们试着传递个哈希表给方法: my_method {a=>1, b=>2}
这是个语法错误,因为左花括号被认为是个块的开始,在这种情况下,圆括号是必须的:my_method({a=>1, b=>2})
l
现在让我们假设哈希表是传递给方法的唯一参数。Ruby非常宽松地允许我们省略花括号: my_method(a=>1, b=>2)
有些人可能认为这看起来像是带有命名参数的方法调用,但是它强调不是这样。
l
现在考虑这个方法调用:
foobar.345看它,有人可能认为foobar是个对象而345是个被调用的方法,但明显地方法的名字是不能以数字开头的!解析器解释它是对方法foobar的调用,传递数字0.345做为一个参数。这儿,你看到的是圆括号或中间的空格都被忽略了的结果。不用说,事实上你可以用这种方式编码,但这只是你可的暗示。
l
有些情况下空白也很重要。例如,这些表达式的意思似乎是一样的:
x = y + z
x = y+z
x = y+ z
x = y +z


事实上第一到第三个是一样的。然而,在第四种情况中,解析器认为y是个方法调用,+z是个传递给它的参数!然后,如果没有名字为y的方法,它将对这一行给出个错误信息。The moral is to use blank spaces in a reasonable way.
l
类似地,x = y*z 是y和z的乘法,然而x = y
*z 是方法y的调用,传递一个数组z的扩展做为参数。
l
在构造标识符时,下划线被认为是小写字母。所以,标识符可以用下划线开头,但它不能是常量即使下一个字母是大写。
l
线性的,如果语句被嵌套,使用关键字elsif而不像其它语言使用else
if 或elif 。
l
Ruby内的关键字不是真正的"被保留单词"。在很多情况中,一个关键字可被用于做为一个标识符同时解释器也不会弄混。我们不会说在什么条件下可以或不可以这样做。我们说这些只是认为如果你真的需要的话是可以这做的,警告是这会带来混乱。通常,使用关键字做一个标识符应该小心,应该在你的思想中保持可读性。
l
当然关键字是可选的(在if和case语句中)。为了可读性当然也可以使用它。对while和until循环来说也是一样的。
l
问号和感叹号不是真正的它们可以修改的标识符的一部分,它们应该被认为是后缀。所以,例如尽管chop和chop!被认为是不同的标识符,这些字符不允许在其它的地方使用。同样,我们在Ruby内使用defined?,但defined是关键字。
l
在一个字符串内部,英磅符号(#)被用于表示被计算的表达式。这意味着在很多情况下,当英磅符号出现在一个字符串内时,它必须用反斜线表示法来转义,但是这只在下一个字符是左花括号 ({), 美元符号 ($), 或"at"符号(@)时。
l
三元操作符 (?

,它起源于C语言,在Ruby中有时也称为"未文档化的"。基于这个理由,程序员可以不愿意使用它 (尽管我们并不回避它)。
l
由于事实上问号可以被附加给标识符,所以应该小心要在三元操作符上加上空格。例如,假设我们有变量my_flag,它即保存true也可保存false。然而第一行代码是正确的,而第二行代码将产生语法错误:
x = my_flag ? 23 : 45
# OK
x = my_flag? 23 : 45
# 语法错误


l
The ending marke用于植入文档的标记 =end不应该被当成一个记号。它标记完整行;所以,行内的其它字符不会被认为是程序的一部分,但是它们属于被植入的文档。
l
Ruby内的块不是任意的,也就是说,你不能像C那样凭感觉来开始一个块。块只允许出现在需要它们的地方(例如,附加给迭代器)。这也是为什么Ruby内的post-test循环使用一个begin-end对的原因,即使不进行异常处理。
l
记住关键字BEGIN 和END与begin 和 end 关键字是完全不同的。
l
When strings bump together (static concatenation), the concatenation is of a higher precedence than a method call. Here's an example:
# These three all give the same result.
str1 = "First " 'second'.center(20)
str2 = ("First " + 'second').center(20)
str3 = "First second".center(20)
Precedence is different.
l
Ruby有几个伪变量,像起来像局部变量但它们用于特殊目的。它们是self, nil, true, false, __FILE__, 和 __LINE__.

7、Perspectives in Programming
大概每个人都知道Ruby在过去曾是个学生或其它语言的用户。这个经历使用学习Ruby变得较为容易,Ruby内的许多特性与其它语言内相应特性相似。换句话说,程序员可能被Ruby内这熟悉的结构带入到一种虚假的安全感觉中,它们会用以前的经验来使用这些结构。
大多数人认为Ruby来自于Smalltalk, Perl, C/C++, 和其它语言。Their presuppositions and expectations may all vary somewhat, but they will always be present. For this reason, here are a few of the things that some programmers may "trip over" in using Ruby:
l
实际上Ruby内的字符是个整数。它没有自己的类型,也不会被认为是长度为1的字符串。考虑下面代码片断:
x = "Hello"
y = ?A
print "x[0] = #{ x[0]} n"
# Prints: x[0] = 72
print "y = #yn"
# Prints: y = 65
if y == "A"
# Prints: no

print "yesn"
else

print "non"
end
l
和其它很多语言一样没有Boolean类型。TrueClass 和FalseClass是截然不同的类,它们的实例化是ture和false。
Ruby的很多操作符类似或等同于C中的。有两个值 得注意的例外是增量减量操作符 (++ 和 --)。它们在Ruby中是无效。
l
模数操作符在对待负数上不同的语言有些差别。这种观点的讨论都超出了本书的范围;但可以说Ruby有下面这样的行为:
print
5 % 3

# Prints 2
print
-5 % 3

# Prints 1
print
5 % -3

# Prints -1
print
-5 % -3

# Prints 2
l
有些人习惯地认为false值可以用0,空字符串,空字符,或其它东西。但是在Ruby中,所有东西都是true;事实上除了false和nil每个东西都是true。
l
Ruby总是反复强调:变量没有类型;只有值才有类型。
l
说变量未被定义(例如,变量没有声明)本质与说它是nil是一样的。这样的值会通过与nil的等同性测试并且如何在一个条件中单独使用它将计算出false。这个原则在哈希表中是个例外,因它存储在哈希表中的nil是有效值,与nil比较以在哈希表中找是否存在值是不适当的。(通过方法调用手段,有几个正确的方式可以完成这个比较。)
l
记住post-test循环在Ruby内可以通过跟随在while或until的修饰符形式后面的一个begin-end结构来模仿。
l
记住Ruby内没有变量声明。然而,给变量nil初始值是个好习惯。这的确没有赋给变量类型并且也没有真正地初始化它,但它通知解析器这是个变量的名字而不是一个方法的名字。Ruby解释一个标识符为一个方法名字,除非它看到早先赋值个名字的引用给变量。
l
记住 ARGV[0] 是命令行的第一个参数,编号自然从零开始;前面提到的参数不是文件或脚本的名字,如C中的argv[0] 。
l
大多数Ruby的操作符是真正的方法;这些方法的点形式提供了熟悉和便利。第一个例外是一套反身赋值操作符(+=, -=, *=, 等等);第二个例外是下面这些:
=
..
...
!
not
&&
and
||
or
!=
!~
l
像大多数(尽管不是全部)现代语言,Boolean操作总是短路;即,Boolean表达式的计算在它是true值时停止。在or操作符序列内,第一个true将停止求值;在有and操作符的字符串内,第一个false将停止求值。
l
记住前缀@@用于类变量(它与类关联而不是实例)。
l
记住loop不是关键字;它是一个Kernel方法,不是一个控制结构。
l
有些人会发觉unless-else句法有点违反直觉。因为unless是if的反面,如果条件为false则else子句会被执行。
l
通常传递给方法的参数其实是一个对象的引用;同样,参数有从方法内部被修改的潜在可能。
l
简单的Fixnum类型被做为直接值传递,所以它不可能在方法内部被修改。true,false和nil也是一样。
l
不要混淆&& 和 || 操作符与& 和 | 操作符。它们的用法与C语言类似;前者用于Boolean操作,后者用于算术或位操作。
l
这儿是在&&-||操作符以及and-or操作符之间的区别。前者用于更普通的用途,在一个表达内的结果不是true或false。后则的结果则总是true或false;它们被明确地用于条件内连接Boolean表达式 (所以如果一个表达式不能计算出true或false时会有语法错误)。看下面代码片断:
print (false || "string1n")
# Prints string1
# print (false or "string2n")
#
Syntax error!
print (true && "string3n")
# Prints string3
# print (true and "string4n")

#
Syntax error!
print (true || "string5n")
# Prints true
# print (true or "string6n")
#
Syntax error!
print (false && "string5n")
# Prints false
# print (false or "string6n")
#
Syntax error!
l
and-or 操作符比&&-|| 操作符有较小优先级。看下面代码片断:
a = true
b = false
c = true
d = true
a1 = a && b or c && d
# &&'s are done first
a2 = a && (b or c) && d
# or is done first
print a1
# Prints false
print a2
# Prints true
l
另外,要小心赋值操作符有比and或or操作符高的优先级!(反身赋值操作符+=,-=和其它也是一样的。)例如,下面代码的第三行看起来像个普通的赋值语句,但它其实是个free-standing表达式 (事实上,等同于第五行。)。第七行是个真正的赋值语句,它才是程序员真正想要做的:
y = false
z = true
x = y or z
# Line 3: = is done BEFORE or!
print x, "n"
# Prints false
(x = y) or z
# Line 5: Same as line 3
print x, "n"
# Prints false
x = (y or z)
# Line 7: or is done first
print x, "n"
# Prints true


l
不要混淆对象属性和局部变量。如果你习惯于C++或Java,你可能忘记这一点。变量@my_var是你写的类的上下文环境内的实例变量(或属性),但是同样环境下的my_var则只是那个上下文环境内的局部变量。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: