写这篇文章的初衷源于我的伙伴们在上手Ruby过程中,表现实在是太让人拙计了。由于项目的急功近利,需要迅速入门Ruby并上手项目。所以很多开发者在实际开发过程中,不熟悉Ruby的表达方式,也会沿用其他语言比较生涩的表达形式。在我看来,Ruby的学习应该是个系统的循序渐进的过程,尽量避免急迫的方式。不过现实往往是紧迫的,所以就有了这篇文章。

标题中的菜鸟主要是指那些有其他编程语言开发经验,但在Ruby面前是个学习时间不久的初学者。我的工作伙伴都是这样的一些人。所以,我就在考虑Ruby和其他语言的一些显著的不同点,想要提点他们注意这些地方,能将程序尽量写得Rubic。在我与其他语言进行比较的过程中,有了一些灵感,所以我就写了点。后来灵感多了些,我也就多写了些。

着重指出一点,没有菜鸟开发者,只有停滞不前的开发者。系统学习一门语言才能自如地运用该语言的表达。Ruby的官方文档是永远是学习Ruby语言的最好资料,它最全面且持续更新。此外,Ruby的官方也给出了从其它语言到 Ruby的比较文档。

字符串

在Java中,字符串只有双引号的形式;在Python和JavaScript中,字符串既有单引号形式也有双引号形式,但它们实践是一回事。在Ruby的世界中,字符串的表达方式要丰富得多。Ruby中的字符串,既有单引号的形式,也有双引号的形式,但它们的含义却是截然不同的。

单引号的字符串,指的是原生字符串,其中不含有转义规则。例如'\n'不是指换行符,而是指两个字符的字符串,分别为字符\\和字符n

双引号的字符串,是包含转义规则的。例如"\n"就是指换行符。另外,双引号的字符串还可以使用#{...}的方式嵌入表达式。

"My Name is #{name}, and my years old is #{age}."

TODO 多行字符串

符号

Ruby引入符号的概念,是源于Ruby的一个设计缺陷。在大部分语言设计中,字符串都设计为不可变对象;然而在Ruby当中,字符串被设计为可变的。为此,引入了另一个字符序列的类型,但它是不可变的。这就是符号(Symbol)。

Ruby中符号的写法是在文本前面加上冒号(:)。对于Ruby中合法的变量名,直接加上冒号即可,例如:

:name
:age
:kind_of_animal

也可以在字符串前面加上冒号,这时符号的内容可以包含空格等变量名不允许的字符。示例:

:"My Name is #{name}, and my years old is #{age}."

这里字符串的单引号和双引号的性质也被沿用了下来。

符号是不可变的;并且,其是唯一的。对于内容完全相同的符号,其只会有一个实例存在于Ruby解释器环境中。

TODO 相同内容符号的object_id一致

符号对于Hash的构造有特殊的作用。Ruby中,Hash的构造比较繁琐,要用到=>符号:

{ 'a' => 'a', 'b' => 'b', 'c' => 'c' }

但是如果键值都是符号的话,有简便的构造方法:

{ a: 'a', b: 'b', c: 'c' }

它等价于:

{ :a => 'a', :b => 'b', :c => 'c' }

由于在方法调用中最后一个Hash参数可以省略大括号,所以下面的调用

f({ a: 'a', b: 'b', c: 'c' })

可以去掉大括号,写成:

f(a: 'a', b: 'b', c: 'c')

这就很像Python的关键字参数了。

最后,符号和字符串的相互转化方式如下:

str.to_sym  #字符串转化为符号
sym.to_s #符号转化为字符串

方法名是符号。

一切皆是对象

Java中有些基本数据类型(boolean、int、double),它们不是对象。JavaScript中的基本数据类型可以理解为对象,如boolean、number、string、function;但它们不能像普通的JS对象那样自如地增删属性。Python要彻底些,一切皆是对象,包括数字和布尔值都是普通的对象。

不过,比起所有其他的语言,Ruby是贯彻一切皆是对象这一思想最彻底的语言。在Ruby中:

  • 数字、布尔值、字符串、数组是对象。

  • 类是对象,它是Class类的实例。

  • 指示对象不存在的nil值也是对象,它是NilClass的实例,可以调用方法to_s, to_i等。

一切皆是表达式

这可能是Ruby又一个玄妙的地方了,影射了Ruby大一统的设计理念。Ruby中一切皆是表达式,一切表达方式都返回值。

  • 普通的Ruby表达式当然返回值。

  • if、while等控制结构返回值,其值是内部最后一条语句的值。

  • 方法调用返回值,其值由return指定或者是方法内最后一条语句的值。

  • 类定义返回值,其值是类内部最后一条语句的值。

  • 方法定义返回值,其值是方法名表示的符号。

