【问题标题】:How can one know if a Proc is a lambda or not in Ruby在 Ruby 中如何知道 Proc 是否是 lambda
【发布时间】:2015-02-18 10:45:24
【问题描述】:

假设我创建了一个 lambda 实例,我想稍后查询这个对象,看看它是 proc 还是 lambda。如何做到这一点? .class() 方法不能解决问题。

irb(main):001:0> k = lambda{ |x| x.to_i() +1 }
=> #<Proc:0x00002b931948e590@(irb):1>
irb(main):002:0> k.class()
=> Proc

【问题讨论】:

    标签: ruby lambda introspection proc


    【解决方案1】:

    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
    

    Pre 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')
    

    在终端cd到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.9.3开始就可以使用了
    • @user1134991 您应该在问题中提及您的 Ruby 版本并相应地标记它,特别是如果您运行的是旧版本。
    • @user1134991 查看更新后的答案!希望你会喜欢它。
    • “我们将制作 ruby​​ 原生扩展” +1 兔子洞:-P
    猜你喜欢
    • 2010-09-06
    • 2021-07-28
    • 2015-12-08
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    相关资源
    最近更新 更多