here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
Ummm, why wouldn't we be able to use inject? I was under the impression that
inject was the functional way to do it in Ruby.
On 10/19/05, Andreas Semt <Andreas.Semt@gmx.net> wrote:
Hello list,
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
This looks more like the Haskell, but it's not idiomatic for Ruby. It
only looks like a standalone function, it's really a method on Object.
Ruby can be used this way, but it's going against the grain.
The Ruby way is definitely x.inject {|a,b| a + b}, or if you'll be
using it a lot:
class Array
def sum
inject {|a,b| a+b}
end
end
regards,
Ed
···
On Thu, Oct 20, 2005 at 03:41:09AM +0900, Andreas Semt wrote:
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
You can abuse Ruby arrays for lists:
def list_sum(l)
case l
when then 0
else l.first + list_sum(l[1, l.size])
end
end
list_sum([1,2,3]) # => 6
But using Array#slice for getting the "tail" of the "list" could be inefficient.
You could also use my lazylist gem and the do this:
require 'lazylist'
def list_sum(l)
case l
when LazyList::Empty then 0
else l.head + list_sum(l.tail)
end
end
list_sum list(1,2,3)
That way you can also create an infinite ones lazy list in Ruby with this nice notation:
ones = list(1) { ones } # => [1,... ]
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
anything that contradicts experience and logic should be abandoned.
-- h.h. the 14th dalai lama
I'm not going to answer your concrete question. I'm going to answer the question you should be asking....
The answer is with the exception of the the non '!' string methods and numbers most of ruby operations are non-"functional pure" in the sense that they have side effects and change state.
Thus to recapture "functional" programming purity in Ruby, for most objects and operations on them requires you to make very heavy use of the clone method. ie. Force yourself to go obj.clone.operation to make ruby into something like the "Self" language.
Certainly in some contexts (eg. when you can prove there are no other references to the object in question) a clone + modify is equivalent to just a modify. Thus you can make an optimization in such cases, but you will receive very little support from the language in proving this.
It doesn't even have C++'s "const" keyword. Although it does have "freeze", which unfortunately only works at run time after the object has been frozen, which tends to be a bit late.
On the other hand ruby is a "functional" language in the sense that procs, blocks and methods, etc are all first order objects and you can curry dice and slice them. It even has several flavours of eval.
John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand
Carter's Clarification of Murphy's Law.
"Things only ever go right so that they may go more spectacularly wrong later."
From this principle, all of life and physics may be deduced.
···
On Thu, 20 Oct 2005, Andreas Semt wrote:
Which is the best way to say it in Ruby (functional style)?
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
so many thanks for all your answers!
My original interest in this question was learning functional
programming, with both languages.
Ruby is my language of choice, so i try to compare both languages to
find out how much functional ruby can be. All the proposals are really
helpfull, both for understandig functional programming better *and* for
understanding the principles of ruby.
But inject *is* functional! It's equivalent to Lisp's accumulate. It
doesn't modify the list at all or have any side-effects.
Exactly.
Incidentally, the original example isn't really the best way to do this in
Haskell either. I haven't written any Haskell for a while, so some of this
might not be syntactically correct, but you get the idea. Please correct me
if any of this is wrong.
The above would best be expressed something like this (Iike I said, it's
been a while, so the parameter order might be wrong):
foldr + 0 list
foldr does exactly the same thing as inject. It takes a binary function, a
starting value, and a list. The neat thing about Haskell is that the
addition operator--actually any function--is automatically curried.
I'd make the claim here that the use of the higher order function is
actually better functional style than the explicit recursion.
If I recall correctly, many of the list functions in the Hugs standard
library are actually implemented this manner.
"Ara.T.Howard" <Ara.T.Howard@noaa.gov> wrote in message
news:Pine.LNX.4.62.0510191259580.28380@harp.ngdc.noaa.gov...
···
On Thu, 20 Oct 2005, Andreas Semt wrote:
Hello list,
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
You can abuse Ruby arrays for lists:
def list_sum(l)
case l
when then 0
else l.first + list_sum(l[1, l.size])
end
list_sum([1,2,3]) # => 6
Just for fun I was trying to see how visually close I could get to the
Haskell. The answer is... not very But the star operator
actually handles the x : xs list thing rather well:
def list_sum(x,*xs)
case xs
when : x # note: not 0 when done this way
else x + list_sum(*xs)
end
end
i don't think it is functional because the name of the function cannot be used
as a first class object. eg you cannot to
the_function = the_other_function
without calling 'the_other_function' __unless__ the objects in question are
first class objects. in ruby you must use lambda to acheive something close
to this. at least i think this right...
-a
···
On Thu, 20 Oct 2005, Louis J Scoras wrote:
But inject *is* functional! It's equivalent to Lisp's accumulate. It
doesn't modify the list at all or have any side-effects.
Exactly.
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
anything that contradicts experience and logic should be abandoned.
-- h.h. the 14th dalai lama
That can get a bit shorter too, since you don't need the (0) part.
Yeah. And I always hated it, that your program is going to crash, if "a" happens to be empty and you naively
use the inject result for further processing.
nice. still the functional vs. non is a very thin line in ruby:
harp:~ > cat a.rb
class << self
def list_sum x = nil, *xs
x ? x + list_sum(*xs) : 0
end
end
list_sum = method 'list_sum'
p list_sum[0b101000, 0b10]
p list_sum[42]
p list_sum
harp:~ > ruby a.rb
42
0
ps. i'm trying to wrap my mind around ocaml attm.
regards.
-a
···
On Thu, 20 Oct 2005, Dave Burt wrote:
"Ara.T.Howard" <Ara.T.Howard@noaa.gov> wrote in message
news:Pine.LNX.4.62.0510191259580.28380@harp.ngdc.noaa.gov...
On Thu, 20 Oct 2005, Andreas Semt wrote:
Hello list,
here a really simple Haskell function, which sums all elements of a list
(from the book "The Haskell School of Expression"):
--------------------------------
listSum = 0
listSum (x : xs) = x + listSum xs
--------------------------------
Which is the best way to say it in Ruby (functional style)? Don't use
'enum.inject', please!
OK, this is the first actually functional post -- list_sum is a first-class
function.
Here's my translation:
list_sum = Proc.new {|x, *xs| if x then x + list_sum[*xs] else 0 end }
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
anything that contradicts experience and logic should be abandoned.
-- h.h. the 14th dalai lama