TODO 一切皆是表达式示例

一切皆是方法调用

Ruby是也是贯彻面向对象设计模式最彻底的语言。在面向对象的设计理念中,为了提升封装性,会禁止直接的对象属性操作,只给出相应的get和set方法。

而在Ruby中,从语言层级中就禁止了直接访问对象属性的途径,只存在方法调用。我们平常常见的a.namea.name = 'Hello'的调用方式,看上去很像是直接操作属性,其实不是的。因为Ruby的方法调用可以省略括号,所以

a.name

等价于

a.name()

a.name = 'Hello'

的形式,实际上是

a.name=('Hello')

的简写。

TODO attr_reader, attr_writer, attr_accessor宏

省略分号

TODO 省略分号

省略括号的方法调用

Ruby中的方法调用,可以省略括号:

f a, b, c

等价于:

f(a, b, c)

控制结构

TODO 控制结构:if-else,unless-else,when-case,while,begin-rescue-ensure

变量命名约定

面向对象语言中,根据作用域的不同,分别有全局变量、常量、类变量、实例变量、局部变量的区别。在其他的语言中,可能是通过不同的修饰符和作用域进行区别。例如在Java中,没有全局变量的概念,常量用final修饰,类变量用static修饰,实例变量存在于类定义中,局部变量存在于方法定义中。有时候,这些变量很容易混淆;局部变量也很容易覆盖掉实例变量和类变量。

在Ruby中,是以变量名的格式区别变量的类型。总结如下:

  • 局部变量:以小写字母开头

  • 常量:以大写字母开头

  • 实例变量:以@开头

  • 类变量:以@@开头

  • 全局变量:以$开头

TODO 变量名示例

方法名约定

Ruby中的方法名结尾可以跟?和!。一般来说,以?结尾的方法返回布尔值;以!结尾的方法提示危险性。例如字符串中,empty?返回字符串是否为空;subsub!方法替换字符串,区别是sub不修改原字符串,返回替换的字符串;sub!作原地替换,会修改原字符串。

一般来讲,返回布尔值的方法名以?结尾,会对原对象作潜在性的修改的方法名以!结尾。

Ruby中的方法不是一等公民。方法不是值,不能作为参数传递给另一个方法。不过Ruby有块的概念,块可以作为语言特性附加给方法调用。

块的写法有两种形式,分别是大括号形式和do...end形式。

大括号形式:

{ |a, b|
a.to_i <= b.to_i
}

do...end形式:

do |a, b|
a.to_i <= b.to_i
end

乍一看,大括号的形式有点丑。一般来说,只在单行块的时候用大括号的形式:

{ |a, b| a.to_i <= b.to_i }

Ruby中的每个方法都可以接受一个块。块要紧接着方法调用的后面,不是方法的参数之一。例如

f(1, 2, 3) do |a, b|
a.to_i <= b.to_i
end

上面的示例中省略括号也是合法的:

f 1, 2, 3  do |a, b|
a.to_i <= b.to_i
end

但像下面这样把块用括号括起来作为最后一个参数就是错误的:

f(1, 2, 3, { |a, b| a.to_i <= b.to_i }) #语法错误

块与方法一个很大的区别是块支持闭包:

min = 18

array.select do |v|
v >= min #访问外层min变量
end

TODO 在方法定义中用yield关键字调用块

迭代器

Ruby中没有提供Java和JavaScript当中三段for循环的模式。所谓三段for循环,是指下面JavaScript的for循环:

for(i = 0; i <= 9; i++) {
console.log(i);
}

Ruby中没有提供这样的方式。但这并没有什么痛苦的,因为Ruby提供了基于块的迭代方式。例如上面的代码,在Ruby中可以写成:

0.upto(9) do |i|
puts i
end

Ruby中的集合,都支持这样传递代码块的迭代方式。Ruby中的集合包括Range、Array、Hash、String、etc。例如上面的示例可以改写成Range的each迭代形式:

(0..9).each do |i|
puts i
end

TODO -ect方法:collect, inject, select

真假值

Ruby中用于if、unless、while的条件判断中,真假值的规则很简洁:

  • nil和false为假

  • 其余都为真

TODO list

我懒!

