From: ritchie@... Date: 2018-11-17T16:54:38+00:00 Subject: [ruby-core:89846] [Ruby trunk Feature#15302] Proc#with and Proc#by, for partial function application and currying Issue #15302 has been updated by RichOrElse (Ritchie Buitre). shevegen (Robert A. Heiler) wrote: > I am not sure if the API seems ok. I am also not sure if matz > wants to have Symbols have methods such as .with(). For example, > to me personally it is not entirely clear why "with 2" would > be equal to "n * 2" as such. > > I am also not sure about the use case - it has not been > mentioned in this issue as far as I can see. > > However had, perhaps we should wait a bit on the upcoming > developer meeting this year anyway, because there have been > other proposed changes that are somewhat related to the issue > of how much class Symbol should be able to do - e. g. see > what Victor Shepelev suggested, linked in to > https://bugs.ruby-lang.org/issues/15229 for Symbol#call. > > Then we also know matz' opinion about class Symbol in > regards to any possible changes to it. Thank you for taking the time to review my proposal and for the suggestions. To illustrate more clearly how **Symbol#with** works, here's another example: ~~~ ruby [DateTime.new(2018,11,1), DateTime.new(2018,11,30)].map &:strftime.with("%m/%d/%Y") ~~~ Which is the same as the following: ~~~ ruby [DateTime.new(2018,11,1), DateTime.new(2018,11,30)].map { |d| d.strftime("%m/%d/%Y") } ~~~ Although #15229 **Symbol#call** is shorter than the functional equivalent proposal **Symbol#with**, the later's interface is consistent with **Proc#with** and **Method#with** where, as you are already aware, have their method **call** already taken. Here's a use case for *filling optional arguments*. Given a method named **greet**: ~~~ ruby def greet(name, greeting = 'hello') p "#{greeting.capitalize}! #{name}" end greet 'bob' # => "Hello! bob" ~~~ We can reuse the same method by pre-filling the last argument like so: ~~~ ruby module Spanish GREETINGS = method(:greet).with('hola') # Using Method#call would invoke the method instead of returning a Proc. end Spanish::GREETINGS['Roberto'] # => "Hola! Roberto" ~~~ ---------------------------------------- Feature #15302: Proc#with and Proc#by, for partial function application and currying https://bugs.ruby-lang.org/issues/15302#change-74905 * Author: RichOrElse (Ritchie Buitre) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- **Proc#by** allows currying implicitly ~~~ ruby class Proc def by(*head) return self if head.none? curry(head.size.next).(*head) end end class Method def by(*head) to_proc.by(*head) end end class Symbol def by(*head) to_proc.by(*head) end end double = :*.by(2) # => proc { |n| 2 * n } ~~~ **Proc#with** pre-defines trailing arguments and/or block. ~~~ ruby class Proc def with(*tail, &blk) if arity == tail.size.next proc { |head| call head, *tail, &blk } else proc { |*head| call *head, *tail, &blk } end end end class Method def with(*head, &blk) to_proc.with(*head, &blk) end end class Symbol def with(*head, &blk) to_proc.with(*head, &blk) end end double = :*.with(2) # => proc { |n| n * 2 } ~~~ That's the basic idea, but I've also expanded on it by optimising and defining operators (+, &, |) and other methods (Proc#such) [here](https://gist.github.com/RichOrElse/12d056be5757ec7ce540708bbac2b584). -- https://bugs.ruby-lang.org/ Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>