English 中文(简体)
页: 1
原标题:Ruby: convert proc to lambda?

是否有可能将一面面面面面面面面面面面面面面面面面面面面面孔转换成一个lam子。

比方惊讶的是,至少在1.9.2节中,这种工作拖了:

my_proc = proc {|x| x}
my_lambda = lambda &p
my_lambda.lambda? # => false!
问题回答

这是一种微小的trick滴。 http://ruby-doc.org/ruby-1.9/classes/Proc.src/M001173.html” rel=“noretinger”>Proc#lambda?,用于1.9,对<编码>proc与lamdba 之间的区别进行了相当长时间的讨论。

由此得出的是:lambda 执行正确的论据数目,procn t。 从那份文件中可以看出,将诉讼变成伊斯兰教的唯一途径就是:

即便是非伊斯兰教者,也总是界定一种无trick的方法。 标 标 。 这是没有保护trick的唯一例外。

 class C
   define_method(:e, &proc {})
 end
 C.new.e(1,2)       => ArgumentError
 C.new.method(:e).to_proc.lambda?   => true

如果你想避免对任何类别进行污染,你就只能确定一个匿名物体的单一吨方法,以胁迫<条码>proc至lambda:

def convert_to_lambda &block
  obj = Object.new
  obj.define_singleton_method(:_, &block)
  return obj.method(:_).to_proc
end

p = Proc.new {}
puts p.lambda? # false
puts(convert_to_lambda(&p).lambda?) # true

puts(convert_to_lambda(&(lambda {})).lambda?) # true

无需改动。 Mark Rushakoff的回答没有保留栏目中的<条码>自封的价值,因为<条码>自封/条码>改为<条码>。 Pawel Tomulik的答复可以与Ruby 2.1做,因为define_singleton_method。 代表:

我的回答是也错了:

def convert_to_lambda &block
  obj = block.binding.eval( self )
  Module.new.module_exec do
    define_method(:_, &block)
    instance_method(:_).bind(obj).to_proc
  end
end

保留栏目中的<代码>本身的价值:

p = 42.instance_exec { proc { self }}
puts p.lambda?      # false
puts p.call         # 42

q = convert_to_lambda &p
puts q.lambda?      # true
puts q.call         # 42

但是它没有遵守<条码>_exec:

puts 66.instance_exec &p    # 66
puts 66.instance_exec &q    # 42, should be 66

我必须使用<代码>block. binding.eval(自封)来找到正确的对象。 我把我的方法放在一个匿名的单元中,因此永远不会污染任何阶层。 然后,我把我的方法与正确的目标联系起来。 虽然该目标从未包括该模块,但这项工作却不成功! 约束性方法使“lam”。

<代码>66.instance_exec &q之所以失效,是因为q是秘密的一种方法,受约束于42,instance_exec可重新整合该方法。 可以通过扩大<代码>q,暴露无约束的方法,重新界定<代码>instance_exec<>/code>,将无约束的方法约束于不同的物体。 即便如此,module_exec_class_exec 仍然失败。

class Array
  $p = proc { def greet; puts "Hi!"; end }
end
$q = convert_to_lambda &$p
Hash.class_exec &$q
{}.greet # undefined method `greet  for {}:Hash (NoMethodError)

问题是<代码>。 Hashem_exec 和amp;$q 下定义如下:,而不是Hash#greet。 (尽管$q 秘密是一种匿名模块方法,但它仍然界定了Array的方法,而不是在匿名模块中。) 原文照相,Hash.class_exec &$p <代码>Hash#greet。 我的结论是,<条码>convert_to_lambda 是错误的,因为它没有与<条码>_exec合作。

可能的解决办法是:

class Proc
  def to_lambda
    return self if lambda?

    # Save local reference to self so we can use it in module_exec/lambda scopes
    source_proc = self

    # Convert proc to unbound method
    unbound_method = Module.new.module_exec do
      instance_method( define_method( :_proc_call, &source_proc ))
    end

    # Return lambda which binds our unbound method to correct receiver and calls it with given args/block
    lambda do |*args, &block|
      # If binding doesn t changed (eg. lambda_obj.call) then bind method to original proc binding,
      # otherwise bind to current binding (eg. instance_exec(&lambda_obj)).
      unbound_method.bind( self == source_proc ? source_proc.receiver : self ).call( *args, &block )
    end
  end

  def receiver
    binding.eval( "self" )
  end
end

p1 = Proc.new { puts "self = #{self.inspect}" }
l1 = p1.to_lambda

p1.call #=> self = main
l1.call #=> self = main

p1.call( 42 ) #=> self = main
l1.call( 42 ) #=> ArgumentError: wrong number of arguments (1 for 0)

42.instance_exec( &p1 ) #=> self = 42
42.instance_exec( &l1 ) #=> self = 42

p2 = Proc.new { return "foo" }
l2 = p2.to_lambda

p2.call #=> LocalJumpError: unexpected return
l2.call #=> "foo"

1. 如果工作于Ruby 2.1+

Cross ruby compatiable library for converting procs to lambdas: https://github.com/schneems/proc_to_lambda

The Gem: http://rubygems.org/gems/proc_to_lambda

以上代码与<代码>instance_exec只字不提,但我认为对此有简单的规定。 我在此举了一个例子,说明问题与解决办法:

# /tmp/test.rb
def to_lambda1(&block)
  obj = Object.new
  obj.define_singleton_method(:_,&block)
  obj.method(:_).to_proc
end

def to_lambda2(&block)
  Object.new.define_singleton_method(:_,&block).to_proc
end


l1 = to_lambda1 do
  print "to_lambda1: #{self.class.name}
"
end
print "l1.lambda?: #{l1.lambda?}
"

l2 = to_lambda2 do
  print "to_lambda2: #{self.class.name}
"
end
print "l2.lambda?: #{l2.lambda?}
"

class A; end

A.new.instance_exec &l1
A.new.instance_exec &l2

to_lambda1基本上是由Mark、to_lambda 2提出的执行,是“固定”代码。

以上文字的产出是:

l1.lambda?: true
l2.lambda?: true
to_lambda1: Object
to_lambda2: A

事实上,I d 预期instance_exec to输出A, not Object (instance_exec should change binding). 我不知道为什么这项工作不同,但我假定:define_singleton_method。 一种尚未受<代码>约束的方法 标的和Object#method回归一种已经具有约束力的方法。





相关问题
Ruby parser in Java

The project I m doing is written in Java and parsers source code files. (Java src up to now). Now I d like to enable parsing Ruby code as well. Therefore I am looking for a parser in Java that parses ...

rails collection_select vs. select

collection_select and select Rails helpers: Which one should I use? I can t see a difference in both ways. Both helpers take a collection and generates options tags inside a select tag. Is there a ...

RubyCAS-Client question: Rails

I ve installed RubyCAS-Client version 2.1.0 as a plugin within a rails app. It s working, but I d like to remove the ?ticket= in the url. Is this possible?

Ordering a hash to xml: Rails

I m building an xml document from a hash. The xml attributes need to be in order. How can this be accomplished? hash.to_xml

multiple ruby extension modules under one directory

Can sources for discrete ruby extension modules live in the same directory, controlled by the same extconf.rb script? Background: I ve a project with two extension modules, foo.so and bar.so which ...

Text Editor for Ruby-on-Rails

guys which text editor is good for Rubyonrails? i m using Windows and i was using E-Texteditor but its not free n its expired now can anyone plese tell me any free texteditor? n which one is best an ...

热门标签