Ruby系列学习资料(四)

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 则只是那个上下文环境内的局部变量。

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值