`
biyeah
  • 浏览: 203301 次
  • 来自: ...
社区版块
存档分类
最新评论

[转]eval, class_eval, instance_eval和binding

    博客分类:
  • Ruby
 
阅读更多
http://www.cnblogs.com/rubylouvre/archive/2011/08/28/2112321.html
前些天写html生成器的时候用到了erb,在生成html的时候是这么一句:
html=tpl.result(binding)
binding这个变量(Kernel的一个方法 T_T)有点古怪,就搜了下。它表示了ruby的当前作用域,没有任何对外可见的成员函数,唯一的用途就是传递给eval作第二个参数。因而可以这样:
def test_binding
    magic='brother Chun is PURE MAN'
    return binding
end
eval "puts magic", test_binding

这样就穿越了一个作用域。
有时可以见到这样的构造函数:
a=Baby.new {
    name "Makr"
    father "Mike"
    age 0.2
}
a.cry

好处就是好看。实现起来其实也很容易,用instance_eval:
class Baby
    def initialize(&blc)
        instance_eval(&blc) #here
    end
  
    def name(str=nil)
        @name=str if str
        @name
    end
    def age(num=nil)
        @age=num if num
        @age
    end
    def father(str=nil)
        @father=str if str
        @father
    end
    def cry
        puts "#{name} is only #{age.to_s} year old, he wanna milk! Brother Chun is PURE MAN!"
    end
end
#有重复代码?用class_eval缩短之,有点像宏了:
class Baby
    def initialize(&blc)
        instance_eval(&blc)
    end
  
    def Baby.my_attr(*names)
        names.each{|n|
            class_eval %{
                def #{n}(x=nil)
                    @#{n}=x if x
                    @#{n}
                end
            }
        }
    end
  
    my_attr :name, :father, :age
  
    def cry
        puts "#{name} is only #{age.to_s} year old, he wanna milk! Brother Chun is PURE MAN!"
    end
end
  
a=Baby.new {
    name "Makr"
    father "Mike"
    age 0.2
}
a.cry

这里class_eval穿越到了类的作用域,实现了动态添加函数。instance_eval也是,穿越到了实例的作用域,实现修改其内部数据。明白了它们的穿越关系,我们可以实现自己的class_eval和instance_eval——从合适的地方搞到binding就行了。
class Baby
    def my_instance_eval(code)
        eval code, binding
    end
    def Baby.my_class_eval(code='')
        eval code, binding
    end
end
#就这么简单。调用的时候就像这样:
class Baby
    def initialize(code)
        my_instance_eval(code)
    end
    my_attr :name, :father, :age
end
a=Baby.new %{
    name "Test"
    father "Orz"
    age 0.2
}

刚才省略了一点,那就是class_eval和instance_eval可以接受block代替字符串。搜了下,貌似没找到eval接受block的方法,所以这顶多算是只能eval字符串的山寨class_eval。
update: 想起来ruby中lambda和proc在作用域上的小区别,也就是binding的不同了。proc直接使用原先的binding,lambda继承原先作用域创建一个新的binding。

def add_method(c, m, &b)
c.instance_eval { #在此使用class_eval是一样的效果
define_method(m, &b)
}
end
add_method(String, :greet) { "Hello, " + self }
p "world".greet # => "Hello, world"
分享到:
评论

相关推荐

    Ruby中ERB模板的使用

    output = template.result(variables.instance_eval { binding }) puts output ``` `instance_eval`方法会将`variables`哈希转换为一个对象,使得`@title`和`@username`可以访问到其中的键值。`binding`返回当前上...

    java动态代码执行

    GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); groovyObject.invokeMethod("sayHello", null); } } ``` 在这个例子中,我们动态地定义了一个名为DynamicGroovy的类,并调用了它的...

    groovy脚本1

    Groovy是一种动态、灵活的编程语言,它与Java高度兼容并常常被用于简化Java开发,尤其是在脚本编写和自动化任务中。在这个场景中,我们看到了两个主要的Groovy使用示例:通过`GroovyClassLoader`解析Groovy类和通过`...

    BDES.rar_lisp

    6. **EVAL和APPLY**:这两个函数是LISP的核心,EVAL用于评估一个表达式,APPLY用于将一个函数应用于一组参数。 7. **REPL(Read-Eval-Print Loop)**:LISP环境通常提供一个交互式解释器,用户可以即时运行和测试...

    ASP.NET 2.0快速入门(9):ASP.NET 2.0 数据绑定高级技巧

    5. **Binding Sources**(绑定源):除了直接的数据集和数据库,ASP.NET 2.0还支持多种数据源,如XML文件、Web服务、甚至是其他控件的输出。这极大地扩展了数据绑定的可能性。 6. **模板字段**:在GridView和...

    ruby语法基础教程

    §12.3.3 使用eval方法 88 §12.3.4 性能 88 §12.4 Hook和回调方法 89 §12.4.1 什么是Hook 89 §12.4.2 Ruby中的Hook 89 §11.4.2 回调方法 90 §12.5 跟踪程序的运行 90 §12.5.1 set_trace_func 90 §12.5.2 ...

    用36行代码实现最简单的javascript双向绑定

    binding.value = self.$eval(exp); }); }); }; ViewModel.prototype.$eval = function(exp) { with (this.$data) { return eval('(' + exp + ')'); } }; ``` ViewModel类负责连接数据和视图。`bind`方法遍历...

    RUBY基础入门指南

    RubyGems是一个包管理系统,用于管理Ruby的第三方库(gems),简化了库的安装、管理和使用过程。 #### 三、类与对象 **3.1 类的定义** 类是对象的模板,定义了一组具有相同属性和行为的对象。 ```ruby class ...

    listbox 显示图像

    然而,除了显示文本信息,我们有时还需要在`ListBox`中展示图像,以提高用户体验和视觉吸引力。在本文中,我们将深入探讨如何在不同的编程环境中实现`ListBox`显示图像的功能,包括Windows Forms、WPF以及Web应用中...

    专家门诊-ASP.NET开发答疑

    理解控件的生命周期和数据绑定机制(如DataBinder.Eval和BindingSource)对实现动态数据展示至关重要。 3. **状态管理**:由于HTTP协议的无状态性,ASP.NET提供了多种状态管理机制,如视图状态(ViewState)、...

    ASP.NET 2.0快速入门(2):ASP.NET 2.0 数据绑定

    - **declarative binding(声明式绑定)**:在控件的属性中直接指定数据源和字段,如BoundField、TemplateField。 - **event-driven binding(事件驱动绑定)**:通过事件处理程序进行数据绑定,如Page_Load事件。...

    Ruby-PryByebug实现在Pry中一步一步调试和堆栈导航

    `Pry` 是一个替代 IRB(Interactive Ruby)的 REPL(Read-Eval-Print Loop),它提供了更多的功能和方便的上下文导航;而 `Byebug` 是一个源码级别的调试器,可以让你在代码执行时插入断点,查看变量值,甚至控制...

    微软asp.net2.0快速入门第二节

    首先,我们有多种数据绑定表达式可供选择,如 (DataBinder.Eval)和 $ %>(DataBinder.ExpandProperties)。前者用于在服务器端执行数据绑定,后者则用于访问页面上的数据源和资源。这两种表达式极大地简化了从视图...

    C#集成开发新闻发布系统

    例如,使用Repeater或ListView控件,结合DataBinder.Eval或BindingSource组件,可以方便地实现这一功能。 此外,权限管理和用户认证也是新闻发布系统的一个重要组成部分。C#和ASP.NET提供了内置的身份验证和授权...

    ASP.NET2.0(C#)基础教程 李勇平老师的ppt课件 char11

    2. **Explicit Data Binding**(显式数据绑定):使用`Bind()`或`Eval()`表达式直接在控件的属性中绑定数据,如`("ColumnName") %>' />`。 3. **Dynamic Data Binding**(动态数据绑定):在事件处理程序中手动绑定...

    ASP.NET网络书店

    7. 数据绑定技术:项目可能使用了数据绑定技术,如DataBinder.Eval或BindingSource控件,来动态地将数据库中的数据呈现到Web页面上。 8. 错误处理和日志记录:一个完善的Web应用应该具备错误处理机制,如使用Try-...

    ASP.NET服务器控件开发技术与实例

    3. 数据绑定事件:如DataBound和Binding,允许在数据绑定后执行自定义操作。 五、AJAX和UpdatePanel ASP.NET AJAX扩展了服务器控件的功能,允许部分页面更新,提高用户体验。UpdatePanel控件可实现异步回发,无需...

    ASP.NET源码——动态浏览数据库的数据源码.zip

    在这个源码中,可能会使用到DataBinder.Eval或BindingSource等方法来实现数据绑定。 动态浏览数据库通常涉及到以下几个关键步骤: 1. 连接数据库:源码中可能使用ADO.NET库,通过SqlConnection类建立与数据库的...

    Emacs-imagex:Emacs图片扩展

    (eval-after-load 'image+ `(when (require 'hydra nil t) (defhydra imagex-sticky-binding (global-map "C-x C-l") "Manipulating Image" ("+" imagex-sticky-zoom-in "zoom in") ("-" imagex

Global site tag (gtag.js) - Google Analytics