Ruby菜鸟入门指南的更多相关文章

  1. CUDA显卡运算编程菜鸟入门指南1——Hello world - yfszzx的专栏 - 博客频道 - CSDN.NET

    第一次知道有显卡(GPU)编程这个东西,是去年比特币最热门的时候,看了几篇关于比特币的文章,说比特币挖矿要靠显卡,CPU的速度与GPU根本就没法比,于是就非常好奇,显卡是什么神奇的东西?为什么运算速度 ...

  2. [转] Clojure 快速入门指南:1/3

    [From] http://huangz.iteye.com/blog/1325228 导读 本文的目标是为熟悉 Ruby.Python或者其他类似语言.并对 Lisp 或者函数式编程有一定程度了解的 ...

  3. Vue.js 入门指南之“前传”(含sublime text 3 配置)

    题记:关注Vue.js 很久了,但就是没有动手写过一行代码,今天准备入手,却发现自己比菜鸟还菜,于是四方寻找大牛指点,才终于找到了入门的“入门”,就算是“入门指南”的“前传”吧.此文献给跟我一样“白痴 ...

  4. 【翻译】Fluent NHibernate介绍和入门指南

    英文原文地址:https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started 翻译原文地址:http://www.cnblogs ...

  5. React-Native入门指南之HelloWorld

    iOS React-Native入门指南之HelloWorld React-native 作为facebook开源项目,最近是火的一塌糊涂,它采用node.js能够写ios和android的nativ ...

  6. Ext JS 6学习文档–第1章–ExtJS入门指南

    Ext JS 入门指南 前言 本来我是打算自己写一个系列的 ExtJS 6 学习笔记的,因为 ExtJS 6 目前的中文学习资料还很少.google 搜索资料时找到了一本国外牛人写的关于 ExtJS ...

  7. Java程序员的Golang入门指南(上)

    Java程序员的Golang入门指南 1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如 ...

  8. CSS进阶之SASS入门指南

    CSS进阶之SASS入门指南         随着跟着公司学习项目的前端的推进,越来越对好奇了许久的SASS垂涎欲滴,哈哈,可能这个词使用不当,没有关系,就是对SASS有一股神秘的爱!好了,闲话不多说 ...

  9. 深入浅出 JMS(二) - ActiveMQ 入门指南

    深入浅出 JMS(二) - ActiveMQ 入门指南 上篇博文深入浅出 JMS(一) – JMS 基本概念,我们介绍了消息通信的规范JMS,这篇博文介绍一款开源的 JMS 具体实现-- Active ...

随机推荐

  1. python接口测试,第三方包xlrd和xlutils,怎么安装

    第1个:xlrd的下载地址:https://pypi.python.org/pypi/xlrd/0.9.2 安装过程:下载后解压文件夹,使用cd命令行进入该文件夹后,用命令:python setup. ...

  2. wpf窗口禁止最大化但允许调整大小

    wpf中窗口禁止最大化可以通过属性ResizeMode来设置,但是ResizeMode有一个问题就是如果ResizeMode设置为NoResize的话,是可以禁止最大化的,但是这样同时也就不能拖动调整 ...

  3. DSOFramer控件使用注意事项

    1.引用dll==>AxInterop.DSOFramer.dll ==>Interop.DSOFramer.dll ==>WindowsFormsIntegration ==> ...

  4. 51nod 1086【背包·DP】

    思路: 如果体积乘以数量>=W,那么直接用完全背包模型.如果不到的话,用二进制优化就好了. 基础题,感觉这样写很优雅?回去睡觉. #include <bits/stdc++.h> u ...

  5. RVO算法

    http://blog.sina.com.cn/s/blog_6ad33d350102xqal.html 简介 在介绍VO,RVO之前,需要先介绍路径规划. 对Agent进行路径规划,实际上要完成的任 ...

  6. 洛谷P1220 关路灯(区间dp)

    关路灯 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯.为了给村里节 ...

  7. 2014-9-13 NOIP模拟赛

    NOIP2014模拟赛 ——lwher 题目名 环上的游戏 舞蹈课 数位和乘积 源文件 cycle.cpp/c/pas dancingLessons.pas/cpp digit.cpp.cpp/c/p ...

  8. codevs 3333 高级打字机

    3333 高级打字机   题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作 ...

  9. Python学习笔记(正则表达式)

    \b - 表示以什么开头或结尾 \d - 匹配数字 \w - 匹配字母或数字或下划线或汉字(我试验下了,发现3.x版本可以匹配汉字,但2.x版本不可以) \s - 匹配任意的空白符 ^ - 匹配字符串 ...

  10. Java IO 输入和输出流

    数据流是指一组有顺序的,有起点和终点的字节集合. 最初的版本中,java.io 包中的流只有普通的字节流,即以 byte 为基本处理单位的流.字节流用来读写 8 位的数据,由于不会对数据做任何转换,因 ...