`
simohayha
  • 浏览: 1403613 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

ruby way之Symbols

    博客分类:
  • ruby
阅读更多
1 symbols简介

在ruby中一个symbol就是一个Symbol类的实例,他的语法也就是简单的一个冒号后面跟着一个声明.

一个symbol就像一个字符串,可是它和字符串所不同的是每一个symbol都只有一个实例。我们举个例子:

array = ["foo", "foo", "foo", :foo, :foo, :foo]


在这个例子中字符串"foo"在内存里面被存储为3个不同的对象,而:foo则是被存储为一个对象,只不过是多个引用而已。

在ruby1.6之前的版本,一个symbol不是一个first-class 的对象,他是被传递给一个Fixnum ,然后再存储起来。在现在的版本中,内部仍然是这么实现的,一个symbol表示为一个数字然后被存储。这个数字可以用to_i来得到。

在这里一个symbol和他的名字之间有了一个一一对应的关系,我们操作他就像操作其他东西一样.

symbol经常使用到的地方就是表示一个变量或者一个方法,例如如果我们想要加一个读写方法给一个类中的变量我们能这么做:

class SomeClass
  attr_accessor :whatever
end

他和下面的代码是等价的:

class SomeClass
  def whatever
    @whatever
  end
  def whatever=(val)
    @whatever = val
  end
end


这里你可能要问为什么要用symbol而不是用string。其实这里也就是一个习惯了。大部分使用symbol的地方都能用字符串来代替。

一个symbol像是一个字符串,这导致很多人说,symbol就是一个不可变得字符串。这个观点非常错误,因为Symbol并没有从String类继承什么东西。并且很多典型的操作符只能用用于字符串,而不能用于symbol。

另外一个误会是symbols能够直接联系到他的标识符,这导致很多人在讨论the symbol table。可是这是没有意义的,因为尽管symbols在内部是有一个table,可是那个表对于外部程序来说是不可见的,我们并不能访问它。

一个symbols并不需要看起来像是一个标识符:
sym1 = :"This is a symbol"
sym2 = :"This is, too!"
sym3 = :")(*&^%$"            # and even this


你可能使用symbols来定义实例变量和方法,这时你就需要使用诸如send and instance_variable_get 这样的方法来操作他们。这种情况下,不建议你使用字符串。

2 作为枚举的symbol

象pascal和c这样的语言提供了枚举类型。ruby没有真正意义上的这个东西。我么能够使用symbols来模拟这个东西:

North, South, East, West = :north, :south, :east, :west


虽然这边还可以使用string,可是一个symbol只有一个变量,使我们选择symbol更合理

3 symbol作为一个Metavalues

经常我们使用异常来代替使用返回码。我们经常需要一些值来作为错误时的返回值(比如nil),例如asc字符NUL被认为不是一个字符,c有空指针,pascal也有nil指针,ruby也有nil。

可是问题来了,在ruby中nil不是一个真正的 非对象,它能被存储和操作,比如我们有一个has[key]=nil.当我们调用这个返回时,我们不知道是真的返回nil,还是说出错没有找到key所以返回nil。

这个时候,我们能使用symbol:

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

这个代码一定就比使用异常更清晰和更聪明吗,不一定这个方法只是说能让你保持在你的脑子里就行了。

4 symbol,变量和方法

可能最广为人知的使用symbol就是在一个类里面定义一个属性:

class MyClass
  attr_reader :alpha, :beta
  attr_writer :gamma, :delta
  attr_accessor :epsilon
  # ...
end


attr_accessor使用symbol来表示实例的名字和读写方法的名字。可是这并不意味着实例的名字和symbol之间有什么联系请看例子:

sym1 = :@foo
sym2 = :foo
instance_variable_set(sym1,"str")   # Works
instance_variable_set(sym2,"str")   # 出错


简而言之,一个symbol只是作为一个参数给atrr之类的方法,这些方法,基于symbol的值来创建实例变量和方法(写方法结尾有一个=,实例变量前面加上@)。因此symbol之和它的引用标记之间有联系。

5 symbols的转换

字符串和symbols之间的转换使用to_s和to_sym方法:

a = "foobar"
b = :foobar
puts a == b.to_s   # true
puts b == a.to_sym    # true 


如果你正在使用元编程(metaprogramming),那么接下来的方法有时会非常有用:

class Symbol
  def +(other)
    (self.to_s + other.to_s).to_sym
  end
end


+方法使我们能够连接两个symbol。接下来就是使用他的例子。accessor方法接受一个symbol为参数,并测试它是否含有读写方法:

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呢?显然,有两个参数,一个是对象上下文中的symbol自身。也就是将symbol他自己作为一个消息传递给的那个对象:
def to_proc
  proc {|obj, *args| obj.send(self, *args) }
end


这个代码,来自于Gavin Sinclair的Ruby Extensions工程。现在我们能够重写我们上面的代码了:
list = words.map(&:capitalize)


花时间理解这段代码是很有意义的。map方法接受一个block为参数。这里将一个不是proc的类传递给block,这时解释器会自动调用to_proc方法,来将symbol转换成一个block。然后返回proc,这时map会为他的每一个参数调用它。为什么self作为一个消息传递给数组是正确的呢?那是因为proc是一个闭包,它能够记忆他被创建时的上下文环境。当他被创建时self指向的就是to_proc被创建时的那个symbol。






分享到:
评论

相关推荐

    SF Symbols.7z

    当你使用windows系统设计、开发苹果APP时,你需要准确的使用苹果的特定字体SF-Symbols,以便预览最佳视觉效果。 此SF-Symbols资源由苹果官方文件中提出的纯净Fonts字体文件,不含其他苹果系统的辅助配置。 SF-...

    ABAP FIELD-SYMBOLS 学习资料

    如果 `<s>` 中没有I型(整数)或F型(浮点数)字段,那么 `<f>` 的定义长度应大于等于 `<s>` 中所有字段长度之和,否则会引发语法错误。 - b. 当 `<s>` 包含I型或F型字段时,推荐 `<f>` 为结构类型,且结构应与 `...

    Ruby Pocket Reference.pdf

    符号(Symbols)在 Ruby 中是一种非常有用的资源,常用于提高性能和代码可读性。它们是不可变且唯一的对象标识。 #### 预定义变量和伪变量 预定义变量(Predefined Variables)和伪变量(Pseudovariables)在 Ruby...

    Node.js-log-symbols-为各种日志级别提供着色的符号

    `log-symbols` 是一个非常有用的模块,专为命令行环境设计,提供了各种颜色鲜明的日志级别符号,使得日志输出更易读、更直观。 `log-symbols` 模块的主要功能在于它为常见的日志级别(如信息、警告、错误等)提供了...

    windows 7 debug symbols 32位 64位 sp1的symbols是另一个文件

    windows 7 debug symbols 不含win7 sp1的symbol If you plan to install symbols manually, it is crucial that you remember this basic rule: the symbol files on the host computer are required to match the...

    winxp符号文件包完整(symbols)

    在Windows XP系统中,开发和调试驱动程序是一个关键任务,而符号文件(Symbols)在此过程中起着至关重要的作用。符号文件(.pdb 文件)包含了操作系统、应用程序或驱动程序的调试信息,如变量名、函数名、行号等,...

    Ruby on Rails入门经典代码

    - Symbols:不可变对象,常用于方法参数、哈希键等,以提高效率。 - Mixins:Ruby的模块系统允许类间共享代码,实现类似多重继承的功能。 3. **Rails生成器**: - `rails new`:创建新Rails项目。 - `generate ...

    could not read symbols: Bad value

    "could not read symbols: Bad value" 问题解决方案 本文将详细介绍在 64 位 Linux 系统下出现的 "could not read symbols: Bad value" 问题,并提供解决方案。 问题描述 -------- 在 64 位 Linux 系统下编译 ...

    windows xp sp3 symbols full enu

    windows xp sp3 的symbols 包 。WindowsXP-KB936929-SP3-x86-symbols-full-ENU。 找了半天,没找到中文版的符号包,只找到英文版的,不过可以用。然后这个是full版的。

    wps-font-symbols.zip

    该压缩包名为"wps-font-symbols.zip",内含文件为"wps-font-symbols-master",这通常意味着这是一个包含WPS字体符号的源代码或资源库。下面我们将深入探讨WPS字体符号的使用和重要性,以及如何通过这个资源包来优化...

    Android代码-symbols

    Symbols Symbols is a Java library to generate static strings constants for attribute names using annotation processor. Tell me more In some cases, in Java (ex: when using reflection methods) we need ...

    windows的symbols文件

    在Windows操作系统中,调试符号(Symbols)是程序员和系统管理员在进行系统级调试时不可或缺的资源。这些符号文件,通常以PDB(Program Database)格式存在,提供了关于系统组件、驱动程序和其他二进制文件的详细元...

    Atom-atom-symbols-view-plus,原子/符号的替代品.zip

    Atom-atom-symbols-view-plus是基于Atom文本编辑器的一个扩展插件,它的主要功能是对原生的`atom/symbols-view`进行增强,提供更高效、更便捷的代码符号浏览体验。Atom是一个由GitHub开发的开源文本编辑器,它利用了...

    LaTeX-symbols.zip

    "LaTeX-symbols.zip"这个压缩包包含了两个关于LaTeX符号的重要资源,对于学习和使用LaTeX的人来说是不可或缺的参考资料。 首先,"symbols-a4.pdf"是这份资料的主要部分,它是一个长达300多页的PDF文档,详尽地列出...

    sketch-batch-create-symbols, 用于将选定图层转换为单个符号的插件插件.zip

    sketch-batch-create-symbols, 用于将选定图层转换为单个符号的插件插件 概述在草图中,当你有一些需要转换为符号的图层时,必须一个选择它们并使用'转换为符号'函数。 多个选择将合并为一个符号。这里插入将为当前...

    Ruby袖珍参考手册

    Symbols(符号)** - 符号是以冒号开头的标识符,例如`:symbol`。它们类似于字符串但更轻量级,不会被重复创建。 #### 三、进阶内容 **1. Predefined Variables(预定义变量)** - Ruby中有一系列预定义的变量...

    Ruby.Pocket.Reference

    ### Ruby Pocket Reference: Key IT Knowledge Points #### Title and Description Overview The title "Ruby Pocket Reference" and the description "Ruby.Pocket.Reference.Jul.2007 learning ruby 的 can ...

    Window xp sp3 调试符号(symbols)更新包

    Window xp sp3 调试符号(symbols)更新包

    xpSP3Symbols zip易解压版

    有些电脑WindowsXP-KB936929-SP3-x86-symbols-full-ENU.exe无法自解压,可能是系统盗版啦,或者计数器已经出现问题,本来就是用来调试麻,所以上传一个我解压好了(880MB)再zip压缩的,方便那些苦难的人。

Global site tag (gtag.js) - Google Analytics