`
RednaxelaFX
  • 浏览: 3052948 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

关于||=与变量定义

    博客分类:
  • Ruby
阅读更多
在Ruby里,给可能未定义或值为nil的变量设置一个默认初始值时,惯用法是使用||=的办法,例如:
a ||= []
a << 'first'

这个例子里,无论a原本有没有定义,或者定义是什么都好,都会被当作是一个变量。如果原本a是一个有非nil非false值的变量,那么a的值不变;如果a原本是一个方法,那么作为方法名的a会被作为变量名的a所屏蔽,并且a被赋值为[]。
看下面这个例子:
a ||= 1
puts a               # 1

def b
  2
end

puts b               # 2
puts b || 3          # 2

b ||= 3
puts b               # 3
puts method(:b).call # 2

可以看到变量名屏蔽方法名的行为。

OK,那有什么好说的呢?Ola Bini最近做过一个关于在JVM上创造自己的语言的讲演,其中有一部分是向与会者介绍Ruby。他演示的时候提到诸如a ||= 1没问题,但他一时以为在a还没定义的时候a = a || 1不行,在演示的时候稍微卡了一下。乍一看,要是根据他当时的思路,确实会觉得这个不行。
思路是:如果单独写a || 1,在a还没定义的时候,访问a的值会得到“未定义局部变量或方法”的错误;把这个放在赋值的右手边,就应该会在能够赋值之前就先遇到错误了。

但实际上,a ||= 1就是a = a || 1的简写,这两者在运行时的行为是一样的。那为什么单独写a || 1会出问题,而放在赋值的右手边就没事了呢?
因为Ruby要想办法知道一个名字到底是变量还是方法调用。最直观的判断依据是,执行到当前位置时这个名字有没有出现在赋值符号的左手边,有的话就把这个名字当作变量,没有的话就默认把这个名字当作方法;后一种情况中如果没有这个名字的方法,那就出错了。
像这样就会出错:
def foo
  puts b  # undefined local variable or method `b'
  b = 1 if false
end

foo

而这样就不会:
def foo
  b = 1 if false
  puts b  # nil
end

foo

也就是说不用真的执行赋值,只要Ruby解析器能看到某个名字出现在赋值符号的左边就够了,就会创建一个这个名字的变量,未赋值时值为nil。

回到a = a || 1。这里Ruby先看到了a出现在赋值符号的左手边,于是创建出变量a,值为nil;接下来对赋值符号右手边求值,nil || 1的结果是1;然后完成赋值,a的值就是1了。单独的a || 1则没这待遇,得看前面有没有别的地方让a存在,不然就会出错。

以前在好多地方都有人提到过Ruby的这个行为。昨晚跟NS老兄聊的时候突然想起||的问题一时没想通,多得他提醒才又想起来了。记下来免得以后又糊涂……
分享到:
评论
2 楼 RednaxelaFX 2009-04-07  
night_stalker 写道
油头粉面的 Ola 被卡住的时候真尴尬……

嗯 XDD
顺带一提,那段录像可以在Ola Bini的blog上找到链接,在这里
对应的幻灯片在这里
1 楼 night_stalker 2009-04-05  
油头粉面的 Ola 被卡住的时候真尴尬……

其实这个特性有好处的:如果不小心写错了一个字母,就会弹出一个error

def fun very_long_parameter_nameeeeeeeeeeeee
  very_long_parameter_nameeeeeeeeeeee || 'bastard!'
end

