From: "mame (Yusuke Endoh)" Date: 2012-04-04T21:14:47+09:00 Subject: [ruby-core:44126] [ruby-trunk - Feature #6253][Assigned] Implement a way to pass keyword options to curried procs Issue #6253 has been updated by mame (Yusuke Endoh). Status changed from Open to Assigned Assignee set to matz (Yukihiro Matsumoto) Hello, 2012/4/4 jballanc (Joshua Ballanco) : > The example below demonstrates a Rack-like system where a curried proc is passed to a helper, then after partial application of the arguments, the returned curried proc is stored and later evaluated: *snip* I think Proc#curry is not an appropriate answer to your problem. You should just create a new lambda: class NightGreeting def initialize(app) @app = app end def call(sender) proc do |receiver| @app.call(sender, receiver, greeting: "Goodnight") end #.curry # needed when the proc accepts multiple parameters end end > Currying is really only useful when it can be used with partial application. However, Ruby currently limits how you can achieve partial application of curried procs. In particular, there is no way to manage partial application of parameters with default values. As such, it is not surprising that Proc#curry does not seem to have been adopted very widely. In my personal survey of ~600 gems that I use in various projects, I did not find any usage of Proc#curry. In a sense, the situation is just as I expected :-) I'm the person who made the proposal of Proc#curry in [ruby-dev:33676]. I suggested it with purely theoretical interest, or, just for the fun of functional programming, such as playing with SKI combinator [1]. I did not think it would be used widely in real-world case, and even I think it should not be used that way. [1] http://en.wikipedia.org/wiki/SKI_combinator_calculus Usage example in my products: - An compiler for Grass (esoteric functional language) [2] - An interpreter for Unlambda (yet another esoteric functional language) [3] - An interpreter for SKI-based joke language [4] [2] https://github.com/mame/grass-misc/blob/master/yagc.rb [3] http://d.hatena.ne.jp/ku-ma-me/20090203/p1 (in Japanese) [4] https://github.com/mame/ikamusume In addition, I had another (ironical) intent; there is a lot of confusion between curry and partial application [5]. I wanted to preempt the name "curry" in a correct terminology. [5] http://lambda-the-ultimate.org/node/2266 -- Yusuke Endoh ---------------------------------------- Feature #6253: Implement a way to pass keyword options to curried procs https://bugs.ruby-lang.org/issues/6253#change-25652 Author: jballanc (Joshua Ballanco) Status: Assigned Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: core Target version: 2.0.0 =begin (See original discussion in issue #4610) With the introduction of keyword arguments in Ruby 2.0, it would be useful to have a way to set a keyword-based option on a curried proc. The example below demonstrates a Rack-like system where a curried proc is passed to a helper, then after partial application of the arguments, the returned curried proc is stored and later evaluated: class NicknameTranslator def initialize(app) @app = app end def call(name) case name when 'Robert' @app.call('Bob') when 'James' @app.call('Jimmy') else @app.call(name) end end end class NightGreeting def initialize(app) @app = app @app.pass_option(greeting: 'Goodnight') end def call(name) @app.call(name) end end class Greeter def initialize(helper) @helper = helper @app = lambda do |sender, receiver, greeting: 'Hello'| puts "#{sender} says \"#{greeting}\" to #{receiver}" end.curry @greetings = {} end def call(sender, receiver) @greetings[sender] ||= @helper.new(@app).call(sender) @greetings[sender].call(receiver) end end Greeter.new(NicknameTranslator).call('Josh', 'Joe') Greeter.new(NicknameTranslator).call('Robert', 'Joe') Greeter.new(NicknameTranslator).call('Josh', 'Robert') If we wanted, however, to be able to set a keyword-based option in the helper, there is currently no way in Ruby 2.0 to do so. Currently, keyword arguments can only be used at the same time as the final non-keyword, non-default, non-rest argument to the proc is applied. So, for example, there is no way to do the above with NightGreeting in place of NicknameTranslator. Currying is really only useful when it can be used with partial application. However, Ruby currently limits how you can achieve partial application of curried procs. In particular, there is no way to manage partial application of parameters with default values. As such, it is not surprising that Proc#curry does not seem to have been adopted very widely. In my personal survey of ~600 gems that I use in various projects, I did not find any usage of Proc#curry. So, I would request a method like Proc#pass_option (or some other, better name) that allows for setting keyword arguments on a curried proc at any time. =end -- http://bugs.ruby-lang.org/