> LçÉettçËäº Matt Maycock <ummaycoc / gmail.com> > Aihe: Re: Partial function application (was: Re: Binding precedence for first sym...) > > On Wed, 2 Feb 2005 02:50:44 +0900, Trans <transfire / gmail.com> wrote: > > Douglas Livingstone wrote: > > > How about this: > > > > > > def fun(z) > > > x = 1 > > > y = 2 > > > > > > # unmodified original > > > x = x + y + z > > > end > > > > > > Then you shouldn't need to worry about rewriting as they would act > > > more like defult params. > > > > Nice. > > This isn't even what he was asking for, though. The OP wanted a > `saved arguments' thing like currying... hardcoding in x and y is the > same as hardcoding 1 and 2 in the q (or x in OP's one example) = x + > y+ z... > > Also, I've made a few small updates to my curry file, if anyone is > interested (just default behaviors for certain methods invoked without > any information to use). Here's a naive, slightly more straightforward implementation (entirely untested): ######################## # class Proc / Extension # -- Extend Proc to enable currying. # If a block is invoked with too few arguments, it is # automatically converted to a 'new' block with the # given arguments bound to it in the fashion of currying. # If skipping an argument is desired, :_ can be used as # a placeholder: # # p = Proc.new {|a, b, c| a + b + c} # # p1 = p.call(1, 2) # ~ Proc.new {|c| 1 + 2 + c} # p2 = p.call(1, :_, 3) # ~ Proc.new {|b| 1 + b + 3} # # p.call(1, 2, 3) # => 6 # p1.call(3) # => 6 # p2.call(2) # => 6 # class Proc alias :proc_init :initialize alias :proc_call :call # initialize / Constructor # -- Create a normal Proc object and # initialize currying handling. def initialize(&block) # Initialize the block normally proc_init &block # Set up currying ar = block.arity # Block accepts any number of arguments? @catchall if ar < 0 # Number of required arguments @available = ar < -1 ? ar.abs : ar.abs - 1 # Set up the argument placeholders @args = Array.new @available, :_ end # Interface public # call / Interface method # -- Attempt to execute the method. If all required # arguments have not been received, the block will # be executed, otherwise the block will be curried # from the collected arguments. def call(*args) # Bind the remaining arguments bind_vars args # Curry if all arguments are not present return self if @available > 0 # Execute the block with the collected args proc_call @args end # [] / Interface method # -- Synonym for #call alias :[] :call # curry / Interface method # -- Explicitly curries the block from the given args. def curry(*args) # Bind only bind_vars args end # bind / Interface method # -- Synonym for #curry alias :bind :curry # Internals private # bind_vars / Internal method # -- Store the arguments given for future use. def bind_vars(args) # Ensure there are enough available slots raise ArgumentError if (@available -= args.length) < 0 and not @catchall # Replace the placeholders with the given arguments @args.map! do |arg| args.shift.dup if arg == :_ and end # Accept any remaining arguments if the block can take them @args << args if @catchall end end # class Proc ######################## The main issue, of course, is that extra syntax would be required to be able to curry methods rather than blocks. Once either () becomes overridable or something of that tune, this is more of a curiosity. Then there's of course the age-old question whether this is in any way a necessary addition to the language. It'd be nice to have an end-all-be-all language but some features just don't jive together. This one might. > Given that the OP mentioned Haskell, I think we should all try to come > up with some language that has the wonderfulness of Haskell with the > wonderful ness of Ruby. We could call it Rascal. Since Haskell cats > are all about domain specific languages, we could call DSLs in Rascal > "Little Rascals"... :-) Apparently merd (www.merd.net) is trying to fill this niche. The documentation is very sparse, though. > ~Me! E