2015-02-18 4 views
2

Предположим, что я создал экземпляр лямбда, и я хочу, чтобы позже запросить этот объект, чтобы увидеть, является ли это proc или лямбдой. Как это сделать? метод .class() не выполняет трюк.Как узнать, является ли Proc лямбдой или нет в Ruby?

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

ответ

2

Рубин 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 решение

Мы собираемся сделать рубиновый родное расширение. Создать 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 
+0

О какой версии Ruby, мы говорим Вот? У меня есть старый 1.8.7, и у него его нет ... На самом деле нет метода, начинающегося с «l» ... irb (main): 006: 0> k.methods(). Sort (). Выберите {| x | x.to_s(). match (/^l /)} => [] – user1134991

+1

@ user1134991 Я думаю, что этот метод доступен с 1.9.3 – user2422869

+1

@ user1134991, вы должны указать свою версию Ruby в своем вопросе и пометить ее соответствующим образом, особенно если вы используете устаревшую версию. – Stefan