相关推荐

    visual--c/c++--sanfa

    #### 定义及原理 迭代法是一种常用的算法设计方法,主要用于求解方程或方程组的近似根。对于一个形式为 \(f(x) = 0\) 的方程,通过数学变换得到一个新的等价形式 \(x = g(x)\)。迭代法的核心在于通过反复计算 \(g(x)...

    数学北师大七年级上绝对值PPT学习教案.pptx

    首先,绝对值被定义为一个数在数轴上对应点与原点之间的距离。这意味着任何数的绝对值都是非负的,因为距离不能为负。例如,4的绝对值是4,表示在数轴上4与原点的距离是4个单位;同样,-5的绝对值也是5,因为-5与...

    第1章 概率论基础2-统计部分1

    在本章中,我们将深入探讨条件数学期望的定义、性质及其应用。 首先,条件数学期望是基于某一条件下的随机变量的数学期望。对于一个二维随机变量(,),当给定的值时,的条件数学期望[| = ]是在取特定值时,的期望...

    lcc源程序分析21-40【PDF版】

    接下来,我们将深入分析LCC源代码中关于局部变量声明的处理过程。这一部分的代码主要位于 `compound` 函数中,具体如下所示: ```c #031 // 局部变量声明处理. #032 while(kind[t] == CHAR || kind[t] == STATIC #...

    1.2 编程基础之变量定义、赋值及转换 python版.zip

    文件"1.2编程基础之变量定义、赋值及转换 05 填空:类型转换2.py"和"1.2编程基础之变量定义、赋值及转换 04 填空:类型转换1.py"可能是关于不同类型之间的转换练习,比如浮点数到整数的舍入(在"1.2编程基础之变量...

    部分互信息解决变量方向

    例如,当 \(X\) 与 \(Z\) 独立时,可以定义 \(PMI(X;Y|Z)\) 为: \[ PMI(X;Y|Z) = I(X;Y|Z) + D(p(x|z)||p^*(x|z)) + D(p(y|z)||p^*(y|z)) \] 这里,当 \(X\) 与 \(Z\) 独立时,有 \(p(x|z) = p(x)\) 和 \(p^*(x|z...

    n次独立重复试验与二项分布.pdf

    本资源是关于n次独立重复试验和二项分布的知识点总结。内容涵盖条件概率、事件的相互独立性、独立重复试验和二项分布等方面。 条件概率 条件概率是指在事件A发生的情况下,事件B发生的概率。其定义为P(B|A)=P(AB)...

    好东东一个关于C的程序

    - **函数声明与定义**:在C语言中,函数必须先声明后使用。例如,`int fun(int a[M][N]) {}`是函数声明,而`int fun(int a[M][N]) {...}`是函数定义。 - **主函数main()**:程序的入口点,所有C程序都必须有一个main...

    2019_2020学年高中数学第2章随机变量及其分布2.2.1条件概率课件新人教A版选修2_3202004290481

    在高中数学中,特别是在随机变量及其分布的学习中,条件概率是理解二项分布和其他概率模型的关键。 标题和描述提到的是高中数学课程中关于条件概率的部分,具体到2.2.1章节,即条件概率的讲解。这部分内容通常会...

    C/C++语言中全局变量重复定义问题的解决方法

    宏定义、结构体定义、函数声明以及全局变量定义放到一个head.h头文件中 函数的定义放到head.cpp中 main函数放到main.cpp中 然而却报错了,提示xxx变量在*.obj文件中已定义 问题出现的原因 为什么会出现这种...

    矩阵的秩与方程组的解PPT学习教案.pptx

    1. 矩阵的秩(Rank)定义了矩阵列向量张成的空间的维度,即最大线性无关向量组的个数。对于行阶梯阵,秩可以通过非零行的个数来确定。 2. 方程组的解的情况与矩阵的秩和增广矩阵[A, b]的秩有关。如果R(A|b) = R(A) ...

    C++实现万年历,适合初学者的小代码

    类定义与成员变量 ```cpp class date { private: int year, month, day; public: void set(int y, int m, int d); void isleapyear(); void print(); void week(); void declare(); bool wrong(); void add...

    java中关于变量的练习题及答案

    ### Java中关于变量的练习题及答案解析 #### 基础知识点概述 在Java编程语言中,变量是用来存储数据的容器。理解变量的基本概念及其使用规则是学习Java的基础之一。本篇解析将针对给定的练习题进行详细解答,并...

    高等数学 第五版 下册 齐次方程

    一种常见的解法是将变量u定义为u=xy,从而将原方程转化为关于u的微分方程。当进行这种变量代换时,\( dx = \frac{du}{y} - \frac{xdu}{y} \) 和 \( dy = \frac{du}{x} \),这样可以将原方程改写为关于u的可分离变量...

    Enum ,file

    在编程领域,枚举(Enum)是一种特殊的数据类型,它允许我们定义一组相关的常量,这些常量可以作为变量的值。在这个上下文中,“Enum file”可能是指使用枚举来处理或操作文件的过程。在VC++6.0,这是一个较老的...

    届高三数学第二轮专题一第六讲数学思想方法与答题模板建构.pdf

    3. **函数定义域**:第二题和第四题涉及到函数的定义域,需要找到使函数有意义的自变量x的取值范围。 4. **不等式求解**:第四题通过解不等式`f≤ 0`和`f'&lt;x&gt;&lt;0`来确定集合M和N,这里涉及到二次不等式的解法。 5. ...

    第1.2节 充分统计量与完备统计量.PPT

    此外,因子分解定理在实际应用中非常有用,因为它提供了一种检验统计量充分性的简便方法,而无需直接验证定义。通过分解样本的联合分布,我们可以判断统计量是否包含关于总体参数的所有信息,这对于构建有效的统计...

    高二数学 2.2.1 条件概率学案(扫描版,无答案) 学案.docx

    条件概率定义:设事件A和B是两个随机事件,如果已知事件B发生的情况下,事件A发生的概率,则称这个概率为事件A在事件B发生的条件下的概率,记为P(A|B)。它的计算公式是P(A|B) = P(AB) / P(B),其中P(AB)表示事件A和B...

    泛函分析考试题集与答案(精编版).pdf

    题目中证明了当xxn和yy n趋向于0时,内积(y, x)也趋向于0,表明内积函数关于两变量连续。 5. **线性算子的连续性**:线性算子T从一个赋范空间X到另一个赋范空间Y是连续的,当且仅当对于X中的所有收敛序列{x_n},T(x...

    《应用信息论基础》习题答案

    这些值表明,在已知另一个变量的情况下,关于未知变量的信息量减少了多少。 - **2.3(3)** 计算了互信息 \(I(X;Y) = 0.251 \text{ bit}\),以及三个随机变量的联合熵 \(H(XYZ) = 1.585 \text{ bit}\)。互信息表示两个...

Global site tag (gtag.js) - Google Analytics