https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112012-04-04T21:14:46ZRuby Issue Tracking SystemRuby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=256522012-04-04T21:14:46Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>matz (Yukihiro Matsumoto)</i></li></ul><p>Hello,</p>
<p>2012/4/4 jballanc (Joshua Ballanco) <a href="mailto:jballanc@gmail.com" class="email">jballanc@gmail.com</a>:</p>
<blockquote>
<p>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:<br>
<em>snip</em></p>
</blockquote>
<p>I think Proc#curry is not an appropriate answer to your problem.<br>
You should just create a new lambda:</p>
<pre><code>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
</code></pre>
<blockquote>
<p>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.</p>
</blockquote>
<p>In a sense, the situation is just as I expected :-)</p>
<p>I'm the person who made the proposal of Proc#curry in <a href="https://blade.ruby-lang.org/ruby-dev/33676">[ruby-dev:33676]</a>.<br>
I suggested it with purely theoretical interest, or, just for the fun<br>
of functional programming, such as playing with SKI combinator [1].<br>
I did not think it would be used widely in real-world case, and even<br>
I think it should not be used that way.</p>
<p>[1] <a href="http://en.wikipedia.org/wiki/SKI_combinator_calculus" class="external">http://en.wikipedia.org/wiki/SKI_combinator_calculus</a></p>
<p>Usage example in my products:</p>
<ul>
<li>An compiler for Grass (esoteric functional language) [2]</li>
<li>An interpreter for Unlambda (yet another esoteric functional<br>
language) [3]</li>
<li>An interpreter for SKI-based joke language [4]</li>
</ul>
<p>[2] <a href="https://github.com/mame/grass-misc/blob/master/yagc.rb" class="external">https://github.com/mame/grass-misc/blob/master/yagc.rb</a><br>
[3] <a href="http://d.hatena.ne.jp/ku-ma-me/20090203/p1" class="external">http://d.hatena.ne.jp/ku-ma-me/20090203/p1</a> (in Japanese)<br>
[4] <a href="https://github.com/mame/ikamusume" class="external">https://github.com/mame/ikamusume</a></p>
<p>In addition, I had another (ironical) intent; there is a lot of<br>
confusion between curry and partial application [5].<br>
I wanted to preempt the name "curry" in a correct terminology.</p>
<p>[5] <a href="http://lambda-the-ultimate.org/node/2266" class="external">http://lambda-the-ultimate.org/node/2266</a></p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=260192012-04-20T04:00:40Zjballanc (Joshua Ballanco)jballanc@gmail.com
<ul></ul><p>=begin<br>
I still want to think about this problem some more, but I also wanted to share some of my early thoughts...</p>
<p>I think that part of the problem with currying in Ruby is that we don't have the sort of type system that makes curried Procs so useful in languages like OCaml. For example, if you have a function in OCaml with the signature (({A -> B -> C})), then you have a guarantee that you can apply an instance of A to the first argument, and the result will still be a function. In Ruby, if you have a method defined like (({def foo(a_proc)})), and you #call the proc passed in, you can't know whether the result will still be a proc or whether it will be the result of executing the proc. For this reason, it makes far more sense to simply wrap procs in procs:</p>
<pre><code>def takes_curry(a_proc)
a_proc.call('hello') # <-- might return a value, or a proc
end
def takes_proc(a_proc)
proc do |other_arg|
a_proc.call('hello', other_arg)
end
# ^ definitely returns a proc that takes one more argument
end
</code></pre>
<p>However, I don't think that means that currying procs in Ruby is useless. On the contrary, now that we have keyword arguments, I think that a curried proc could make a very compelling substitute for the method object pattern:</p>
<pre><code>class NightParams
def self.parameterize(meth)
meth.greeting = 'Goodnight'
end
end
class QuestionParams
def self.parameterize(meth)
meth.punctuation = '?'
end
end
def parameterize_and_call(parameterizer, name)
method = proc do |name, greeting: 'Hello', punctuation: '!'|
puts "#{greeting}, #{name}#{punctuation}"
end.curry
parameterizer.parameterize(method)
method.call(name)
end
parameterize_and_call(NightParams, 'moon') #=> "Goodnight, moon!"
parameterize_and_call(QuestionParams, 'Joe') #=> "Hello, Joe?"
</code></pre>
<p>Any thoughts?<br>
=end</p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=275422012-06-28T17:05:44Zjballanc (Joshua Ballanco)jballanc@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/2824">6253-proposal.pdf</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/2824/6253-proposal.pdf">6253-proposal.pdf</a> added</li></ul><p>First feature request. Please let me know if PDF is not acceptable.</p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=276642012-07-02T00:41:55Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>Your slide is received. Thank you!</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=276812012-07-02T02:46:21Ztrans (Thomas Sawyer)
<ul></ul><p>Is the return value of #curry an instance of Method? Or is it some other thing in itself, e.g. a Curry object?</p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=276972012-07-02T06:04:02Zjballanc (Joshua Ballanco)jballanc@gmail.com
<ul></ul><p>=begin<br>
Currently, Proc#curry returns an instance of Proc.</p>
<p>Technically speaking, currying takes an n-arity Proc, and turns it into n nested 1-arity Procs. However, Ruby's implementation does not follow this strictly. In Ruby, currying a proc prepares it for partial application, but is not strict about the 1-arity rule (and also, negative-arity on the source proc causes further confusion).</p>
<p>More examples (because they're fun!):</p>
<p>Currently -<br>
>> def mult(a, b) a * b end<br>
=> nil<br>
>> times_two = method(:mult).to_proc.curry.(2)<br>
=> #<Proc:0x007fb9341bbe90 (lambda)><br>
>> times_two.(4)<br>
=> 8</p>
<p>Proposed future -<br>
>> def math(a, b, function: :*) a.send(function, b) end<br>
=> nil<br>
>> addition = method(:math).to_proc.curry<br>
=> #<Proc:0x007fb9341bbe90 (lambda)><br>
>> addition.function = :"+"<br>
=> :+<br>
>> add_two = addition.(2)<br>
=> #<Proc:0x007fb9341bbe90 (lambda)><br>
>> add_two.(6)<br>
=> 8<br>
=end</p> Ruby master - Feature #6253: Implement a way to pass keyword options to curried procshttps://bugs.ruby-lang.org/issues/6253?journal_id=283232012-07-23T23:09:42Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Rejected</i></li></ul><p>Joshua Ballanco,</p>
<p>Sorry but this proposal was rejected at the developer meeting (7/21).</p>
<p>Proc#curry is like an easter egg. Matz felt no need to care about the<br>
interaction between Proc#curry and other advanced features.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>