[前][次][番号順一覧][スレッド一覧]

ruby-changes:53698

From: nobu <ko1@a...>
Date: Thu, 22 Nov 2018 14:57:55 +0900 (JST)
Subject: [ruby-changes:53698] nobu:r65914 (trunk): Proc#<< and Proc#>>

nobu	2018-11-22 14:51:43 +0900 (Thu, 22 Nov 2018)

  New Revision: 65914

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65914

  Log:
    Proc#<< and Proc#>>
    
    [Feature #6284]

  Modified files:
    trunk/NEWS
    trunk/proc.c
    trunk/test/ruby/test_method.rb
    trunk/test/ruby/test_proc.rb
Index: proc.c
===================================================================
--- proc.c	(revision 65913)
+++ proc.c	(revision 65914)
@@ -3052,14 +3052,21 @@ compose(VALUE dummy, VALUE args, int arg https://github.com/ruby/ruby/blob/trunk/proc.c#L3052
     VALUE f, g, fargs;
     f = RARRAY_AREF(args, 0);
     g = RARRAY_AREF(args, 1);
-    fargs = rb_ary_new3(1, rb_funcall_with_block(g, idCall, argc, argv, passed_proc));
 
-    return rb_proc_call(f, fargs);
+    if (rb_obj_is_proc(g))
+        fargs = rb_proc_call_with_block(g, argc, argv, passed_proc);
+    else
+        fargs = rb_funcall_with_block(g, idCall, argc, argv, passed_proc);
+
+    if (rb_obj_is_proc(f))
+        return rb_proc_call(f, rb_ary_new3(1, fargs));
+    else
+        return rb_funcallv(f, idCall, 1, &fargs);
 }
 
 /*
  *  call-seq:
- *     prc * g -> a_proc
+ *     prc << g -> a_proc
  *
  *  Returns a proc that is the composition of this proc and the given <i>g</i>.
  *  The returned proc takes a variable number of arguments, calls <i>g</i> with them
@@ -3067,17 +3074,19 @@ compose(VALUE dummy, VALUE args, int arg https://github.com/ruby/ruby/blob/trunk/proc.c#L3074
  *
  *     f = proc {|x| x * 2 }
  *     g = proc {|x, y| x + y }
- *     h = f * g
+ *     h = f << g
  *     p h.call(1, 2) #=> 6
  */
 static VALUE
-proc_compose(VALUE self, VALUE g)
+proc_compose_to_left(VALUE self, VALUE g)
 {
-    VALUE proc, args;
+    VALUE proc, args, procs[2];
     rb_proc_t *procp;
     int is_lambda;
 
-    args = rb_ary_new3(2, self, g);
+    procs[0] = self;
+    procs[1] = g;
+    args = rb_ary_tmp_new_from_values(0, 2, procs);
 
     GetProcPtr(self, procp);
     is_lambda = procp->is_lambda;
@@ -3091,7 +3100,41 @@ proc_compose(VALUE self, VALUE g) https://github.com/ruby/ruby/blob/trunk/proc.c#L3100
 
 /*
  *  call-seq:
- *     meth * g -> a_proc
+ *     prc >> g -> a_proc
+ *
+ *  Returns a proc that is the composition of this proc and the given <i>g</i>.
+ *  The returned proc takes a variable number of arguments, calls <i>g</i> with them
+ *  then calls this proc with the result.
+ *
+ *     f = proc {|x, y| x + y }
+ *     g = proc {|x| x * 2 }
+ *     h = f >> g
+ *     p h.call(1, 2) #=> 6
+ */
+static VALUE
+proc_compose_to_right(VALUE self, VALUE g)
+{
+    VALUE proc, args, procs[2];
+    rb_proc_t *procp;
+    int is_lambda;
+
+    procs[0] = g;
+    procs[1] = self;
+    args = rb_ary_tmp_new_from_values(0, 2, procs);
+
+    GetProcPtr(self, procp);
+    is_lambda = procp->is_lambda;
+
+    proc = rb_proc_new(compose, args);
+    GetProcPtr(proc, procp);
+    procp->is_lambda = is_lambda;
+
+    return proc;
+}
+
+/*
+ *  call-seq:
+ *     meth << g -> a_proc
  *
  *  Returns a proc that is the composition of this method and the given <i>g</i>.
  *  The returned proc takes a variable number of arguments, calls <i>g</i> with them
@@ -3103,14 +3146,38 @@ proc_compose(VALUE self, VALUE g) https://github.com/ruby/ruby/blob/trunk/proc.c#L3146
  *
  *     f = self.method(:f)
  *     g = proc {|x, y| x + y }
- *     h = f * g
+ *     h = f << g
+ *     p h.call(1, 2) #=> 6
+ */
+static VALUE
+rb_method_compose_to_left(VALUE self, VALUE g)
+{
+    VALUE proc = method_to_proc(self);
+    return proc_compose_to_left(proc, g);
+}
+
+/*
+ *  call-seq:
+ *     meth >> g -> a_proc
+ *
+ *  Returns a proc that is the composition of this method and the given <i>g</i>.
+ *  The returned proc takes a variable number of arguments, calls <i>g</i> with them
+ *  then calls this method with the result.
+ *
+ *     def f(x, y)
+ *       x + y
+ *     end
+ *
+ *     f = self.method(:f)
+ *     g = proc {|x| x * 2 }
+ *     h = f >> g
  *     p h.call(1, 2) #=> 6
  */
 static VALUE
-rb_method_compose(VALUE self, VALUE g)
+rb_method_compose_to_right(VALUE self, VALUE g)
 {
     VALUE proc = method_to_proc(self);
-    return proc_compose(proc, g);
+    return proc_compose_to_right(proc, g);
 }
 
 /*
@@ -3209,7 +3276,8 @@ Init_Proc(void) https://github.com/ruby/ruby/blob/trunk/proc.c#L3276
     rb_define_method(rb_cProc, "lambda?", rb_proc_lambda_p, 0);
     rb_define_method(rb_cProc, "binding", proc_binding, 0);
     rb_define_method(rb_cProc, "curry", proc_curry, -1);
-    rb_define_method(rb_cProc, "*", proc_compose, 1);
+    rb_define_method(rb_cProc, "<<", proc_compose_to_left, 1);
+    rb_define_method(rb_cProc, ">>", proc_compose_to_right, 1);
     rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
     rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0);
 
@@ -3236,7 +3304,8 @@ Init_Proc(void) https://github.com/ruby/ruby/blob/trunk/proc.c#L3304
     rb_define_method(rb_cMethod, "call", rb_method_call, -1);
     rb_define_method(rb_cMethod, "===", rb_method_call, -1);
     rb_define_method(rb_cMethod, "curry", rb_method_curry, -1);
-    rb_define_method(rb_cMethod, "*", rb_method_compose, 1);
+    rb_define_method(rb_cMethod, "<<", rb_method_compose_to_left, 1);
+    rb_define_method(rb_cMethod, ">>", rb_method_compose_to_right, 1);
     rb_define_method(rb_cMethod, "[]", rb_method_call, -1);
     rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
     rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
Index: NEWS
===================================================================
--- NEWS	(revision 65913)
+++ NEWS	(revision 65914)
@@ -171,6 +171,12 @@ sufficient information, see the ChangeLo https://github.com/ruby/ruby/blob/trunk/NEWS#L171
     * KeyError.new accepts +:receiver+ and +:key+ options to set receiver and
       key in Ruby code.  [Feature #14313]
 
+[Method]
+
+  [New methods]
+
+    * added Method#<< and Method#>> for Proc composition.  [Feature #6284]
+
 [Module]
 
   [New methods]
@@ -203,6 +209,10 @@ sufficient information, see the ChangeLo https://github.com/ruby/ruby/blob/trunk/NEWS#L209
 
 [Proc]
 
+  [New methods]
+
+    * added Proc#<< and Proc#>> for Proc composition.  [Feature #6284]
+
   [Incompatible changes]
 
     * Proc#call doesn't change <code>$SAFE</code> any more.  [Feature #14250]
Index: test/ruby/test_proc.rb
===================================================================
--- test/ruby/test_proc.rb	(revision 65913)
+++ test/ruby/test_proc.rb	(revision 65914)
@@ -1420,33 +1420,33 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L1420
   def test_compose
     f = proc {|x| x * 2}
     g = proc {|x| x + 1}
-    h = f * g
 
-    assert_equal(6, h.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(6, (g >> f).call(2))
   end
 
   def test_compose_with_multiple_args
     f = proc {|x| x * 2}
     g = proc {|x, y| x + y}
-    h = f * g
 
-    assert_equal(6, h.call(1, 2))
+    assert_equal(6, (f << g).call(1, 2))
+    assert_equal(6, (g >> f).call(1, 2))
   end
 
   def test_compose_with_block
     f = proc {|x| x * 2}
     g = proc {|&blk| blk.call(1) }
-    h = f * g
 
-    assert_equal(8, h.call { |x| x + 3 })
+    assert_equal(8, (f << g).call { |x| x + 3 })
+    assert_equal(8, (g >> f).call { |x| x + 3 })
   end
 
   def test_compose_with_lambda
     f = lambda {|x| x * 2}
     g = lambda {|x| x}
-    h = f * g
 
-    assert_predicate(h, :lambda?)
+    assert_predicate((f << g), :lambda?)
+    assert_predicate((g >> f), :lambda?)
   end
 
   def test_compose_with_method
@@ -1455,9 +1455,9 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L1455
       def g(x) x + 1 end
     }
     g = c.new.method(:g)
-    h = f * g
 
-    assert_equal(6, h.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(5, (f >> g).call(2))
   end
 
   def test_compose_with_callable
@@ -1465,17 +1465,20 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L1465
     c = Class.new {
       def call(x) x + 1 end
     }
-    g = f * c.new
+    g = c.new
 
-    assert_equal(6, g.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(5, (f >> g).call(2))
   end
 
   def test_compose_with_noncallable
     f = proc {|x| x * 2}
-    g = f * 5
 
     assert_raise(NoMethodError) {
-      g.call(2)
+      (f << 5).call(2)
+    }
+    assert_raise(NoMethodError) {
+      (f >> 5).call(2)
     }
   end
 end
Index: test/ruby/test_method.rb
===================================================================
--- test/ruby/test_method.rb	(revision 65913)
+++ test/ruby/test_method.rb	(revision 65914)
@@ -1048,9 +1048,9 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L1048
     }
     f = c.new.method(:f)
     g = c.new.method(:g)
-    h = f * g
 
-    assert_equal(6, h.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(6, (g >> f).call(2))
   end
 
   def test_compose_with_proc
@@ -1059,9 +1059,9 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L1059
     }
     f = c.new.method(:f)
     g = proc {|x| x + 1}
-    h = f * g
 
-    assert_equal(6, h.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(6, (g >> f).call(2))
   end
 
   def test_compose_with_callable
@@ -1072,9 +1072,10 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L1072
       def call(x) x + 1 end
     }
     f = c.new.method(:f)
-    g = f * c2.new
+    g = c2.new
 
-    assert_equal(6, g.call(2))
+    assert_equal(6, (f << g).call(2))
+    assert_equal(5, (f >> g).call(2))
   end
 
   def test_compose_with_noncallable
@@ -1082,10 +1083,12 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L1083
       def f(x) x * 2 end
     }
     f = c.new.method(:f)
-    g = f * 5
 
     assert_raise(NoMethodError) {
-      g.call(2)
+      (f << 5).call(2)
+    }
+    assert_raise(NoMethodError) {
+      (f >> 5).call(2)
     }
   end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]