字面量

一个字面量是任何符号,代表在源代码中的固定值。例如,以下所有内容都是 Ruby 中的字面量:

'Hello, world!'          # 字符串 字面量
375                      # 整型 字面量
3.141528                 # 浮点型 字面量
true                     # 布尔型 字面量
{ 'a' => 1, 'b' => 2 }   # 哈希 字面量
[ 1, 2, 3 ]              # 数组 字面量
:sym                     # 符号 字面量
nil                      # nil(空) 字面量

我们很快就会遇到这些字面量和其他字面量。

字符串

一个字符串是在一个特定的字符序列的列表。在编程中,我们经常需要处理诸如名称、消息和描述之类的文本数据。Ruby 使用字符串来表示此类数据。你可以在文本的两侧使用单引号 ( ‘hi there’) 或双引号 ( “hi there”) 编写字符串字面量;请注意,引号是句法的组成部分,而不是值的一部分。单引号和双引号格式都创建一个字符串。但是,存在一些细微的差异。

如果你想在字符串中包含单引号,那么你有两个选择。你可以使用双引号方法或单引号方法进行转义:

示例. 1: 双引号

“The man said, ‘Hi there!’”

示例. 2: 单引号 和 反斜杠

‘The man said, ‘Hi there!’’

反斜杠或转义 ( ) 字符告诉计算机它后面的引号不是 Ruby 语法,而只是要包含在字符串中的简单引号字符。

双引号允许字符串插值。尝试一下,请在 irb 会话中键入以下内容:

irb :001 > a = 'ten'
=> "ten"

irb :002 > "My favorite number is #{a}!"
=> "My favorite number is ten!"

字符串插值是一种将 Ruby 代码与字符串合并的便捷方式。基本语法是: #{ruby expression goes here},返回的表达式将与周围的字符串连接起来。字符串插值仅适用于双引号内。随着时间的推移,你会非常熟悉这种技术。

符号

Ruby 符号是通过在单词前放置一个冒号来创建的。

# symbols 示例
:name
:a_symbol
:"surprisingly, this is also a symbol"

基本上,当你想引用字符串之类的内容但不打算将其打印到屏幕或更改它时,将使用符号。它通常被称为不可变(即不可更改)字符串。虽然在技术上不是 100% 正确,不顾这样解释方便我们记住符号字面量。

数字

数字在 Ruby 中有多种表示方式。数字的最基本形式称为整数。它只用整数表示,没有小数点。更复杂的数字形式称为浮点数。浮点数是包含小数的数字。

# 整型字面量示例
1, 2, 3, 50, 10, 4345098098

# 符号字面量示例
1.2345, 2345.4267, 98.2234

nil

在编程中,我们需要一种表达 “无” 的方法,而在 Ruby 中,我们通过值为 nil. 的变量。nil 可以被描述为 “没有” 或 “完全为空”,甚至只是 “不是任何特定类型”。可能发生这种情况的情况是期望输出但没有返回,例如:

irb :001 > puts "Hello, World!"
Hello, World!
=> ni

该 puts 方法打印出一个字符串并没有返回任何内容,因此我们看到 nil 在显示字符串后返回。

你可以通过 nil 在我们的代码中使用文字来显式引用该值:

irb :002 > x = nil
=> nil

可以使用.nil? 。例如:

irb :001 > "Hello, World".nil?
=> false

nil 类型的一个重要属性是,当在表达式(例如 if 语句)中使用时,它将被视为 false,因为它表示没有内容。

irb :001 > if nil
irb :002 >   puts "Hello, World!"
irb :003 > end
=> nil

在上面的示例中,输出类型(如哈希火箭所示)是 nil,并且 中包含的代码 if 未运行,因为 nil 被解释为错误条件。相反,如果你要执行以下操作:

irb :001 > if 1
irb :002 >   puts "Hello, World!"
irb :003 > end
Hello, World!
=> nil

由于 1 不是 “无” 或假值,因此 if 运行 中的代码并且我们看到输出。稍后我们将更多地讨论条件和 if 语句,但请记住,nil 可以在条件语句中使用,并将被视为假。

对此有一个重要的警告,可以通过以下示例来最好地说明:

irb :001 > false == nil
=> false

虽然 false 和 nil 在表达式中计算时都被视为负数,但它们并不等效,如上所示。

操作

整数的加法、减法和乘法

Ruby 中的基本数学运算非常简单。要将两个整数相加,只需 + 在 irb 中使用如下所示的运算符。确保将这些示例输入 irb 并随意使用其他整数。

irb :001 > 1 + 1
=> 2

减法的工作方式相同。

irb :001 > 1 - 1
=> 0

乘法使用*运算符。

irb :001 > 4 * 4
=> 16

除法与模数

你可以使用/运算符对整数进行除法。

irb :001 > 16 / 4
=> 4

还有一个运算符称为模运算符。这由%符号表示。它也可以称为余数运算符,尽管这并不严格正确。在模表达式中,左边的值%称为商,右边的值称为模数。

