`
rubynroll
  • 浏览: 202118 次
  • 性别: Icon_minigender_1
  • 来自: Wgt
社区版块
存档分类
最新评论

一个有趣的问题: 如何获取引用名?

阅读更多
我们知道, 对于
 
a = 100

这样的一条语句, a是一个指向 "100" 这个对象的引用. 那么, 如何根据a得到它的名字"a"或者符号:a ?


我现在实现了一个'swap'函数,它的作用是交换两个变量的值, 由于Ruby没有类似C的'指针',所以这个swap实现起来还真有点麻烦:

a = 100
b = 200
def swap(x, y, &block)
  bind = block.binding
  vx = eval("lambda { #{x} }", bind).call
  vy = eval("lambda { #{y} }", bind).call
  eval("lambda {|v| #{y.to_s} = v }", bind).call(vx)
  eval("lambda {|v| #{x.to_s} = v }", bind).call(vy)
end

puts "a = #{a}, b = #{b}"

swap(:a, :b){}

puts "a = #{a}, b = #{b}"



好了, 这个swap有两个缺陷:

1) 为了获取caller's binding, 需要带一个空的闭包. 不过这个问题好解决, rails中有Binding.of_caller的实现,用它就可以省去那个空闭包.

2) 为了获取待交换的变量名, 传入swap的参数不能是a,b本身,而需要对应的symbol或string, 看起来有点别扭. 如果存在一个函数get_ref_name(x)返回x的名字, 那么问题就解决了.

那么, get_ref_name 存在么? 该如何实现?


(注: 不要告诉我用a,b = b,a来实现变量交换, 这个不是要讨论的问题)





分享到:
评论
10 楼 rubynroll 2008-08-05  
baryon 写道

>(注: 不要告诉我用a,b = b,a来实现变量交换, 这个不是要讨论的问题)

不好意思,a,b = b,a同你的实现有何不同,望赐教



如果把swap看作是'宏', 那么a,b = b,a就是这个宏的展开.

由于ruby没有提供'宏',所以就只能想办法获取caller的所有信息来模拟它.

liusong1111提供的ParseTree估计是一个正确的方向,有时间去研究一下....
9 楼 sunfengcheng 2008-07-29  
有的时候,代码是逻辑,有的时候代码是复制,其实最后代码编写应该是哲学与美学。我们的日本工程师就是这方面的天才
8 楼 baryon 2008-07-28  

>(注: 不要告诉我用a,b = b,a来实现变量交换, 这个不是要讨论的问题)

不好意思,a,b = b,a同你的实现有何不同,望赐教
7 楼 xiaoxizhen 2008-07-25  
a = 100
get_ref_name(a)
传递的是指向100的引用,跟a一点关系都没有,
怎么可能取到a呢。

除了判断值相等,没法判断传的是什么。
如果判断值相等,返回的也只能是数组。
真想知道问GC吧。
6 楼 liusong1111 2008-07-25  
use powser of ParseTree?
need to wrap magic code in a method or block.
maybe you guys heard it long time ago, while I guess ParseTree will be the next big thing for ruby.




5 楼 rubynroll 2008-07-25  
Quake Wang 写道
我实在想不出获取变量名的实际用途是什么?
如果是为了类似指针方式获取值,ruby有提供ObjectSpace._id2ref


要说到用处么, 有了它就可以实现类似'宏'的功能, 也有可能对有些meta trick有用处吧. 顺便也看看ruby对代码自省到什么程度, 呵呵~
4 楼 QuakeWang 2008-07-25  
我实在想不出获取变量名的实际用途是什么?
如果是为了类似指针方式获取值,ruby有提供ObjectSpace._id2ref
3 楼 rubynroll 2008-07-25  
<div class='quote_title'>dennis_zane 写道</div>
<div class='quote_div'>
<p>我的一个实现,比较丑陋,通过查找local_variables</p>
<p> </p>
<pre name='code' class='ruby'>a=100
b=200
class Test
  attr_accessor :name
end
def get_ref_name(x,vars,b)
  vars.each do |var|
    begin
      return var if eval("#{var}", b) == x  and var!='x'
    rescue
    end
  end
end
c=Test.new
puts get_ref_name(a,local_variables,binding)
puts get_ref_name(c,local_variables,binding)</pre>
 
<p> </p>
</div>
<p> </p>
<p>用local_variables还是有很大局限性, 例如:</p>
<pre name='code' class='ruby'>a = 100
b = 200
c = a</pre>
<p> 这时</p>
<pre name='code' class='ruby'>eval("#{var}", b) == x</pre>
<p> 这句对局部变量a和c都成立, 因为'=='操作符比较的是值.</p>
<p> </p>
<p>另外,还要挖空心思去给'x'取个特别的名字,要不然 var != 'x' 也很容易被击中.</p>
<p> </p>
<p> </p>
<p>很遗憾的是Kernel#caller没有提供参数列表信息,否则这个问题就好解决了.</p>
<p> </p>
2 楼 ye_jian_hui 2008-07-24  
在ruby层面只能用local_variables来实现了
1 楼 dennis_zane 2008-07-24  
<p>我的一个实现,比较丑陋,通过查找local_variables</p>
<p> </p>
<pre name='code' class='ruby'>a=100
b=200
class Test
  attr_accessor :name
end
def get_ref_name(x,vars,b)
  vars.each do |var|
    begin
      return var if eval("#{var}",b)==x and var!='x'
    rescue
    end
  end
end
c=Test.new
puts get_ref_name(a,local_variables,binding)
puts get_ref_name(c,local_variables,binding)</pre>
 
<p> </p>

相关推荐

    jquery插件使用方法大全

    用jq的前提,首先要引用一个有jq的文件 [removed][removed] 这个是jquery官方最新的地址。可用在自己网站里加个这个,就能使用jquery了。 但仍然建议下载到本地服务器上。 编辑本段找到你了!  在编写js库代码时候...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    21.11 一个有趣的依赖性问题 21.12 手动监视和控制对象的生存期 21.13 对象复活 21.14 代 21.15 用于本地资源的其他垃圾回收功能 21.16 预测需求大量内存的操作能否成功 21.17 编程控制垃圾回收器 21.18 ...

    CLR.via.C#.(中文第3版)(自制详细书签)

    21.11 一个有趣的依赖性问题 21.12 手动监视和控制对象的生存期 21.13 对象复活 21.14 代 21.15 用于本地资源的其他垃圾回收功能 21.16 预测需求大量内存的操作能否成功 21.17 编程控制垃圾回收器 21.18 线程...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    21.11 一个有趣的依赖性问题 21.12 手动监视和控制对象的生存期 21.13 对象复活 21.14 代 21.15 用于本地资源的其他垃圾回收功能 21.16 预测需求大量内存的操作能否成功 21.17 编程控制垃圾回收器 21.18 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    21.11 一个有趣的依赖性问题 21.12 手动监视和控制对象的生存期 21.13 对象复活 21.14 代 21.15 用于本地资源的其他垃圾回收功能 21.16 预测需求大量内存的操作能否成功 21.17 编程控制垃圾回收器 21.18 ...

    JAVA上百实例源码以及开源项目

    创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口函数得到远程接口的引用,用远程接口的...

    JAVA上百实例源码以及开源项目源代码

    创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口函数得到远程接口的引用,用远程接口的...

    C#微软培训资料

    第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型...

    PERL语言编程

    如果你碰上一个 Perl 社区解决不了的问题,那你也还有最后的一招:源程序本身。 Perl 社区不会在“升级”的伪装下租给你它们的商业秘密。而且 Perl 社区也不会“停业 ”,更不会让你孤立无援。 &lt;br/&gt;Perl 是...

    亮剑.NET深入体验与实战精要2

    读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集实用性、思想性、趣味性于一体,内容共分为技术基础总结、系统架构设计思想及项目实战解析三部分,随书所附光盘收录大量实例...

    亮剑.NET深入体验与实战精要3

    读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集实用性、思想性、趣味性于一体,内容共分为技术基础总结、系统架构设计思想及项目实战解析三部分,随书所附光盘收录大量实例...

    Detrumpify-crx插件

    用更准确的描述替换对唐纳德...在一个文件中有多个搜索/替换组合1.1.5-修复了王牌正则表达式以避免转换基于王牌的新词-重写替换部分以允许格式化新的替换块-添加任意引用的功能-清单更改以帮助阻止XHR / CSP问题( 1.1.

Global site tag (gtag.js) - Google Analytics