如何在Ruby中判断Proc是否为lambda函数

3
假设我已经创建了一个Lambda实例,并且我想以后查询这个对象,以查看它是一个过程还是Lambda。 怎么做呢? .class()方法行不通。
irb(main):001:0> k = lambda{ |x| x.to_i() +1 }
=> #<Proc:0x00002b931948e590@(irb):1>
irb(main):002:0> k.class()
=> Proc
1个回答

5

Ruby 1.9.3及以上版本

您需要查找Proc#lambda?方法。

k = lambda { |x| x.to_i + 1 }
k.lambda? #=> true
k = proc { |x| x.to_i + 1 }
k.lambda? #=> false

1.9.3版本之前的解决方案

我们将制作ruby本地扩展。 创建proc_lambda/proc_lambda.c文件,并添加以下内容。

#include <ruby.h>
#include <node.h>
#include <env.h>


/* defined so at eval.c */
#define BLOCK_LAMBDA  2
struct BLOCK {
    NODE *var;
    NODE *body;
    VALUE self;
    struct FRAME frame;
    struct SCOPE *scope;
    VALUE klass;
    NODE *cref;
    int iter;
    int vmode;
    int flags;
    int uniq;
    struct RVarmap *dyna_vars;
    VALUE orig_thread;
    VALUE wrapper;
    VALUE block_obj;
    struct BLOCK *outer;
    struct BLOCK *prev;
};

/* the way of checking if flag is set I took from proc_invoke function at eval.c */
VALUE is_lambda(VALUE self) 
{
    struct BLOCK *data;
    Data_Get_Struct(self, struct BLOCK, data);
    return (data->flags & BLOCK_LAMBDA) ? Qtrue : Qfalse;
}

void Init_proc_lambda() 
{
    /* getting Proc class */
    ID proc_id = rb_intern("Proc");
    VALUE proc = rb_const_get(rb_cObject, proc_id);

    /* extending Proc with lambda? method */
    rb_define_method(proc, "lambda?", is_lambda, 0);
}

创建proc_lambda/extconf.rb文件:
require 'mkmf'
create_makefile('proc_lambda')

在终端中,进入proc_lambda目录并运行。
$ ruby extconf.rb
$ make && make install

在irb中进行测试

irb(main):001:0> require 'proc_lambda'
=> true
irb(main):002:0> lambda {}.lambda?
=> true
irb(main):003:0> Proc.new {}.lambda?
=> false

我们在谈论哪个版本的Ruby?我有旧的1.8.7版本,它没有这个...实际上,并没有以“l”开头的方法... irb(main):006:0> k.methods().sort().select{ |x| x.to_s().match(/^l/) } => [] - user1134991
1
@user1134991 我认为这个方法从1.9.3版本开始就可用了。 - user2422869
1
@user1134991,如果您正在运行遗留版本,特别是在提问时,请在问题中提及您的Ruby版本并相应地打标签。 - Stefan
@user1134991 看看更新后的答案吧!希望你会喜欢。 - user2422869
我们将制作Ruby本地扩展,+1进入兔子洞 :-P - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接