31

From the other languages I program in, I'm used to having ranges. In Python, if I want all numbers one up to 100, I write range(1, 101). Similarly, in Haskell I'd write [1..100] and in Scala I'd write 1 to 100.

I can't find something similar in Erlang, either in the syntax or the library. I know that this would be fairly simple to implement myself, but I wanted to make sure it doesn't exist elsewhere first (particularly since a standard library or language implementation would be loads more efficient).

Is there a way to do ranges either in the Erlang language or standard library? Or is there some idiom that I'm missing? I just want to know if I should implement it myself.

I'm also open to the possibility that I shouldn't want to use a range in Erlang (I wouldn't want to be coding Python or Haskell in Erlang). Also, if I do need to implement this myself, if you have any good suggestions for improving performance, I'd love to hear them :)

2240
  • 1,547
  • 2
  • 12
  • 30
Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
  • It's hard to say whether you're doing the wrong thing. You've only said how you're trying to do something, not what you're trying to do. – Dustin Feb 02 '11 at 05:45
  • @Dustin I suppose what I mean is I want to know if I'm not thinking like I ought to in Erlang. – Rafe Kettler Feb 02 '11 at 05:47
  • As btilly points out, lists:seq/2 is the way to go! I can generally recommend looking at the lists module, it really very poweful. Oh, and look at http://www.erldocs.com – E Dominique Feb 02 '11 at 08:53
  • Can't tell if you're thinking about something right if you don't tell us what you're thinking about. There's functionality to do the exact thing you asked about, but that doesn't mean it's the right way to do whatever you're trying to do. It might be. Not enough information to make the judgment call, though. – Dustin Feb 02 '11 at 09:02

4 Answers4

57

From http://www.erlang.org/doc/man/lists.html it looks like lists:seq(1, 100) does what you want. You can also do things like lists:seq(1, 100, 2) to get all of the odd numbers in that range instead.

ndim
  • 35,870
  • 12
  • 47
  • 57
btilly
  • 43,296
  • 3
  • 59
  • 88
13

You can use list:seq(From, TO) that's say @bitilly, and also you can use list comprehensions to add more functionality, for example:

1> [X || X <- lists:seq(1,100), X rem 2 == 0].
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,
 44,46,48,50,52,54,56,58|...]
Shnatsel
  • 4,008
  • 1
  • 24
  • 25
0xAX
  • 20,957
  • 26
  • 117
  • 206
2

There is a difference between range in Ruby and list:seq in Erlang. Ruby's range doesn't create list and rely on next method, so (1..HugeInteger).each { ... } will not eat up memory. Erlang lists:seq will create list (or I believe it will). So when range is used for side effects, it does make a difference.

P.S. Not just for side effects:

(1..HugeInteger).inject(0) { |s, v| s + v % 1000000 == 0 ? 1 : 0 }

will work the same way as each, not creating a list. Erlang way for this is to create a recursive function. In fact, it is a concealed loop anyway.

Victor Moroz
  • 9,167
  • 1
  • 19
  • 23
  • Yeah, Erlang has no means for lazy evaluation. – Rafe Kettler Feb 04 '11 at 18:45
  • 1
    @Rafe Sure it does! Just use funs. – Daniel Yankowsky Feb 05 '11 at 16:21
  • @Daniel curse my early judgement of the language. I should read further into the tutorial. – Rafe Kettler Feb 06 '11 at 02:50
  • @DanielYankowsky, How would you implement lazy stream with funs in Erlang? Lets say we need to iterate through all odd numbers in a range [1..100] lazily. – Sharas May 31 '13 at 11:11
  • @Sharas the quick answer would be to use a generator function which, given a value in the stream, can produce the next value. So a "lazy list" would be a tuple of {initial value, generator function}. If that's not powerful enough, you could have the generator function instead generate the whole tail of the stream... which (being a stream itself) would be a tuple of {initial value, generator function}. Of course, none of the built-in list functions would work on such streams, so you would need to implement the ones you need. For more info, post a new question to SO... somebody will answer. – Daniel Yankowsky Jun 03 '13 at 21:22
1

Example of lazy stream in Erlang. Although it is not Erlang specific, I guess it can be done in any language with lambdas. New lambda gets created every time stream is advanced so it might put some strain on garbage collector.

range(From, To, _) when From > To ->
    done;
range(From, To, Step) ->
    {From, fun() -> range(From + Step, To, Step) end}.

list(done) ->
    [];
list({Value, Iterator}) ->
    [Value | list(Iterator())].

% ----- usage example ------

list_odd_numbers(From, To) ->
    list(range(From bor 1, To, 2)).
Sharas
  • 860
  • 8
  • 18