From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: poffice@blade.nagaokaut.ac.jp Delivered-To: poffice@blade.nagaokaut.ac.jp Received: from kankan.nagaokaut.ac.jp (kankan.nagaokaut.ac.jp [133.44.2.24]) by blade.nagaokaut.ac.jp (Postfix) with ESMTP id 7D4AD1B8016A for ; Sat, 29 Apr 2017 04:06:00 +0900 (JST) Received: from voscc.nagaokaut.ac.jp (voscc.nagaokaut.ac.jp [133.44.1.100]) by kankan.nagaokaut.ac.jp (Postfix) with ESMTP id A841CB5D936 for ; Sat, 29 Apr 2017 04:47:47 +0900 (JST) Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by voscc.nagaokaut.ac.jp (Postfix) with ESMTP id C183D18CC7B1 for ; Sat, 29 Apr 2017 04:47:47 +0900 (JST) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id E8F83120817; Sat, 29 Apr 2017 04:47:43 +0900 (JST) X-Original-To: ruby-core@ruby-lang.org Delivered-To: ruby-core@ruby-lang.org Received: from o1678916x28.outbound-mail.sendgrid.net (o1678916x28.outbound-mail.sendgrid.net [167.89.16.28]) by neon.ruby-lang.org (Postfix) with ESMTPS id 164451207FE for ; Sat, 29 Apr 2017 04:47:32 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=sendgrid.me; h=from:to:references:subject:mime-version:content-type:content-transfer-encoding:list-id; s=smtpapi; bh=qQMeQfRcae6Bk2vL0vcg4KU+fH0=; b=Xzpn3SIMAEBhgKjFYy RoArlaGLMDnrn8gGflnkK93du6LH3X8WNramGNzKEC/Ncs590tEjJ1mr0g62KapS Zw6YvKfdktpwqJCl5a0dOMowD3eKoVMeqo7o26RjGBEDL1eYxrPCld/wnhvtf/8t pJenY9tnnHclPkumdbQiA6S/Q= Received: by filter0430p1mdw1.sendgrid.net with SMTP id filter0430p1mdw1-22980-59039C4F-47 2017-04-28 19:47:27.640809397 +0000 UTC Received: from herokuapp.com (ec2-54-198-145-62.compute-1.amazonaws.com [54.198.145.62]) by ismtpd0003p1iad1.sendgrid.net (SG) with ESMTP id jmAOneTXTbuiu8XkV4582g Fri, 28 Apr 2017 19:47:27.557 +0000 (UTC) Date: Fri, 28 Apr 2017 19:47:27 +0000 From: ritchie@richorelse.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 55973 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 6284 X-Redmine-Issue-Author: pabloh X-Redmine-Issue-Assignee: matz X-Redmine-Sender: RichOrElse X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS7o44E/f3aCSBgJ26mUn3/uPSnFhC70GQK4fx +n1VDqWO6PJJu43HQ6Ml9Gm9XBQXbie+oMEetScLz1g5lf31Qg5jPsiLm+kwOpnkBznwV+nCkOlPEY YHZCEJ/4PzEO1L9CHjcKMeSF1aEm6O/4aYjc0jFH2iMhAdR0enktewO12w== X-ML-Name: ruby-core X-Mail-Count: 80931 Subject: [ruby-core:80931] [Ruby trunk Feature#6284] Add composition for procs X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #6284 has been updated by RichOrElse (Richie Paul Buitre). matz (Yukihiro Matsumoto) wrote: > I want to make sure if everyone agrees with "*" instead of OP's "<<". > Besides that I also wanted to mention that Koichi concerns that function composition may be far slower than method chaining. > > Matz. +1 for #* Initially I thought of the F# convention #<< and it's counter part #>> as intuitive. But after giving it some thought, and practice, I prefer #* and #+. ~~~ ruby class Proc def +(other) # forward compose operation other.to_proc * self end def *(other) # backward compose operation -> arg { self.call other.(arg) } # with only one argument for performance reason. end end f = -> n { n * 2 } g = -> n { n * 4 } h = f * g # equivalent to (g + f) puts h.(5) #=> 40 puts (h + :odd?).call(3) #=> false ~~~ Instead of composition I see potential use for shovel operations #<< and #>> for piping purposes similar to Elixir's #|>. ~~~ ruby class Object def >>(transform) # piping operation transform.(self) end end class Integer def >>(num_or_func) return num_or_func.(self) if num_or_func.respond_to? :call super end end class Proc def <<(input) # feed value call input end end add_header = ->val {"Title: " + val} format_as_title = add_header + :capitalize + :strip puts 'Title goes here.' >> format_as_title #=> Title: title goes here. puts format_as_title << 'Title goes there.' #=> Title: title goes there. ~~~ ---------------------------------------- Feature #6284: Add composition for procs https://bugs.ruby-lang.org/issues/6284#change-64565 * Author: pabloh (Pablo Herrero) * Status: Feedback * Priority: Normal * Assignee: matz (Yukihiro Matsumoto) * Target version: ---------------------------------------- =begin It would be nice to be able to compose procs like functions in functional programming languages: to_camel = :capitalize.to_proc add_header = ->val {"Title: " + val} format_as_title = add_header << to_camel << :strip instead of: format_as_title = lambda {|val| "Title: " + val.strip.capitalize } It's pretty easy to implement in pure ruby: class Proc def << block proc { |*args| self.call( block.to_proc.call(*args) ) } end end =end ---Files-------------------------------- 0001-proc.c-Implement-Proc-for-Proc-composition.patch (3.65 KB) 0002-proc.c-Implement-Method-for-Method-composition.patch (2.67 KB) 0003-proc.c-Support-any-callable-when-composing-Procs.patch (3.97 KB) -- https://bugs.ruby-lang.org/