首页 > 代码库 > 《ruby编程语言》笔记 1
《ruby编程语言》笔记 1
赋值:
ruby支持并行赋值,即允许在赋值表达式中出现多余一个值和多于一个的变量:
x,y=1,2
a,b=b,a
x,y,z=[1,2,3]
(python同样可以正常上面的语句)。
Methods in Ruby are allowed to return more than one value, and parallel assignment
is helpful in conjunction with such methods. For example:
# Define a method to convert Cartesian (x,y) coordinates to Polar
def polar(x,y)
theta = Math.atan2(y,x) # Compute the angle
r = Math.hypot(x,y) # Compute the distance
[r, theta] # The last expression is the return value
end
# Here‘s how we use this method with parallel assignment
distance, angle = polar(2,2)
以等于号=结尾的方法比较特殊,
Methods that end with an equals sign (=) are special because Ruby allows them to be
invoked using assignment syntax. If an object o has a method named x=, then the
following two lines of code do the very same thing:
o.x=(1) # Normal method invocation syntax
o.x = 1 # Method invocation through assignment
1.1.6 Punctuation Suffixes and Prefixes
We saw previously that methods whose names end with = can be invoked by assignment
expressions. Ruby methods can also end with a question mark or an exclamation point.
A question mark is used to mark predicates—methods that return a Boolean value. For
example, the Array and Hash classes both define methods named empty? that test
whether the data structure has any elements. An exclamation mark at the end of a
method name is used to indicate that caution is required with the use of the method.
A number of core Ruby classes define pairs of methods with the same name, except
that one ends with an exclamation mark and one does not. Usually, the method without
the exclamation mark returns a modified copy of the object it is invoked on, and the
one with the exclamation mark is a mutator method that alters the object in place. The
Array class, for example, defines methods sort and sort!.
In addition to these punctuation characters at the end of method names, you’ll notice
punctuation characters at the start of Ruby variable names: global variables are prefixed
with $, instance variables are prefixed with @, and class variables are prefixed with @@.
These prefixes can take a little getting used to, but after a while you may come to
appreciate the fact that the prefix tells you the scope of the variable. The prefixes are
required in order to disambiguate Ruby’s very flexible grammar. One way to think of
variable prefixes is that they are one price we pay for being able to omit parentheses
around method invocations.
Ruby的意外之处
每一门语言都会有那样的一些特性,他们使得接触该语言的人大伤脑筋,ruby也不例外,下面我们来描述两个令人吃惊的特性。
Ruby’s strings are mutable, which may be surprising to Java programmers in particular.
The []= operator allows you to alter the characters of a string or to insert, delete, and
replace substrings. The << operator allows you to append to a string, and the String
class defines various other methods that alter strings in place. Because strings are mutable,
string literals in a program are not unique objects. If you include a string literal
within a loop, it evaluates to a new object on each iteration of the loop. Call the
freeze method on a string (or on any object) to prevent any future modifications to
that object. 字符串是可变的。
Ruby’s conditionals and loops (such as if and while) evaluate conditional expressions
to determine which branch to evaluate or whether to continue looping. Conditional
expressions often evaluate to true or false, but this is not required. The value of nil is
treated the same as false, and any other value is the same as true. This is likely to
surprise C programmers who expect 0 to work like false, and JavaScript programmers
who expect the empty string "" to be the same as false.
nil和false为假,其他都是true。
使用ri查看文档
ri文档查看器是另一个重要的ruby工具,在命令行调用ri,后接一个Ruby类,模块或方法的名字,ri就会显示对应的文档。你也可以只指定一个方法名而不加类名或模块名作为限定,但是这样会显示一个包含了所有叫这个名字的方法的列表(除非这个方法是独一无二的)。通常情况下,你可以用句点将类或模块名与方法名进行分隔。如果一个类定义了同名的类方法和实例方法,那么你就要用::引用类方法,而用#引用实例方法,下面是例子:
ri Array
ri Array.sort
ri Hash#each
ri Math::sqrt
我在windows上使用ri总是提示:找不到主题
C:\Users\Administrator>ri Kernel.sprintf
Nothing known about Kernel
其实解决也很简单,如下即可
gem install rdoc-data# Regenerate system docsrdoc-data --install# Regenerate all gem docsgem rdoc --all --overwrite# Regenerate specific gem doc with specific versiongem rdoc gemname -v 1.2.3 --overwrite
参考:http://blog.csdn.net/mydo/article/details/8545964
问题,使用gem install半天没有反应,是因为被墙了,怎么办?使用国内镜像:
http://ruby.taobao.org/
参考http://www.iteye.com/problems/76704
This documentation displayed by ri is extracted from specially formatted comments in
Ruby source code. See §2.1.1.2 for details.
这些文档是从源代码提取出来的。
ruby中的注释以#开头并持续到该行结束,ruby解释器将忽略#字符及其后的任何文本(但是并不忽略换行符,因为换行符是一个有意义的空白符,也许会作为语句的终结符)。如果#字符串出现在一个字符串中,那么将作为一部分。
#this line is comment
通常情况下,通过在每一行前添加一个#字符表示多行注释
#
# thsi clas repremetn
# a complerx nuerm
#
嵌入式文档
ruby支持另外一种称为嵌入式文档(embeded docuemnt)的多行注释风格。这种注释以一个"=begin"开头,并以一个"=end"结尾。(=end所在的那一行也包括在内)。
=begin Someone needs to fix the broken code below!
Any code here is commented out
=end
Note that embedded documents only work if the = signs are the first characters of each
请注意,=必须作为该行的第一个字符才有效。
line:
# =begin This used to begin a comment. Now it is itself commented out!
The code that goes here is no longer commented out
# =end
As their name implies, embedded documents can be used to include long blocks of
documentation within a program, or to embed source code of another language (such
as HTML or SQL) within a Ruby program. Embedded documents are usually intended
to be used by some kind of postprocessing tool that is run over the Ruby source code,
and it is typical to follow =begin with an identifier that indicates which tool the
comment is intended for.嵌入式文档通常会被一些后期处理工具使用,在“=begin之后,通常跟着一个标识符来表明希望用哪个工具来处理该注释。
2.1.1.2 Documentation comments
Ruby programs can include embedded API documentation as specially formatted comments
that precede method, class, and module definitions. You can browse this
documentation using the ri tool described earlier in §1.2.4. The rdoc tool extracts documentation
comments from Ruby source and formats them as HTML or prepares them
for display by ri. Documentation of the rdoc tool is beyond the scope of this book; see
the file lib/rdoc/README in the Ruby source code for details.
Documentation comments must come immediately before the module, class, or
method whose API they document. They are usually written as multiline comments
where each line begins with #, but they can also be written as embedded documents
that start =begin rdoc. (The rdoc tool will not process these comments if you leave out
the “rdoc”.)
The following example comment demonstrates the most important formatting elements
of the markup grammar used in Ruby’s documentation comments; a detailed
description of the grammar is available in the README file mentioned previously:
## Rdoc comments use a simple markup grammar like those used in wikis.## Separate paragraphs with a blank line.## = Headings## Headings begin with an equals sign## == Sub-Headings# The line above produces a subheading.# === Sub-Sub-Heading# And so on.## = Examples## Indented lines are displayed verbatim in code font.# Be careful not to indent your headings and lists, though.## = Lists and Fonts## List items begin with * or -. Indicate fonts with punctuation or HTML:# * _italic_ or <i>multi-word italic</i># * *bold* or <b>multi-word bold</b># * +code+ or <tt>multi-word code</tt>## 1. Numbered lists begin with numbers.# 99. Any number will do; they don‘t have to be sequential.# 1. There is no way to do nested lists.## The terms of a description list are bracketed:# [item 1] This is a description of item 1# [item 2] This is a description of item 2#
literal字面量
字面量就是那些直接出现杂ruby源代码里面的值。字面量包括数字,文本字符串及正则表达式(其他字面量,比如数组和hash,是一些更为复杂的表达式,而非单个标记。)
1 #an integer literal
1.0 # a floating-point
‘onw‘
/three/
2.1.3 Punctuation 标点符号
Ruby uses punctuation characters for a number of purposes. Most Ruby operators are
written using punctuation characters, such as + for addition, * for multiplication, and
|| for the Boolean OR operation. See §4.6 for a complete list of Ruby operators. Punctuation
characters also serve to delimit string, regular expression, array, and hash
literals, and to group and separate expressions, method arguments, and array indexes.
We’ll see miscellaneous other uses of punctuation scattered throughout Ruby syntax.
标识符:
标识符不包含标点符号。
以从A到Z这26个大写字母开头的标识符是常量,如果你试图修改一个这样的标识符,ruby解释器会发出警告(但不是错误)。类和模块名必须以大写开头,否则会报错。
标识符里的标点符号
标点符号可以出现在ruby标识符的开始或结尾,他们具有如下含义:
$ Global variables are prefixed with a dollar sign. Following Perl’s example, Ruby defines a number of global variables that
include other punctuation characters, such as $_ and $-K. See Chapter 10 for a list of these special globals.
@ Instance variables are prefixed with a single at sign, and class variables are prefixed with two at signs. Instance variables
and class variables are explained in Chapter 7.
? As a helpful convention, methods that return Boolean values often have names that end with a question mark.
! Method names may end with an exclamation point to indicate that they should be used cautiously. This naming convention
is often to distinguish mutator methods that alter the object on which they are invoked from variants that return a modified
copy of the original object.
= Methods whose names end with an equals sign can be invoked by placing the method name, without the equals sign, on
the left side of an assignment operator. (You can read more about this in §4.5.3 and §7.1.5.)
Here are some example identifiers that contain leading or trailing punctuation
characters:
$files # A global variable
@data # An instance variable
@@counter # A class variable
empty? # A Boolean-valued method or predicate
sort! # An in-place alternative to the regular sort method
timeout= # A method invoked by assignment
空白符与方法调用
ruby的语法允许在特定环境下与方法调用相关的圆括号可以被省略,这使ruby的方法使用起来就好像他们是语句一样。这也是ruby优雅性的重要体现。然而,不幸的是,他也带来了另一个有危害的空白符依赖性。比较下面的两行代码,他们的差异仅仅在于一个空白符:
f(3+2)+1
f (3+2) +1
第一行代码将5传递给方法f,然后在结果上加1,。由于第二行代码在方法名之后出现了一个空白符,所以ruby就会假设方法调用的圆括号被省略了。在空白符之后出现的圆括号将括起子表达式3+2,而整个表达式(3+2)+1将被用作方法的参数。如果在执行代码时使用-w开启了警告,ruby将在他碰到二义性的代码时发出警告。
(F:/ruby/rubySource/hello.rb:11: warning: (...) interpreted as grouped expression)
对于这种空白符依赖性问题的解决办法很直接:
.永远 不要在方法名和其后的左圆括号之间留白
。如果一个方法的第一个参数以圆括号开头,那么在此方法的调用中,请一直使用圆括号,比如f((3+2)+1);
.请一直使用ruby解释器的-w选项,这样他就会在你忘记上述规则时发出了警告。
ruby中的block
代码块:{} do end
除了上面两种,除了避免与上述真正意义上的块发生混淆,我们称另一种为体(body)(然而在实际中,术语”块“常常用于指代这两种)所谓的体就是一个语句列表,该列表包括类定义体、方法定义体、while循环体等诸如此类的结果。ruby的体永远不会用花括号作为分界符,而是采用关键字。
体和块可以互相嵌套,而且典型的ruby程序都包含几层嵌套代码,他们之间通过相对缩进来保持可读性。如下:
module Stats #A module class Dataset #a class in the module def initialize(filename) # a method in the class IO.foreach(filename) do |line| if line[0,1]=="#" next end end end endend
文件结构
指定文件的编码(在这一点上,ruby遵循了python的惯例)
#coding:utf-8
字符串coding后必须接一个冒号或等号,然后再接期望的编码名称(该名称不能包含空格,也不能包含除了字符和下划线以外的标点符号)。在冒号或等号的两边允许有空白符存在,而且字符串coding可以包含任意的前缀,比如以en为前缀则拼写encoding。整个注释,包含coding字符串和编码名称,都不区分大小写,可以随意采用大小写。
文本编辑器可以通过编码注释来获取文件的编码方法,比如Emacs的用户可以向下面这样编写:
#-*- coding: utf-8
vi的用户可以向下面这样编写:
# vi: set fileencoding=utf-8 :
数字
An integer literal is simply a sequence of digits:
0
123
12345678901234567890
If the integer values fit within the range of the Fixnum class, the value is a Fixnum.
Otherwise, it is a Bignum, which supports integers of any size. Underscores may be
inserted into integer literals (though not at the beginning or end), and this feature is
sometimes used as a thousands separator: 千分符
1_000_000_000 # One billion (or 1,000 million in the UK)
If an integer literal begins with zero and has more than one digit, then it is interpreted
in some base other than base 10. Numbers beginning with 0x or 0X are hexadecimal
(base 16) and use the letters a through f (or A through F) as digits for 10 through 15.
Numbers beginning 0b or 0B are binary (base 2) and may only include digits 0 and 1.
Numbers beginning with 0 and no subsequent letter are octal (base 8) and should
consist of digits between 0 and 7. Examples:
以0x开头的为12进制,0b开头为二进制,0为8进制。
0377 # Octal representation of 255
011 #八进制9
0b1111_1111 # Binary representation of 255
0xFF # Hexadecimal representation of 255
To represent a negative number, simply begin an integer literal with a minus sign.
Literals may also begin with a plus sign, although this never changes the meaning of
the literal.
当一个整数结果太大而无法容纳一个Fixnum时,ruby会自动将其转化为一个bignum,这样做的结果是,ruby中的整数算术操作不会像其他语言中那样产生溢出。浮点数会上溢至两个特殊的值,即正无穷大或负无穷大,此外还会下溢至0.
除法操作符的行为是与操作数的类型有关的。如果两个操作数都是整个,那么进行的是截断性的整数除法(truncating-integer divsion)。如果任意一个数是Float,那么执行的是浮点数除法
x = 5/2 # result is 2
y = 5.0/2 # result is 2.5
z = 5/2.0 # result is 2.5
Integer division by zero causes a ZeroDivisionError to be thrown. Floating-point division
by zero does not cause an error; it simply returns the value Infinity. The case of
0.0/0.0 is special; on most modern hardware, and with most operating systems, , it
evaluates to another special floating-point value known as NaN, or Not-a-Number.
The modulo (%) operator computes remainder-after-integer division:
x = 5%2 # result is 1
The % operator can also be used with Float operands, although this is less common:
x = 1.5%0.4 # result is 0.3
Division, Modulo, and Negative Numbers
When one (but not both) of the operands is negative, Ruby performs the integer division
and modulo operations differently than languages like C, C++, and Java do (but the
same as the languages Python and Tcl). Consider the quotient -7/3. The floating-point
result is –2.33. The result of integer division must be an integer, however, so this number
must be rounded. Ruby rounds toward negative infinity and returns –3. C and related
languages round toward zero instead and return –2. (This is just one way to characterize
the results; no floating-point division is actually done, of course.)
ruby采取的是向负无穷大取整,-7/3结果得到是-3.C语言得到的-2。
An important corollary of Ruby’s definition of integer division is that, in Ruby, -a/b
equals a/-b but may not equal -(a/b).
Ruby’s definition of the modulo operation also differs from that of C and Java. In Ruby,
–7%3 is 2. In C and Java, the result is -1 instead. The magnitude of the result differs, of
course, because the value of the quotient differs. But the sign of the result differs, too.
In Ruby, the sign of the result is always the same as the sign of the second operand. In
C and Java, the sign of the result is always the same as the sign of the first operand.
(Ruby also provides a remainder method that behaves, in sign and magnitude, like the
C modulo operator.)
但在c和java中结果却为-1.由于两种操作的商不同,所以其结果的量也不同。此外,两个结果的符号也不同。在ruby中,结果的符号始终和第二个操作数的符号保持一致,在c和java中,结果的符号始终和第一个操作数保持一致。(ruby还定义了一个remainer方法,在结果的量和符号方面,他的行为都类似C的取模操作。
ruby从Fortran语言处借鉴了**操作符表示指数。
指数操作能导致非常大的值,请记住,整数可以变得任意大,但是float对象却不能表示大于Float::MAX的数,因此,表达式10**1000可以得到精确的整数结果,但是表达式9.9**1000却会溢出到Infinitiy这个float。
Fixnum和bignum支持标准的位操作符。~,&,|,^,>>,<<。这些操作符在C和java中很常见。此外,可以像索引数组那样对整数值的单个位进行索引,索引0将返回最低有效位。
(感觉这个太方便了。)
even = (x[0] == 0) # A number is even if the least-significant bit is 0
string literal字符串字面量
单引号:普通的字符串
双引号
支持\n,\t等。可以包含任意的ruby表达式,称为字符串内插。这样写:
#{2*Math::PI}
当要插入到字符串字面量中的表达式只是一个对于全局、实例或类变量的引用时,花括号可以被省略:
$var=‘hello‘
"#$var world"
当不希望#字符串被特殊处理的时候,你可以在前面加一个反斜线来进行转义。只有当#后妈是{,$或@字符时,才需要这样的转义:
"My phone #: 555-1234" #不需要转义
"Use \#{ to interpolate expressions" # Escape #{ with backslash
printf和sprintf
C programmers may be happy to know that Ruby also supports printf and sprintf*
functions for interpolating formatted values into strings:
sprintf("pi is about %.4f", Math::PI) # Returns "pi is about 3.1416"
The advantage of this style of interpolation is that the format string can specify options,
such as the number of decimal places to display in a Float. In true Ruby style, there is
even an operator form of the sprintf method: simply use a % operator between a format
string and the arguments to be interpolated into it:
"pi is about %.4f" % Math::PI # Same as example above
"%s: %f" % ["pi", Math::PI] # Array on righthand side for multiple args
感觉类似python。
3.2.1.5 Here documents here文档
For long string literals, there may be no single character delimiter that can be used
without worrying about remembering to escape characters within the literal. Ruby’s
solution to this problem is to allow you to specify an arbitrary sequence of characters
to serve as the delimiter for the string. This kind of literal is borrowed from Unix shell
syntax and is historically known as a here document. (Because the document is right
here in the source code rather than in an external file.)
Here documents begin with << or <<-. These are followed immediately (no space is
allowed, to prevent ambiguity with the left-shift operator) by an identifier or string that
specifies the ending delimiter. The text of the string literal begins on the next line and
continues until the text of the delimiter appears on a line by itself. For example:
document = <<HERE # This is how we begin a here document
This is a string literal.
It has two lines and abruptly ends...
HERE
3.2
反引号所引用的命令的执行
ruby支持另一种有关引号和字符串的说法。当使用反引号来引用文本时,该文本被作为一个由双引号引用的字符串字面量来处理。该文本的值将被传递给一个特殊的名为Kernel.`的方法,该方法将该文本的值作为一个系统的shell命令来执行,并将命令的输出作为字符串返回。
考虑下面的ruby代码:
`ls`
在一个unix系统上,这4个字符将产生一个字符串,该字符串所代表的命令列出当前目录下的文件名。当然这具有很强的平台依赖性,window下的`dir`和他是等价的。
字符串字面量的分界符
当一段文本里含有撇号和引号时,要将其作为单引号或双引号的字符串字面量来处理,就会显得比较棘手。ruby支持一种更一般化的语法来引用字符串(正如我们随后将要看到的,对于正则表达式和数组字面量也有这样的语法支持)。以%q开头的字符串字面量将遵循单引号引用字符串的规则,而已%Q(或%)开头的字符串字面量将遵循双引号的规则。紧跟在q或Q之后的第一个字符是该字符串的分界符从该分界符之后的第一个字符开始,直到下一个相匹配的(未被转义的)分界符之间的内容就组成了该字符串。如果起始分界符为(,[,{或<,那么与之相匹配的分界符就是),],}或>。否则结束分界符就是和起始分界符同样的字符。
%q(Don‘t worry about escaping ‘ characters!)
%Q|"How are you?", he said|
%-This string literal ends with a newline\n- # Q omitted in this one
ruby字符串是可变的,因此,ruby解释器无法用同一个对象来表达两个相同的字符串字面量。(如果你是一个java程序员,也许你觉得奇怪)。每当ruby遇见了一个字符串字面量时,都会创建一个对象,如果你在一个循环体内包含了一个字面量,那么ruby每次迭代的时候都会创建一个新的对象。可以运行下面的代码证明这点:
10.times{ puts "test".object_id }
为了获得 更好的运行效率,你应该避免在循环中使用字符串字面量。
3.2.1.8 The String.new method
In addition to all the string literal options described earlier, you can also create new
strings with the String.new method. With no arguments, this method returns a newly
created string with no characters. With a single string argument, it creates and returns
a new String object that represents the same text as the argument object.
在ruby程序中,你可以通过在字符前加一个?来表示单个字符构成的字面量,不需要使用任何形式的引号:
irb(main):057:0> ?A
=> "A"