![]() |
Defining a new function by composition
Hi.
I would like to add a method to the Array class, say Array#pop! which is actually split!(-1). But then, I can think of a more general problem: define a new function by composition of two or more functions. In Haskell, I can do something like f :: a -> b -> c f x y = something g::b -> c g = f some_value What is the Ruby equivalent of this? Regards, Ed |
Re: Defining a new function by composition
"Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag news:478c16ae0408061209424c2032@mail.gmail.com... > Hi. > > I would like to add a method to the Array class, say Array#pop! which > is actually split!(-1). But then, I can think of a more general > problem: define a new function by composition of two or more > functions. > In Haskell, I can do something like > > f :: a -> b -> c > f x y = something > > g::b -> c > g = f some_value > > What is the Ruby equivalent of this? > > Regards, > Ed > > How about class Array def pop!() split!(-1) end end Note: pop! and split! are not functions but methods. So you always have an implicit argument (named 'self' in Ruby). I think this does not lend easily to chaining the way you seek. Of course, for the general case you could do something like this: module Kernel private def chain(name, *funcs) eval "def #{name}(*a) #{funcs.map {|f| "#{f}("}}*a#{")" * funcs.size} end" end end >> def foo(x) "<#{x}>" end => nil >> def bar(x) "[#{x}]" end => nil >> chain :xxx, :foo, :bar => nil >> xxx 100 => "<[100]>" Or a more functional approach: module Kernel private def chain2(*funcs) lambda {|*a| funcs.inject(a){|val, fun| send(fun, *val) } } end end >> xx2 = chain2 :bar, :foo => #<Proc:0x10169340@(irb):61> >> xx2.call 100 => "<[100]>" Note the different order. Regards robert |
Re: Defining a new function by composition
On Sat, 7 Aug 2004 04:46:25 +0900, Robert Klemme <bob.news@gmx.net> wrote:
> > "Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag > news:478c16ae0408061209424c2032@mail.gmail.com... > > > > I would like to add a method to the Array class, say Array#pop! which > > is actually split!(-1). But then, I can think of a more general > > problem: define a new function by composition of two or more > > functions. > > How about > > class Array > def pop!() split!(-1) end > end I imagined this. But, I thought you were going to surprise me with a weird (or unimagined) way to use alias ;-) Thanks, Ed |
Re: Defining a new function by composition
Edgardo Hames wrote:
>On Sat, 7 Aug 2004 04:46:25 +0900, Robert Klemme <bob.news@gmx.net> wrote: > > >>"Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag >>news:478c16ae0408061209424c2032@mail.gmail.com.. . >> >> >>>I would like to add a method to the Array class, say Array#pop! which >>>is actually split!(-1). But then, I can think of a more general >>>problem: define a new function by composition of two or more >>>functions. >>> >>> >>How about >> >>class Array >> def pop!() split!(-1) end >>end >> >> > >I imagined this. But, I thought you were going to surprise me with a >weird (or unimagined) way to use alias ;-) > > > Though this won't do what you want since there isn't a method split! for array. I think what you actually want is something like class Array def pop! slice!(-1, 1) end end This discussion did give me an idea for a curry method, that let's you predefine the parameters for a method. class Class def curry(newmethod, oldmethod, stored_params) send(:define_method, newmethod) do |*args| x = stored_params x += args if args send(oldmethod, *x) end end end then you can define pop! with class Array curry(:pop!, :slice!, -1, 1) end then x = [1,2,3] p x.slice! #=> 3 p x #=> [1,2] -- Mark Sparshatt |
Re: Defining a new function by composition
On Sat, 7 Aug 2004 06:27:11 +0900, mark sparshatt
<msparshatt@yahoo.co.uk> wrote: > > > > > > Though this won't do what you want since there isn't a method split! for > array. > Since there is a method push which modifies the receiver, I believe pop should do the same. I find it kind of odd this isn't so. Regards. Ed |
Re: Defining a new function by composition
mark sparshatt wrote:
[snip] > > then > x = [1,2,3] > p x.slice! #=> 3 that should of course be p x.pop! #=> 3 > p x #=> [1,2] > > -- > Mark Sparshatt > > > |
Re: Defining a new function by composition
[Edgardo Hames <ehames@gmail.com>, 2004-08-06 23.36 CEST]
> Since there is a method push which modifies the receiver, I believe > pop should do the same. I find it kind of odd this isn't so. $ ruby -e 'a=[1,2,3]; a.pop; p a' [1, 2] |
Re: Defining a new function by composition
"Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag news:478c16ae0408061345100e8692@mail.gmail.com... > On Sat, 7 Aug 2004 04:46:25 +0900, Robert Klemme <bob.news@gmx.net> wrote: > > > > "Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag > > news:478c16ae0408061209424c2032@mail.gmail.com... > > > > > > I would like to add a method to the Array class, say Array#pop! which > > > is actually split!(-1). But then, I can think of a more general > > > problem: define a new function by composition of two or more > > > functions. > > > > How about > > > > class Array > > def pop!() split!(-1) end > > end > > I imagined this. But, I thought you were going to surprise me with a > weird (or unimagined) way to use alias ;-) :-) Not possible because of the argument. Here's another solution - even more functional, although I still think this looks a bit more elegant in functional languages: def concat3(*fun) lambda {|*a| fun.inject(a) {|val,f| f.call(*val)} } end >> foo = lambda {|x| "<#{x}>"} => #<Proc:0x1019fac0@(irb):17> >> bar = lambda {|x| "[#{x}]"} => #<Proc:0x10194d38@(irb):18> >> xx3 = concat3 bar, foo => #<Proc:0x101b7250@(irb):15> >> xx3.call 100 => "<[100]>" >> xx3[ 100 ] => "<[100]>" As you can see, there are plenty ways to do this. And you can even use Ruby as a functional language, although I'd say best use is made of it if you use it OO. Regards robert |
| All times are GMT. The time now is 11:34 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.