处理正整数时,模运算符返回除法运算的余数。让我们测试一下。

irb :001 > 16 % 4
=> 0

这不是很有趣。那这个呢?

irb :001 > 16 % 5
=> 1

我们走了!由于 16 除以 5 等于 3,余数为 1,因此我们返回的是 1。很花哨吧?

现在,请注意当我尝试除以不均匀除法的整数时会发生什么。

irb :001 > 15 / 4
=> 3

在对整数进行除法时,你只会收到一个整数作为返回值。如果我们想要更高的精度,我们需要不同的数据类型。这就是花车进来的地方,我们稍后会讲到。不过,首先,我们需要讨论一些有时会让学生感到困惑的事情:模数和余数之间的区别。

模数与余数

该#remainder 方法计算并返回整数除法运算的余数:

irb :001 > 16.remainder(5)
=> 1

嗯……结果和 16 % 5. 然而,你不能指望这总是正确的,我们马上就会看到。还有一种#divmod 方法可以计算除法的整数结果及其模值。

irb :001 > 16.divmod(5)
=> \[3, 1\]

在数学中,模运算和余数运算之间存在细微但重要的区别。我们不会进入数学定义,但效果可以总结如下:

模运算在第二个操作数为正时返回一个正整数,当第二个操作数为负时返回一个负整数。
余数运算在第一个操作数为正时返回一个正整数,当第一个操作数为负时返回一个负整数。

在处理正整数时,我们不必担心应该使用模运算符还是余数方法;无论哪种方式,返回值都是正数且相同。然而,如果任何一个数字都是负数,那就是事情变得混乱的地方。牢记上述规则确实不容易,尤其是当你不经常遇到它们时。更复杂的是,一些语言使用%运算符来计算余数而不是模值。

通常,你希望避免这个问题——如果你需要确定两个整数的模数或余数,请尝试只使用正整数。如果不能,那么请确保你确切地知道在处理负整数时需要使用哪种运算符或方法。

乘法和除法浮点数

为了更准确地计算上述除法问题,我们可以使用 floats。

irb :001 > 15.0 / 4
=> 3.75

啊,这样更好看。每当你在运算中使用浮点数时,Ruby 总是返回一个浮点数,即使其中一个数字是纯整数。

你还可以乘以浮点数来进行更复杂的乘法。

irb :001 > 9.75 * 4.32
=> 42.120000000000005

相等比较

有时你想检查两个对象的值是否相同。要测试两件事的相等性,你可以使用运算符。这会将 左侧的对象与右侧的对象进行比较,并返回 true 或 false。 true 并且在大多数编程语言中 false 被称为布尔值。让我们在 irb 中尝试一些比较。也不要忘记输入这些示例!

irb :001 > 4 == 4
=> true
irb :002 > 4 == 5
=> false

你也可以将==运算符与字符串一起使用。

irb :001 > 'foo' == 'foo'
=> true
irb :002 > 'foo' == 'bar'
=> false

在 irb 中输入以下命令会发生什么?

irb :001 > '4' == 4

这种比较返回 false 是因为我们正在比较两种不同的类型。因为’4’是字符串并且 4 是整数,所以==运算符返回 false。

字符串连接

字符串连接看起来很像加法。当你使用 + 运算符将两个字符串连接在一起时,你正在执行字符串连接。回到 irb!

irb :001 > 'foo' + 'foo'
=> "foofoo"
irb :002 > 'foo' + 'bar'
=> "foobar"

它非常简单,但可以随意使用此功能以获得更好的感觉。

让我们尝试一些不同的东西。下面会返回什么?自己试试吧。

irb :001 > '1' + '1'

如果你在想 2,那绝对是有道理的。但是由于’1’和’1’都是字符串,所以它们是连接在一起的,而不是相加的。这就是为什么你最终得到’11’.

irb :001 > '1' + '1'
=> '11'

如果我们尝试连接一个字符串和一个数字会发生什么?

irb :001 > 'one' + 1
=> TypeError: no implicit conversion of Integer into String
   from (irb):1:in `+'
   from (irb):1
   from /usr/local/rvm/rubies/ruby-2.5.3/bin/irb:16:in `<main>'

看起来我们有一个错误信息!解释器抱怨它不能隐式转换 Integer 为 String. 这意味着什么?在这种情况下,它看起来像我们不能添加 Integer 和 String 在一起。

类型转换

但是如果我们需要将 aString 和 a 添加 Integer 在一起呢?假设我们得到了一些用户输入’12’,即 a String,但我们希望将其增加 2。我们知道我们不能只做’12’ + 2,因为我们会得到一个错误。

我们可以调用一个方便的方法将 a 转换 String 为 a Integer,它被称为 to_i。你可以 String 像这样调用它:

irb :001 > '12'.to_i
=> 12

你可以看到这将返回一个 Integer. 好的,我们使用了一些新词,例如 method 和 returns。理解这些非常重要,你将在整本书中接触到它们。现在,只知道我们可以调用 to_i 字符串,然后我们可以对结果执行整数运算,比如加法和减法。

