Skip to content

Instantly share code, notes, and snippets.

@no6v
Created March 19, 2012 13:12
Show Gist options
  • Save no6v/2111606 to your computer and use it in GitHub Desktop.
Save no6v/2111606 to your computer and use it in GitHub Desktop.
{Object,NilClass}#try
diff --git a/object.c b/object.c
index 63af8a2..77ba3e2 100644
--- a/object.c
+++ b/object.c
@@ -615,6 +615,12 @@ rb_obj_tap(VALUE obj)
return obj;
}
+VALUE
+rb_obj_try(int argc, VALUE *argv, VALUE obj)
+{
+ if (argc == 0) return obj;
+ return rb_funcall2(obj, rb_intern("__send__"), argc, argv);
+}
/*
* Document-method: inherited
@@ -1246,6 +1252,16 @@ rb_false(VALUE obj)
return Qfalse;
}
+VALUE
+nil_try(int argc, char *argv)
+{
+ VALUE obj;
+
+ if (argc > 0) return Qnil;
+ obj = rb_obj_alloc(rb_cBasicObject);
+ rb_define_singleton_method(obj, "method_missing", nil_try, -1);
+ return obj;
+}
/*
* call-seq:
@@ -2875,6 +2891,7 @@ Init_Object(void)
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
+ rb_define_method(rb_mKernel, "try", rb_obj_try, -1);
rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
rb_define_global_function("format", rb_f_sprintf, -1); /* in sprintf.c */
@@ -2897,6 +2914,7 @@ Init_Object(void)
rb_define_method(rb_cNilClass, "^", false_xor, 1);
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
+ rb_define_method(rb_cNilClass, "try", nil_try, -1);
rb_undef_alloc_func(rb_cNilClass);
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
/*
unless Object.method_defined?(:try)
class Object
def try(*args)
if args.empty?
self
else
__send__(args.shift, *args)
end
end
end
end
unless NilClass.method_defined?(:try)
class NilClass
def try(*args)
if args.empty?
obj = BasicObject.new
def obj.method_missing(*)
nil
end
obj
else
nil
end
end
end
end
{a:1}.try(:[], :a) # => 1
nil.try(:[], :a) # => nil
{a:1}.try[:a] # => 1
nil.try[:a] # => nil
h = {a:1}
h.try(:[]=, :b, 2) # => 2
h # => {:a=>1, :b=>2}
h = nil
h.try(:[]=, :b, 2) # => nil
h # => nil
h = {a:1}
h.try[:b] = 2 # => 2
h # => {:a=>1, :b=>2}
h = nil
h.try[:b] = 2 # => 2
h # => nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment