- 浏览: 2652831 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
在Ruby中symbol是Symbol类的实例。symbol的语法为一个冒号后面接一个标识符。
symbol就像一个字符串,它表示了一个字符序列。它不像字符串,每个symbol只有一个实例(和Fixnum一样)。因此,有一个内存或
性能问题需要弄清楚。例如,在下面的代码中,"foo"字符串以三个单独的对象存储在内存中,但是symbol :foo作为一个单独的对
象存储(被引用了多次):
有些人被symbol前面的冒号弄糊涂了。其实没有必要糊涂;这只是一个简单的语法形式。字符串,数组和哈希都有开始和结束界定
符;而symbol只有一个开始界定符。把它当成一个单界定符而不是二元界定符即可。开始时你可能认为这个语法很奇怪,但事实上
没有什么神秘的。
值得注意的是在老版本的Ruby(1.6之前)中,symbol常量不是第一类对象而是转换成Fixnum来存储。现在在内核中这仍然是对的;
symbol对应于一个数字并作为一个immediate value来存储。这个值可以使用to_i来得到,但是没有必要。
根据Jim Weirich,symbol是"有名字的对象"。Austin Ziegler更喜欢说"an object that is a name"。无论怎样,在symbol和名字
间始终有一个一对一的对应。什么样的东西我们需要使用名字?例如变量,方法和任意的常量。
一个常见的symbol使用场景是表示变量或方法的名字。例如,我们知道如果我们想添加一个读/写属性到类中,我们可以这样做:
这等价于:
换句话说,:whatever这个symbol告诉attr_accessor方法"getter"和"setter(以及实例变量)都将根据该symbol来给予名字。
你可能想问为什么我们不能使用一个字符串来替代。我们可以。大部分希望使用symbol的核心方法都可以使用字符串来替代。
事实上,symbol就"像"一个字符串,它对应于一个字符序列。这导致有些人说"a symbol is just an immutalbe string"。
但是,Symbol类并不是继承于String,并且对于字符串典型的操作并不适合symbol。
另一个误解是认为symbol没必要直接对应于标识符。这导致有些人说"the symbol table"(as they would in referring to
an assembled object program)。但是这不是一个真正有用的概念;尽管在内部symbol存储在一种table里,Ruby并没有将
这个table作为一个实体暴露给我们访问,而我们作为编程者也不关心它的存在。
而且,symbol不需要看起来像标识符。虽然它们像标识符,但是它们也可以包含标点,如果它们被引号包围的话。如下也是
合法的Ruby symbol:
你甚至可以使用这些symbol来定义实例变量和方法,但是这样的话你需要send和instance_variable_get技术来引用它们。
一般来说不推荐使用字符串形式的symbol。
Symbols As Enumerations
Pascal以及后期版本的C等语言有一个enumerated type的概念。Ruby没有这样的东西;Ruby没有类型检查。但是symbol
非常有用;我可以用:north,:south,:east和:west来表示方向。
将这些symbol存储为常量可能更清晰。
如果它们是字符串而不是symbol,将它们定义为常量会节省内存,但无论如何每个symbol都只在对象空间里存在一次。
(像Fixnum一样Symbol存储为immediate value)
Symbols As Metavalues
我们经常使用异常来作为避免返回代码的方式。但是如果你宁愿使用返回代码的话也可以。RUby的方法不限于单返回类型,
这让传回"out of band"值成为可能。
我们经常需要这样的值。ASCII NUL字符被认为根本就不是一个字符。C有NULL指针,Pascal有nil指针,SQL有NULL等等。
Ruby当然也有nil。
这些metavalue的问题是它们成为合法的值。现在每个人都认为NUL是一个ASCII字符。在Ruby中,nil不是真的non-object;
它可以被存储和操作。这样我们有了如hash[key]返回nil这样的小烦恼;是因为key没有找到而返回nil,还是由于这个key
真的指向nil?
这里symbol可以用来作为好的metavalue。假设一个方法从忘了攫取一个字符串(可能通过http或其他类似的东西)。我们可以
返回非字符串值来表示出现异常。
这比使用异常更好或更清晰?没必要。但是记住,这是处理可能为"edge cases"但不一定是异常的条件时的一项技术。
Symbols, Variables, and Methods
可能使用symbol的最知名的地方是定义类的属性:
attr_accessor使用symbol名字来觉得实例变量和读写方法的名字。这不代表symbol和实例变量名之间有绝对的关系。
例如,如果你使用instance_variable_set,我们必须指定变量的名字,包括@符号:
简短来说,传递到attr系列方法的symbol只是一个参数,这些方法基于symbol的值创建需要的实例变量和方法。(writer方法
在结尾有一个=,而实例变量名字在前面有一个@。)换句话说,symbol必须与它引用的标识符相对应。
大部分情况下,希望使用symbol的方法也可以使用字符串。相反则不一定正确。
Converting to/from Symbols
字符串和symbol可以使用to_s和to_sym方法自由互换:
如果你做元编程,如下方法有时候可能很有用。
上面的方法允许我们连接symbol(或者添加字符串到一个symbol)。下面是一个使用它的例子;这段微小的代码接收一个symbol并
尝试告诉我们它是否是一个accessor(即,读写方法都存在):
我这里要提到一个使用symbol的聪明的方式。当我们做map操作时,有时候一个复杂的block可能附加在后面。但是许多情况下,
我们对每个元素简单的调用一个方法:
在这里,似乎我们为完成工作做了太多事情。让我们打开Symbol类并定义to_proc方法。这保证任何symbol都可以强制转换成
一个proc对象。但是我们应该返回什么proc?显然应该根据对象context里的symbol本身。换句话说,proc应该将symbol本身作
为一个消息发送给对象。
顺便提一下,这段代码来自Gavin Sinclair的"Ruby Extensions"对象。有了这个方法,我们可以重写上面的代码:
值得花费一分钟来理解它怎样工作。map方法使用一个block作为参数。&符号允许我们传递一个proc而不是一个显式附加的
block。由于我们在一个非proc对象上使用&符号,解释器会尝试调用该对象的to_proc方法。返回的proc替代了显式的block,
map将会对每个元素调用它。为什么self作为一个消息传递给array元素有意义呢?这是因为proc是一个闭包,所以它会记住
它被创建在哪个context里。当它被创建时,self表示调用to_proc的symbol。
symbol就像一个字符串,它表示了一个字符序列。它不像字符串,每个symbol只有一个实例(和Fixnum一样)。因此,有一个内存或
性能问题需要弄清楚。例如,在下面的代码中,"foo"字符串以三个单独的对象存储在内存中,但是symbol :foo作为一个单独的对
象存储(被引用了多次):
array = ["foo", "foo", "foo", :foo, :foo, :foo]
有些人被symbol前面的冒号弄糊涂了。其实没有必要糊涂;这只是一个简单的语法形式。字符串,数组和哈希都有开始和结束界定
符;而symbol只有一个开始界定符。把它当成一个单界定符而不是二元界定符即可。开始时你可能认为这个语法很奇怪,但事实上
没有什么神秘的。
值得注意的是在老版本的Ruby(1.6之前)中,symbol常量不是第一类对象而是转换成Fixnum来存储。现在在内核中这仍然是对的;
symbol对应于一个数字并作为一个immediate value来存储。这个值可以使用to_i来得到,但是没有必要。
根据Jim Weirich,symbol是"有名字的对象"。Austin Ziegler更喜欢说"an object that is a name"。无论怎样,在symbol和名字
间始终有一个一对一的对应。什么样的东西我们需要使用名字?例如变量,方法和任意的常量。
一个常见的symbol使用场景是表示变量或方法的名字。例如,我们知道如果我们想添加一个读/写属性到类中,我们可以这样做:
class SomeClass attr_accessor :whatever end
这等价于:
class SomeClass def whatever @whatever end def whatever=(val) @whatever = val end end
换句话说,:whatever这个symbol告诉attr_accessor方法"getter"和"setter(以及实例变量)都将根据该symbol来给予名字。
你可能想问为什么我们不能使用一个字符串来替代。我们可以。大部分希望使用symbol的核心方法都可以使用字符串来替代。
attr_reader :alpha attr_reader "beta" # This is also legal
事实上,symbol就"像"一个字符串,它对应于一个字符序列。这导致有些人说"a symbol is just an immutalbe string"。
但是,Symbol类并不是继承于String,并且对于字符串典型的操作并不适合symbol。
另一个误解是认为symbol没必要直接对应于标识符。这导致有些人说"the symbol table"(as they would in referring to
an assembled object program)。但是这不是一个真正有用的概念;尽管在内部symbol存储在一种table里,Ruby并没有将
这个table作为一个实体暴露给我们访问,而我们作为编程者也不关心它的存在。
而且,symbol不需要看起来像标识符。虽然它们像标识符,但是它们也可以包含标点,如果它们被引号包围的话。如下也是
合法的Ruby symbol:
sym1 = :"This is a symbol" sym2 = :"This is, too1" sym3 = :")(*&^%$" # and even this
你甚至可以使用这些symbol来定义实例变量和方法,但是这样的话你需要send和instance_variable_get技术来引用它们。
一般来说不推荐使用字符串形式的symbol。
Symbols As Enumerations
Pascal以及后期版本的C等语言有一个enumerated type的概念。Ruby没有这样的东西;Ruby没有类型检查。但是symbol
非常有用;我可以用:north,:south,:east和:west来表示方向。
将这些symbol存储为常量可能更清晰。
North, South, East, West = :north, :south, :east, :west
如果它们是字符串而不是symbol,将它们定义为常量会节省内存,但无论如何每个symbol都只在对象空间里存在一次。
(像Fixnum一样Symbol存储为immediate value)
Symbols As Metavalues
我们经常使用异常来作为避免返回代码的方式。但是如果你宁愿使用返回代码的话也可以。RUby的方法不限于单返回类型,
这让传回"out of band"值成为可能。
我们经常需要这样的值。ASCII NUL字符被认为根本就不是一个字符。C有NULL指针,Pascal有nil指针,SQL有NULL等等。
Ruby当然也有nil。
这些metavalue的问题是它们成为合法的值。现在每个人都认为NUL是一个ASCII字符。在Ruby中,nil不是真的non-object;
它可以被存储和操作。这样我们有了如hash[key]返回nil这样的小烦恼;是因为key没有找到而返回nil,还是由于这个key
真的指向nil?
这里symbol可以用来作为好的metavalue。假设一个方法从忘了攫取一个字符串(可能通过http或其他类似的东西)。我们可以
返回非字符串值来表示出现异常。
str = get_string case str when String # Proceed normally when :eof # end of file, socket closed, whatever when :error # I/O or network error when :timeout # didn't get a reply end
这比使用异常更好或更清晰?没必要。但是记住,这是处理可能为"edge cases"但不一定是异常的条件时的一项技术。
Symbols, Variables, and Methods
可能使用symbol的最知名的地方是定义类的属性:
class MyClass attr_reader :alpha, :beta attr_writer :gamma, :delta attr_accessor :epsilon # ... end
attr_accessor使用symbol名字来觉得实例变量和读写方法的名字。这不代表symbol和实例变量名之间有绝对的关系。
例如,如果你使用instance_variable_set,我们必须指定变量的名字,包括@符号:
sym1 = :@foo sym2 = :foo instance_variable_set(sym1, "str") # Works instance_variable_set(sym2, "str") # errors
简短来说,传递到attr系列方法的symbol只是一个参数,这些方法基于symbol的值创建需要的实例变量和方法。(writer方法
在结尾有一个=,而实例变量名字在前面有一个@。)换句话说,symbol必须与它引用的标识符相对应。
大部分情况下,希望使用symbol的方法也可以使用字符串。相反则不一定正确。
Converting to/from Symbols
字符串和symbol可以使用to_s和to_sym方法自由互换:
a = "foobar" b = :foobar a == b.to_s # true b == a.to_sym # true
如果你做元编程,如下方法有时候可能很有用。
class Symbol def +(other) (self.to_s + other.to_s).to_sym end end
上面的方法允许我们连接symbol(或者添加字符串到一个symbol)。下面是一个使用它的例子;这段微小的代码接收一个symbol并
尝试告诉我们它是否是一个accessor(即,读写方法都存在):
class Object def accessor?(sym) return (self.respond_to?(sym) and self.respond_to?(sym+"=")) end end
我这里要提到一个使用symbol的聪明的方式。当我们做map操作时,有时候一个复杂的block可能附加在后面。但是许多情况下,
我们对每个元素简单的调用一个方法:
list = words.map { |x| x.capitalize }
在这里,似乎我们为完成工作做了太多事情。让我们打开Symbol类并定义to_proc方法。这保证任何symbol都可以强制转换成
一个proc对象。但是我们应该返回什么proc?显然应该根据对象context里的symbol本身。换句话说,proc应该将symbol本身作
为一个消息发送给对象。
def to_proc proc { |obj, *args| obj.send(self, *args) } end
顺便提一下,这段代码来自Gavin Sinclair的"Ruby Extensions"对象。有了这个方法,我们可以重写上面的代码:
list = words.map(&:capitalize)
值得花费一分钟来理解它怎样工作。map方法使用一个block作为参数。&符号允许我们传递一个proc而不是一个显式附加的
block。由于我们在一个非proc对象上使用&符号,解释器会尝试调用该对象的to_proc方法。返回的proc替代了显式的block,
map将会对每个元素调用它。为什么self作为一个消息传递给array元素有意义呢?这是因为proc是一个闭包,所以它会记住
它被创建在哪个context里。当它被创建时,self表示调用to_proc的symbol。
评论
11 楼
funjackyone
2008-05-24
hideto 写道
在Ruby中symbol是Symbol类的实例。symbol的语法为一个冒号后面接一个标识符。
symbol就像一个字符串,它表示了一个字符序列。它不像字符串,每个symbol只有一个实例(和Fixnum一样)。因此,有一个内存或
性能问题需要弄清楚。例如,在下面的代码中,"foo"字符串以三个单独的对象存储在内存中,但是symbol :foo作为一个单独的对
象存储(被引用了多次):
有些人被symbol前面的冒号弄糊涂了。其实没有必要糊涂;这只是一个简单的语法形式。字符串,数组和哈希都有开始和结束界定
符;而symbol只有一个开始界定符。把它当成一个单界定符而不是二元界定符即可。开始时你可能认为这个语法很奇怪,但事实上
没有什么神秘的。
值得注意的是在老版本的Ruby(1.6之前)中,symbol常量不是第一类对象而是转换成Fixnum来存储。现在在内核中这仍然是对的;
symbol对应于一个数字并作为一个immediate value来存储。这个值可以使用to_i来得到,但是没有必要。
根据Jim Weirich,symbol是"有名字的对象"。Austin Ziegler更喜欢说"an object that is a name"。无论怎样,在symbol和名字
间始终有一个一对一的对应。什么样的东西我们需要使用名字?例如变量,方法和任意的常量。
一个常见的symbol使用场景是表示变量或方法的名字。例如,我们知道如果我们想添加一个读/写属性到类中,我们可以这样做:
这等价于:
换句话说,:whatever这个symbol告诉attr_accessor方法"getter"和"setter(以及实例变量)都将根据该symbol来给予名字。
你可能想问为什么我们不能使用一个字符串来替代。我们可以。大部分希望使用symbol的核心方法都可以使用字符串来替代。
事实上,symbol就"像"一个字符串,它对应于一个字符序列。这导致有些人说"a symbol is just an immutalbe string"。
但是,Symbol类并不是继承于String,并且对于字符串典型的操作并不适合symbol。
另一个误解是认为symbol没必要直接对应于标识符。这导致有些人说"the symbol table"(as they would in referring to
an assembled object program)。但是这不是一个真正有用的概念;尽管在内部symbol存储在一种table里,Ruby并没有将
这个table作为一个实体暴露给我们访问,而我们作为编程者也不关心它的存在。
而且,symbol不需要看起来像标识符。虽然它们像标识符,但是它们也可以包含标点,如果它们被引号包围的话。如下也是
合法的Ruby symbol:
你甚至可以使用这些symbol来定义实例变量和方法,但是这样的话你需要send和instance_variable_get技术来引用它们。
一般来说不推荐使用字符串形式的symbol。
Symbols As Enumerations
Pascal以及后期版本的C等语言有一个enumerated type的概念。Ruby没有这样的东西;Ruby没有类型检查。但是symbol
非常有用;我可以用:north,:south,:east和:west来表示方向。
将这些symbol存储为常量可能更清晰。
如果它们是字符串而不是symbol,将它们定义为常量会节省内存,但无论如何每个symbol都只在对象空间里存在一次。
(像Fixnum一样Symbol存储为immediate value)
Symbols As Metavalues
我们经常使用异常来作为避免返回代码的方式。但是如果你宁愿使用返回代码的话也可以。RUby的方法不限于单返回类型,
这让传回"out of band"值成为可能。
我们经常需要这样的值。ASCII NUL字符被认为根本就不是一个字符。C有NULL指针,Pascal有nil指针,SQL有NULL等等。
Ruby当然也有nil。
这些metavalue的问题是它们成为合法的值。现在每个人都认为NUL是一个ASCII字符。在Ruby中,nil不是真的non-object;
它可以被存储和操作。这样我们有了如hash[key]返回nil这样的小烦恼;是因为key没有找到而返回nil,还是由于这个key
真的指向nil?
这里symbol可以用来作为好的metavalue。假设一个方法从忘了攫取一个字符串(可能通过http或其他类似的东西)。我们可以
返回非字符串值来表示出现异常。
这比使用异常更好或更清晰?没必要。但是记住,这是处理可能为"edge cases"但不一定是异常的条件时的一项技术。
Symbols, Variables, and Methods
可能使用symbol的最知名的地方是定义类的属性:
attr_accessor使用symbol名字来觉得实例变量和读写方法的名字。这不代表symbol和实例变量名之间有绝对的关系。
例如,如果你使用instance_variable_set,我们必须指定变量的名字,包括@符号:
简短来说,传递到attr系列方法的symbol只是一个参数,这些方法基于symbol的值创建需要的实例变量和方法。(writer方法
在结尾有一个=,而实例变量名字在前面有一个@。)换句话说,symbol必须与它引用的标识符相对应。
大部分情况下,希望使用symbol的方法也可以使用字符串。相反则不一定正确。
Converting to/from Symbols
字符串和symbol可以使用to_s和to_sym方法自由互换:
如果你做元编程,如下方法有时候可能很有用。
上面的方法允许我们连接symbol(或者添加字符串到一个symbol)。下面是一个使用它的例子;这段微小的代码接收一个symbol并
尝试告诉我们它是否是一个accessor(即,读写方法都存在):
我这里要提到一个使用symbol的聪明的方式。当我们做map操作时,有时候一个复杂的block可能附加在后面。但是许多情况下,
我们对每个元素简单的调用一个方法:
在这里,似乎我们为完成工作做了太多事情。让我们打开Symbol类并定义to_proc方法。这保证任何symbol都可以强制转换成
一个proc对象。但是我们应该返回什么proc?显然应该根据对象context里的symbol本身。换句话说,proc应该将symbol本身作
为一个消息发送给对象。
顺便提一下,这段代码来自Gavin Sinclair的"Ruby Extensions"对象。有了这个方法,我们可以重写上面的代码:
值得花费一分钟来理解它怎样工作。map方法使用一个block作为参数。&符号允许我们传递一个proc而不是一个显式附加的
block。由于我们在一个非proc对象上使用&符号,解释器会尝试调用该对象的to_proc方法。返回的proc替代了显式的block,
map将会对每个元素调用它。为什么self作为一个消息传递给array元素有意义呢?这是因为proc是一个闭包,所以它会记住
它被创建在哪个context里。当它被创建时,self表示调用to_proc的symbol。
symbol就像一个字符串,它表示了一个字符序列。它不像字符串,每个symbol只有一个实例(和Fixnum一样)。因此,有一个内存或
性能问题需要弄清楚。例如,在下面的代码中,"foo"字符串以三个单独的对象存储在内存中,但是symbol :foo作为一个单独的对
象存储(被引用了多次):
array = ["foo", "foo", "foo", :foo, :foo, :foo]
有些人被symbol前面的冒号弄糊涂了。其实没有必要糊涂;这只是一个简单的语法形式。字符串,数组和哈希都有开始和结束界定
符;而symbol只有一个开始界定符。把它当成一个单界定符而不是二元界定符即可。开始时你可能认为这个语法很奇怪,但事实上
没有什么神秘的。
值得注意的是在老版本的Ruby(1.6之前)中,symbol常量不是第一类对象而是转换成Fixnum来存储。现在在内核中这仍然是对的;
symbol对应于一个数字并作为一个immediate value来存储。这个值可以使用to_i来得到,但是没有必要。
根据Jim Weirich,symbol是"有名字的对象"。Austin Ziegler更喜欢说"an object that is a name"。无论怎样,在symbol和名字
间始终有一个一对一的对应。什么样的东西我们需要使用名字?例如变量,方法和任意的常量。
一个常见的symbol使用场景是表示变量或方法的名字。例如,我们知道如果我们想添加一个读/写属性到类中,我们可以这样做:
class SomeClass attr_accessor :whatever end
这等价于:
class SomeClass def whatever @whatever end def whatever=(val) @whatever = val end end
换句话说,:whatever这个symbol告诉attr_accessor方法"getter"和"setter(以及实例变量)都将根据该symbol来给予名字。
你可能想问为什么我们不能使用一个字符串来替代。我们可以。大部分希望使用symbol的核心方法都可以使用字符串来替代。
attr_reader :alpha attr_reader "beta" # This is also legal
事实上,symbol就"像"一个字符串,它对应于一个字符序列。这导致有些人说"a symbol is just an immutalbe string"。
但是,Symbol类并不是继承于String,并且对于字符串典型的操作并不适合symbol。
另一个误解是认为symbol没必要直接对应于标识符。这导致有些人说"the symbol table"(as they would in referring to
an assembled object program)。但是这不是一个真正有用的概念;尽管在内部symbol存储在一种table里,Ruby并没有将
这个table作为一个实体暴露给我们访问,而我们作为编程者也不关心它的存在。
而且,symbol不需要看起来像标识符。虽然它们像标识符,但是它们也可以包含标点,如果它们被引号包围的话。如下也是
合法的Ruby symbol:
sym1 = :"This is a symbol" sym2 = :"This is, too1" sym3 = :")(*&^%$" # and even this
你甚至可以使用这些symbol来定义实例变量和方法,但是这样的话你需要send和instance_variable_get技术来引用它们。
一般来说不推荐使用字符串形式的symbol。
Symbols As Enumerations
Pascal以及后期版本的C等语言有一个enumerated type的概念。Ruby没有这样的东西;Ruby没有类型检查。但是symbol
非常有用;我可以用:north,:south,:east和:west来表示方向。
将这些symbol存储为常量可能更清晰。
North, South, East, West = :north, :south, :east, :west
如果它们是字符串而不是symbol,将它们定义为常量会节省内存,但无论如何每个symbol都只在对象空间里存在一次。
(像Fixnum一样Symbol存储为immediate value)
Symbols As Metavalues
我们经常使用异常来作为避免返回代码的方式。但是如果你宁愿使用返回代码的话也可以。RUby的方法不限于单返回类型,
这让传回"out of band"值成为可能。
我们经常需要这样的值。ASCII NUL字符被认为根本就不是一个字符。C有NULL指针,Pascal有nil指针,SQL有NULL等等。
Ruby当然也有nil。
这些metavalue的问题是它们成为合法的值。现在每个人都认为NUL是一个ASCII字符。在Ruby中,nil不是真的non-object;
它可以被存储和操作。这样我们有了如hash[key]返回nil这样的小烦恼;是因为key没有找到而返回nil,还是由于这个key
真的指向nil?
这里symbol可以用来作为好的metavalue。假设一个方法从忘了攫取一个字符串(可能通过http或其他类似的东西)。我们可以
返回非字符串值来表示出现异常。
str = get_string case str when String # Proceed normally when :eof # end of file, socket closed, whatever when :error # I/O or network error when :timeout # didn't get a reply end
这比使用异常更好或更清晰?没必要。但是记住,这是处理可能为"edge cases"但不一定是异常的条件时的一项技术。
Symbols, Variables, and Methods
可能使用symbol的最知名的地方是定义类的属性:
class MyClass attr_reader :alpha, :beta attr_writer :gamma, :delta attr_accessor :epsilon # ... end
attr_accessor使用symbol名字来觉得实例变量和读写方法的名字。这不代表symbol和实例变量名之间有绝对的关系。
例如,如果你使用instance_variable_set,我们必须指定变量的名字,包括@符号:
sym1 = :@foo sym2 = :foo instance_variable_set(sym1, "str") # Works instance_variable_set(sym2, "str") # errors
简短来说,传递到attr系列方法的symbol只是一个参数,这些方法基于symbol的值创建需要的实例变量和方法。(writer方法
在结尾有一个=,而实例变量名字在前面有一个@。)换句话说,symbol必须与它引用的标识符相对应。
大部分情况下,希望使用symbol的方法也可以使用字符串。相反则不一定正确。
Converting to/from Symbols
字符串和symbol可以使用to_s和to_sym方法自由互换:
a = "foobar" b = :foobar a == b.to_s # true b == a.to_sym # true
如果你做元编程,如下方法有时候可能很有用。
class Symbol def +(other) (self.to_s + other.to_s).to_sym end end
上面的方法允许我们连接symbol(或者添加字符串到一个symbol)。下面是一个使用它的例子;这段微小的代码接收一个symbol并
尝试告诉我们它是否是一个accessor(即,读写方法都存在):
class Object def accessor?(sym) return (self.respond_to?(sym) and self.respond_to?(sym+"=")) end end
我这里要提到一个使用symbol的聪明的方式。当我们做map操作时,有时候一个复杂的block可能附加在后面。但是许多情况下,
我们对每个元素简单的调用一个方法:
list = words.map { |x| x.capitalize }
在这里,似乎我们为完成工作做了太多事情。让我们打开Symbol类并定义to_proc方法。这保证任何symbol都可以强制转换成
一个proc对象。但是我们应该返回什么proc?显然应该根据对象context里的symbol本身。换句话说,proc应该将symbol本身作
为一个消息发送给对象。
def to_proc proc { |obj, *args| obj.send(self, *args) } end
顺便提一下,这段代码来自Gavin Sinclair的"Ruby Extensions"对象。有了这个方法,我们可以重写上面的代码:
list = words.map(&:capitalize)
值得花费一分钟来理解它怎样工作。map方法使用一个block作为参数。&符号允许我们传递一个proc而不是一个显式附加的
block。由于我们在一个非proc对象上使用&符号,解释器会尝试调用该对象的to_proc方法。返回的proc替代了显式的block,
map将会对每个元素调用它。为什么self作为一个消息传递给array元素有意义呢?这是因为proc是一个闭包,所以它会记住
它被创建在哪个context里。当它被创建时,self表示调用to_proc的symbol。
10 楼
liusong1111
2008-05-09
居然还没锁贴,再补充一下。
Rails给Hash类做了扩展,加了一个实例方法with_indifferent_access,所做的就是我前面贴的期望自己封装的Hash#to_indiff要做的。源码是:
这样用:
另外,为什么HashWithIndifferentAccess在内部将输入的String或Symbol的key统一当成String存储呢?为什么不统一用Symbol?后者性能不更好吗?
原因在于,ruby1.8中Symbol不会被垃圾收集(1.9解决了),而这个类经常用于封装用户输入数据,比如params返回的就是它的一个实例。恶意用户通过发送大量key值每次各不相同query string,就可能使服务器端内存占用居高不下甚至耗尽。
Rails给Hash类做了扩展,加了一个实例方法with_indifferent_access,所做的就是我前面贴的期望自己封装的Hash#to_indiff要做的。源码是:
def with_indifferent_access hash = HashWithIndifferentAccess.new(self) hash.default = self.default hash end
这样用:
{:a => 1,'b' => 2}.with_indifferent_access #注意用它的返回值,其本身没有修改
另外,为什么HashWithIndifferentAccess在内部将输入的String或Symbol的key统一当成String存储呢?为什么不统一用Symbol?后者性能不更好吗?
原因在于,ruby1.8中Symbol不会被垃圾收集(1.9解决了),而这个类经常用于封装用户输入数据,比如params返回的就是它的一个实例。恶意用户通过发送大量key值每次各不相同query string,就可能使服务器端内存占用居高不下甚至耗尽。
9 楼
ghostv1
2007-12-13
不错,赞一个
8 楼
pure
2007-11-20
写的很好
很受益~
很受益~
7 楼
haiyang
2007-11-05
不错,hideto和liusong的总结很精辟。
6 楼
liusong1111
2007-11-04
从实用角度看,在一些场景下Symbol好过String只有两点:节省内存,表达简洁。
而把两者强制拆开,既有额外好处也带来不便。
好处是充分利用两者的不同进行差异处理,如上面举的异常处理/when的用法。
但不便之处也不少,因为很多情况下需要无区别化对待两者,rails中就大量采用了这种风格,使用者无须担心
attr_accessor :abc 和 attr_accessor 'abc'有什么区别,layout 'main'和layout :main有什么区别(当然,跟layout nil和layout false还是有区别的,一点机智和诡异)。
当用户传过的东东作为Hash的key时,两者的不同让人烦死。
比如,我在每个model里声明一些字段的默认值:
在controller里
请注意controller里的merge,假定页面没有传入params[:person][:age],则新建的person的age取默认值30.
那么,当页面传了age参数为40呢?按理merge后age应该为40,事实却不总正确。因为params里的key都是以String存储的,而我的DEFAULTS的key是Symbol,则merge后的结果是
最终save!以哪个为准,天知道~
rails实现了名为HashWithIndifferentAccess的类(继承自Hash),就是为了解决这一问题。无论开发者传过来的是String还是Symbol(作为key),它都会把预先统一转化成String进行存取,以实现无差别化对待。细心的人可能已察觉,既然params里的内容都是以String作为Key,为啥还可以params[:person]这样访问,奥秘就是用了这个类。它的源码在gems/activesupport-x.x.x/lib/active_support/core_ext/hash/indifferent_access.rb
所以,我上面的model要改成:
即使有这个类,也让人呕吐不止。曾想对它简单封装,提供Hash#to_indiff,仍不满意,不过,注意这个差别并有意避免仍是当前能做到的。
ruby1.9已经把Symbol作为String的子类实现了,并去除了Symbol#to_int,虽然没有百分之百确定出现在ruby2.0里,还好离解放不远,这样从语言角度两者的边界就更清晰了,"Goodbye, HashWithIndifferentAccess."
:symbol.is_a? String
http://redhanded.hobix.com/inspect/SymbolIs_aString.html
让人绝倒的理由之一:
Smalltalk’s symbols are a subclass of string. (He adds that this is his most motivating reason to do it.)
而把两者强制拆开,既有额外好处也带来不便。
好处是充分利用两者的不同进行差异处理,如上面举的异常处理/when的用法。
但不便之处也不少,因为很多情况下需要无区别化对待两者,rails中就大量采用了这种风格,使用者无须担心
attr_accessor :abc 和 attr_accessor 'abc'有什么区别,layout 'main'和layout :main有什么区别(当然,跟layout nil和layout false还是有区别的,一点机智和诡异)。
当用户传过的东东作为Hash的key时,两者的不同让人烦死。
比如,我在每个model里声明一些字段的默认值:
class Person < ActiveRecord::Base DEFAULTS = { :age => 30 } end
在controller里
class PersonController < ActiveController::Base def create person = Person.new(Person::DEFAULTS.merge(params[:person])) person.save! end end
请注意controller里的merge,假定页面没有传入params[:person][:age],则新建的person的age取默认值30.
那么,当页面传了age参数为40呢?按理merge后age应该为40,事实却不总正确。因为params里的key都是以String存储的,而我的DEFAULTS的key是Symbol,则merge后的结果是
{ :age => 30, "age" => 40 }
最终save!以哪个为准,天知道~
rails实现了名为HashWithIndifferentAccess的类(继承自Hash),就是为了解决这一问题。无论开发者传过来的是String还是Symbol(作为key),它都会把预先统一转化成String进行存取,以实现无差别化对待。细心的人可能已察觉,既然params里的内容都是以String作为Key,为啥还可以params[:person]这样访问,奥秘就是用了这个类。它的源码在gems/activesupport-x.x.x/lib/active_support/core_ext/hash/indifferent_access.rb
所以,我上面的model要改成:
class Person < ActiveRecord::Base DEFAULTS = HashWithIndifferentAccess.new({ :age => 30 }) end
即使有这个类,也让人呕吐不止。曾想对它简单封装,提供Hash#to_indiff,仍不满意,不过,注意这个差别并有意避免仍是当前能做到的。
ruby1.9已经把Symbol作为String的子类实现了,并去除了Symbol#to_int,虽然没有百分之百确定出现在ruby2.0里,还好离解放不远,这样从语言角度两者的边界就更清晰了,"Goodbye, HashWithIndifferentAccess."
:symbol.is_a? String
http://redhanded.hobix.com/inspect/SymbolIs_aString.html
让人绝倒的理由之一:
引用
Smalltalk’s symbols are a subclass of string. (He adds that this is his most motivating reason to do it.)
5 楼
mnd
2007-11-04
写的很好,感谢楼主,期待更多的文章
4 楼
hideto
2007-08-08
@jonlove
方法名应该是to_s,笔误。
方法名应该是to_s,笔误。
3 楼
jonlove
2007-08-08
字符串和symbol可以使用to_str和to_sym方法自由互换
我用irb的时候出显的错误:
我用irb的时候出显的错误:
irb(main):007:0> a == b.to_str NoMethodError: underfind method 'to_str' for :foobar:Symbol form(irb):7
2 楼
9esuLuciano
2007-08-07
解释的很清楚,感谢,收藏了
1 楼
rainchen
2007-08-07
有人说,为了提速" Don't symbolize keys":
http://cfis.savagexi.com/articles/2007/07/18/making-rails-go-vroom
是不是内存与CPU间要做个取舍?
对最后一点,有人说Symbol#to_proc比显式的proc慢:http://blog.zenspider.com/archives/2007/07/argh_stop_being_clever.html
但似乎在ruby1.9里修正了
http://cfis.savagexi.com/articles/2007/07/18/making-rails-go-vroom
是不是内存与CPU间要做个取舍?
对最后一点,有人说Symbol#to_proc比显式的proc慢:http://blog.zenspider.com/archives/2007/07/argh_stop_being_clever.html
但似乎在ruby1.9里修正了
发表评论
-
用了TextMate才知道什么叫神级Editor
2011-03-09 04:51 57864一直用Eclipse作为开发Ruby和Java项目的IDE,但 ... -
Ruby使用OAuth登录新浪微博和豆瓣
2011-01-09 12:49 4307首先需要安装oauth这个gem包 gem install ... -
使用Passenger+nginx部署Rails
2010-12-28 15:12 49211. Install Passender gem instal ... -
markItUp+rdiscount搭建Rails下可视化Markdown编辑器
2010-12-21 17:48 5375markItUp是基于jQuery的可视化编辑器,支持Html ... -
Rails3 and MongoDB Quick Guide
2010-12-10 14:13 2717Install MongoDB Download: http: ... -
基于ruby-protobuf的rpc示例
2009-08-11 11:51 41101, 安装ruby-protobuf gem instal ... -
Ruby导出xls和csv的utf-8问题的解决
2009-02-04 15:05 6746数据库数据为utf-8格式,包括中文和拉丁文等等 导出文件xl ... -
URL/HTML/JavaScript的encode/escape
2009-01-04 13:03 9235最近经常被URL、HTML、JavaScript的encode ... -
各种排序的Ruby实现
2008-11-27 14:51 3954Θ(n^2) 1, Bubble sort def bu ... -
12月5日北京RoR活动!
2008-11-26 18:38 2967又是一年过去了,Rails在国内的发展势态良好,很多使用RoR ... -
Rails程序开发的最大问题是代码规范
2008-08-28 11:56 5279使用Rails开发大型复杂B2B应用一年了,这个项目目前开发人 ... -
Web开发大全:ROR版——推荐序
2008-07-09 00:39 2376来自http://www.beyondrails.com/bl ... -
深入ActionMailer,使用Sendmail发邮件
2008-07-03 11:41 3366来自: http://www.beyondrails.com/ ... -
Rails里如何结合ExceptionNotification配置gmail账户发邮件
2008-06-19 19:56 30151,安装ExceptionNotification rub ... -
使用coderay和railscasts样式进行代码高亮
2008-06-17 00:16 2359CodeRay是一个语法高亮的Ruby库,效率很不错。 Cod ... -
Capistrano试用
2008-06-16 19:05 19071,客户端机器安装Capistrano gem insta ... -
lighttpd真垃圾啊
2008-06-04 18:38 2461使用lighttpd+fcgi跑Rails程序,文件上传会si ... -
将gem变成plugin
2008-06-04 11:27 1762有什么样的需求就有什么样的对策 当vhost上的帐号没有ge ... -
在Rails里使用ReCaptcha添加验证码
2008-06-03 15:51 42121,去http://recaptcha.net/sign up ... -
Rails里给文件上传添加progress_bar
2008-05-27 17:00 2054文件上传很慢时,UI没有什么用户提示,这样让人很费解,所以我们 ...
相关推荐
解释的不错,应该明确了不少 ruby symbol详解 起因 最近在学习ruby on rails,的确是一个优秀的数据库开发框架。但在过程中,发现在视图文件夹中的rhtml文件里有大量的类似于以下的语句: <td><%= link_...
ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码
Mail - 一个Ruby邮件库
Yard,是一款 Ruby 文档工具。使用它,你可以在为你的 Ruby app 写文档时预览你的代码。它拥有简单的定制模板,支持你自己的 DSL,并有大量优秀的扩展,而且每天都在增加。
一个Ruby的例子
ruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ...
完整书名《Ruby Programming-向Ruby之父学程序设计》 ,就是那本经典的绿皮书 第一部分:通过简单的Ruby程序来介绍程序的基本架构。 第二部分:介绍基础语法规则,以及类、模块等面向对象程序设计的思考方法与...
[Ruby.Programming_向Ruby之父学程序设计(第2版)].(日)高桥征义,(日)后藤裕藏.扫描版(ED2000.COM).pdf ) 带书签
Puma - 一个Ruby的并发Web服务器
Raven是Sentry的一个Ruby客户端
ruby2ruby 提供一些用来根据 RubyParser 兼容的 Sexps 轻松生成纯 Ruby 代码的方法。可在 Ruby 中轻松实现动态语言处理。 标签:ruby2ruby
《Ruby完全自学手册》是一本完全覆盖Ruby和Ruby on Rails的完全自学手册。《Ruby完全自学手册》的特色是由浅入深、循序渐进,注重理论和实践的结合。虽然定位为入门手册,但是依然涉及许多高级技术和应用,覆盖到的...
Ruby编程,Ruby编程,Ruby编程,Ruby编程,Ruby编程,
ruby源代码 ruby源代码 ruby源代码 ruby源代码2
Money - 一个Ruby库来处理货币和货币转换
ruby源代码 ruby源代码 ruby源代码 ruby源代码4
ruby-git, ruby/Git是一个 ruby 库,可以通过将系统调用包装到Git二进制文件来创建读取和操作Git存储库 用于 ruby的 Git库在 ruby 中使用Git的库。主页项目源代码的Git public 位于:...
redis-rb - Redis的一个Ruby客户端库,试图一对一匹配 Redis的API
LightIO是一个ruby网络库,它结合了ruby fiber和快速IO event loop
Savon是一个Ruby编程语言的SOAP客户端