to_i在 irb 上玩一些字符串,看看你会得到什么。你可能会对结果感到惊讶。还有其他有用的转换运算符,例如 to_f,你可能也有兴趣进行测试。

以下是一些有趣的尝试示例:

irb :001 > '4'.to_i
=> 4

irb :002 > '4 hi there'.to_i
=> 4

irb :003 > 'hi there 4'.to_i
=> 0

irb :004 > '4'.to_f
=> 4.0

irb :005 > '4 hi there'.to_f
=> 4.0

irb :006 > 'hi there 4'.to_f
=> 0.0

如果你猜想有一种类似的 to_s 方法可以将整数和浮点数转换为字符串,那么你是对的。我们将把它留作练习,让你在 irb 中使用该方法。

这只是 Ruby 内置转换方法的皮毛,但现在已经足够了。只要知道可能有一种方法可以将一种基本类型转换为另一种,尽管在进行转换时可能会有一些副作用。始终 irb 尝试使用它以了解边缘情况。

基本数据结构

作为 Ruby 程序员,你将使用的两种非常常见的数据结构是数组和哈希。本书稍后将更深入地介绍它们,但我们希望尽早让你体验它们,以便更顺畅地学习。

数组

一个阵列用于组织信息到有序列表。该列表可以由字符串、整数、浮点数、布尔值或任何其他数据类型组成。在 Ruby 中,数组字面量由方括号 表示 [ ]。在括号内,你可以创建由逗号分隔的元素列表。让我们在 irb 中制作一个。

irb :001 > [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]

我们创建了一个从 1 到 5 的整数数组。数组中的每个元素都可以通过索引访问。索引从零开始编号。因此,如果我们只想要数组中的第一个元素,我们可以这样做。

irb :001 > [ 1, 2, 3, 4, 5][0]
=> 1

如果 [0] 零件扔给你,请不要担心。稍后我们将更详细地介绍数组。这只是为了向你展示第一个元素,即数字 1,位于数组的 0 索引中。通过将 0 的值交换为另一个索引来使用上面的语法。关于数组要记住的关键是顺序很重要,数组中的元素可以通过索引检索,索引从 0 开始。

哈希值

有时被称为字典,是一组键 - 值对。哈希文字用花括号表示{ }。键值对是一种关联,其中为键分配了特定值。哈希由一个键组成,通常由一个符号表示,指向=>任何类型数据的值(用 a 表示)。让我们做一些哈希来感受一下。一起打字!

irb :001 > {:dog => 'barks'}
=> {:dog => 'barks'}
```ruby

以上是指定单个键值对的哈希文字。像数组一样,如果我们用逗号分隔它们,我们可以在哈希中包含多个项目,但它们不一定按任何特定顺序排列。让我们向哈希中添加更多项目。
```ruby
irb :001 > {:dog => 'barks', :cat => 'meows', :pig => 'oinks'}
=> {:dog => 'barks', :cat => 'meows', :pig => 'oinks'}

如果我们想知道猫发出什么声音怎么办?我们可以通过它的键检索一个值:

irb :001 > {:dog => 'barks', :cat => 'meows', :pig => 'oinks'}[:cat]
=> "meows"

再说一次,现在理解这些基本的数据结构是非常重要的。它们是编程的构建块,随着 Ruby 开发人员的成长,你将对它们进行长期的探索。关于哈希,最重要的是要记住使用键来设置或检索值。现在让我们继续,稍后我们将再次访问这些概念。

表达式和返回

在这一点上,你可能间接地注意到,每当你在 irb 中输入某个内容时,你都会看到=>back,它被称为 hash rocket(酷名字,嗯?),后跟 Ruby 表达式返回的内容。当你在 irb 提示符下输入一些内容时,你正在创建一个表达式。表达式是任何可以计算的东西,而用 Ruby 编写的几乎所有东西都是表达式。Ruby 中的表达式总是返回一些东西,即使是错误消息或 nil。接下来我们将更深入地讨论返回,但请记住,Ruby 表达式总是返回一个值,即使该值为 nil 或是一个错误。

puts vs return

对于没有经验的新 Ruby 程序员来说,对 puts 和之间的区别感到困惑是很常见的 return。混淆源于对两者 puts 和 return 是什么的误解。当我们调用该 puts 方法时,我们是在告诉 Ruby 将一些内容打印到屏幕上。但是,puts 不会返回打印到屏幕上的内容。表达式做了一些事情,但它们也返回一些东西。返回的值不一定是执行的操作。我们来看看 irb。

irb :001 > puts 'stuff'
stuff
=> nil

你可以看到这个词 stuff 被打印到控制台,然后 a nil,这是 Ruby 表示 “没有” 的方式,被返回。理解这种区别很重要。例如:

a = puts "stuff"
puts a

我们应该期待什么?a 被分配给由 返回的值 puts “stuff”,即 nil。因此,puts a 结果打印出 “nil”。我们将走的更远成 puts 和 return,当我们谈论方法之后,但我们不得不告诉你 puts,因为我们将在以后的例子来使用它。