Tag: 元编程

如何将任何方法转换为ruby中的中缀运算符

在某些语言(如Haskell)中, 可以使用任何带有两个参数的函数作为中缀运算符。 我觉得这个符号很有意思,想在ruby中实现同样的目的。 假设有一个想象的方法or_if_familiar我希望能够写出类似”omg” or_if_familiar “oh!”东西”omg” or_if_familiar “oh!” 而不是or_if_familiar(“omg”, “oh!”) 如何在ruby中创建这样的符号(不修改ruby本身)?

带有(class_eval,define_method)vs(instance_eval,define_method)的Ruby单例方法

ruby中的元编程非常棒,因为我经常使用它来模拟基于原型的编程,并快速编写原型解决方案来解决某些问题,以测试它们的可行性。 所以我想知道以下代码之间是否存在任何本质区别: (class << some_object; self; end).class_eval do define_method(:method_name) do … method body … end end 和 (class << some_object; self; end).instance_eval do define_method(:method_name) do … method body … end end 这两个版本的代码都定义了一个单例方法,我还没有遇到任何强迫我选择(instance_eval, define_method)组合的(class_eval, define_method)组合来定义单例方法的东西,我想知道如果两者之间存在某些本质区别。

`class_eval`字符串中的变量范围是什么?

我正在使用class_eval编写要在当前类的上下文中执行的代码。 在以下代码中,我想为属性值的更改添加计数器。 class Class def attr_count(attr_name) attr_name = attr_name.to_s attr_reader attr_name # create the attribute’s getter class_eval %Q{ @count = 0 def #{attr_name}= (attr_name) @attr_name = attr_name @count += 1 end def #{attr_name} @attr_name end } end end class Foo attr_count :bar end f = Foo.new f.bar = 1 我对class_eval理解是它在运行时类的上下文中计算块 – 在我的例子中,在class Foo 。 我希望上面的代码运行类似于 […]

从Ruby中的不同绑定访问局部变量

在Ruby中,您可以使用local_variables和eval编程方式轻松访问本地变量。 我真的希望使用单个方法调用对这些变量进行元编程访问,例如 # define a variable in this scope, such as x = 5 Foo.explore_locals # inside the Foo#explore_locals method, access x 其中Foo是一些外部模块。 我们的想法是以一种很好的方式显示和导出局部变量。 explore_locals方法应该包含哪些内容? 有没有办法让这成为可能? 如果绝对必要,我猜它可能会 Foo.explore_locals binding 但是对于我想到的应用程序来说,这并不那么优雅。

调用Ruby Singleton的方法而不引用’instance’

我想调用Singleton对象的方法而不引用它的实例 SingletonKlass.my_method 代替 SingletonKlass.instance.my_method 我想出了这个解决方案(在课堂上使用method_missing): require ‘singleton’ class SingletonKlass include Singleton def self.method_missing(method, *args, &block) self.instance.send(method, *args) end def my_method puts “hi there!!” end end 这有什么缺点吗? 还有更好的解决方案吗? 你的任何推荐? 谢谢。 更新: 我的目标是让一个模块与单例类混合: module NoInstanceSingleton def method_missing(method, *args) self.instance.send(method, *args) end end 结束然后在课堂上使用它: class SingletonKlass include Singleton extend NoInstanceSingleton def method1; end def method2; end … def […]

Ruby:在事件触发器中自动包装方法

inheritance人我拥有/想要的东西: module Observable def observers; @observers; end def trigger(event, *args) good = true return good unless (@observers ||= {})[event] @obersvers[event].each { |e| good = false and break unless e.call(self, args) } good end def on(event, &block) @obersvers ||= {} @obersvers[event] ||= [] @observers[event] << block end end class Item < Thing include Observable def pickup(pickuper) […]

动态创建类方法

我正在编写一个类方法来创建另一个类方法。 关于class_eval和instance_eval如何在类方法的上下文中运行似乎有些奇怪。 为了显示: class Test1 def self.add_foo self.class_eval do # does what it says on the tin define_method :foo do puts “bar” end end end end Test1.add_foo # creates new instance method, like I’d expect Test1.new.foo # => “bar” class Test2 def self.add_foo self.instance_eval do # seems to do the same as “class_eval” define_method :foo […]

包含模块时__callee__的意外值 – 这是一个Ruby错误吗?

当通过alias_method创建的方法调用时, __callee__忽略旧方法的名称(此处为xxx )并返回新方法的名称,如下所示: class Foo def xxx() __callee__ end alias_method :foo, :xxx end Foo.new.foo # => :foo 即使从超类inheritancexxx此行为也成立: class Sup def xxx() __callee__ end end class Bar :bar 考虑到上述两种情况,我预计当通过模块包含xxx时,相同的行为将成立。 但事实并非如此: module Mod def xxx() __callee__ end end class Baz include Mod alias_method :baz, :xxx end Baz.new.baz # => :xxx 我希望返回值为:baz ,而不是:xxx 。 上面的代码是使用Ruby 2.3.1p112执行的。 这是__callee__实现中的__callee__吗? […]

在define_method中使用局部变量

我想了解define_method如何工作以及如何正确使用定义块之外的变量。 这是我的代码: class Test def self.plugin for i in 1..2 define_method(“test#{i}”.to_sym) do pi end end end plugin end ob = Test.new ob.test1 #=> 2 (I would expect 1) ob.test2 #=> 2 (I would expect 2) 似乎在方法test1和test2 , i的值在定义期间没有被替换,而是在调用方法时直接在现场计算。 所以我们只看到i的最新值, i 2 。 但Ruby从哪里获取此值? 有没有办法让test#{i}打印出来? 在这种特殊情况下,我可以使用__method__进行解决方法 ,但可能有更好的解决方案。

比较Procs的内容,而不是结果

使用Ruby 1.9.2 问题 比较两个过程的内容,而不是结果。 我知道结果因为停止问题而无法测试但是没关系; 我还是不想测试结果。 例如 proc {@x == “x”} == proc {@x == “x”} => false # doh! 返回false,因为procs中的对象不一样。 我笨重的解决方案 我有一个解决方案,有点像我做我想要的但它并没有真正测试proc与我放入它的“相同”。 在我的特定情况下,我的procs的格式将始终是对实例变量的布尔测试,如下所示: {@x == “x” && @y != “y” || @z == String} 我编写了一个动态构建类的方法,并创建了设置为指定值的实例变量: def create_proc_tester(property_value_hash) new_class = Class.new.new new_class.class.class_eval do define_method(:xql?) { |&block| instance_eval &block } end property_value_hash.each do |key, value| new_class.instance_variable_set(“@#{key}”, […]