理解Ruby中的标志(Understanding Ruby Symbols)

翻译 2006年06月24日 20:46:00
理解Ruby中的标志(Understanding Ruby Symbols)
原文出处:http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols
翻译:Suninny AT Gmail.com

标志在Ruby中是一个迷。我们用她,但多数人并不真正懂她。
什么是标志?
简单来说,标志是你用来代表名字或字符串的一个东西。这可以归结为一种高效的描述名--产生单一的字符串用于每个命名实例,这样就节省了空间。
琼斯博士的案例
琼斯博士(Dr Jones)是个心理学家。 他通常使用语词联想试验诊断患者,并且使用Ruby记录一切。 他的第一名患者Why来到了这里:

Dr J: Red
Why : Ruby
Dr J: Transportation
Why : Rails
Dr J: Chunky
Why : Bacon

琼斯博士建立一个散列来存储这些数据:

 why = {"red" => "ruby", "transportation" => "rails", "chunky" => "bacon"}

问题所在

在进行几百个语词联想试验之后,琼斯博士开始意识到他用尽了内存! 于是琼斯在irb进行测试:

> patient1 = { "ruby" => "red" }
> patient2 = { "ruby" => "programming" }
> patient1.each_key {|key| puts key.object_id.to_s}
211006
> patient2.each_key {|key| puts key.object_id.to_s}
203536

我们看到,每次他建立一个散列来存储信息,Ruby就在不同的内存位置为每个键建立了一个新的字符串对象。

幸运的是,我们还有其他的方法。

用标志来突围

不同于字符串,在一个Ruby会话期间,同一个名称的标志只作一次初始化然后就存在于内存中。当你需要重用字符串来表示其他东西时,标志是再适合不过的了。重做琼斯博士的测试,我们能直接观察到:

> patient1 = { :ruby => "red" }
> patient2 = { :ruby => "programming" }
> patient1.each_key {|key| puts key.object_id.to_s}
3918094
> patient2.each_key {|key| puts key.object_id.to_s}
3918094

通过使用标志,在语词联想试验中我们用单一的内存地址代表了“ruby”这个单词。随着时间的推移,这能节省下大量的空间。
标志的其他应用场合
无论何时,只要你是重用一个单词来反复代表其他东西,标志就能派上用场。不管是散列中的一个键,还是Http查询中的一个方法。在最新、最伟大的Web框架--Ruby on Rails的路由和链接中就应用到了标志。

在表现一个网页之前,Rails会执行框架内部的控制器(controllers)中定义的动作(actions),因此在Rails中,链接就像这样表示:

link_to("View Article", :controller => "articles", :action => "show", :id => 1)

当一个应用可能至少有数百个链接,或者说有数百个不同动作和控制器的引用时,使用标志就比使用字符串高效得多。

最后,值得注意的是标志的应用场合并不局限于散列中的键。例如,如果你写一个Http客户端(或服务器),在这个程序中,可能需要多次用到get和post:

do_this if query == :get

...
send_message_to_server(:post,filename)

当需要反复用到一个字符串时,标志或许是一个蛮不错的替代品。

更新
在Freenode(译注:一个著名的IRC服务器)的ruby-lang频道,Aria和Nome为这篇文章给出了有用的增补。

11:58 < Aria> 同样,即便完全出于现实方面的考虑,使用标志也很理想:如果你要引用一个方法名,就用标志吧,因为她总会在那里(在定义了方法之后)。
12:03 < nome> Kevin Clark:标志的目的是用来辨别构造(主要是用户级的):散列中的槽、一个方法、一个选项等等。

同样,Aria还回应了Geoff在注解中提出的问题:

Geoff:我很想知道1000个字符串"red"究竟要比:red耗费多少内存。记住,在Rails之外,"red" != :red

Aria:多少内存?20字节/对象,加上存储数据的3个字节,再加上存储长度的4个字节,一共是27×1000=27000个字节。与此相对,标志表条目的一份拷贝,只需几个字节。

Jim Weirich 写到:
我通常有下面的法则来比较字符串和标志:
(1) 如果侧重于对象的内容(即字符序列),就用字符串;
(2) 如果侧重于对象的身份,就用标志。

相关文章推荐

Understanding nil?, empty? and blank? in Ruby and Rails

When first learning Ruby and Rails, I often used the methods nil?, empty? and blank? incorrectly. Th...

Understanding Ruby Blocks, Procs and Lambdas

Understanding Ruby Blocks, Procs and Lambdas Blocks, Procs and lambdas (referred to as closures i...

Ruby+Watir经验谈: Understanding Watir

使用Watire,主要通过是使用Watir::IE的一个实例来获得页面上的各种元素,比如button,link...,然后你可以对这些元素进行操作,比如点击一个button,点击一个link... ...

读书笔记之《七周七语言——理解多种编程范型》Ruby语言学习

正如此书中简介所介绍的一样,作为一个程序员,想要提高自己的编程水平,学习了解各种编程语言是一个很有效的途径。通过吸收各种语言的精髓融入到自己最熟悉的语言代码中去。也许你只是一个Objective-c程...

Ruby中“||=”符号理解

def current_user @current_user ||= session[:user_id] && User.find(session[:user_id]) end 短短...

深入理解 Ruby 关键字 yiald

yield 这个关键字所传达的东西,这也是ruby比较有特色的一个地方 在函数里面的有一条yield语句,到时候执行的时候可以执行函数类外的block。而且这个block可以有自己的context...
  • laxse
  • laxse
  • 2016-10-17 01:08
  • 92

理解ruby中的yield的概念

完美理解ruby中的yield的概念 分类: 转帖 2012-05-26 13:29 10人阅读 评论(0) 收藏 举报 地址:http://www.cnitblog.com...

Ruby中“||=”符号理解

def current_user @current_user ||= session[:user_id] && User.find(session[:user_id]) end短短一行代码,却...

Ruby module和class的理解分析

一个class就是一系列方法的集合,这些方法将操作对象的状态(即对象的实例变量) module.rb: require './project' #require porject.rb...

理解Ruby的4种闭包:blocks, Procs, lambdas 和 Methods

blocks, Procs, Methods, lambdas(也称闭包)是Ruby中最强大的一部分,用过你就会知道,同时也是最容易迷惑的。 这可能是因为Ruby处理闭包的方式有点怪。更甚的是,Ru...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)