Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Newbie query - the lack of a "range operator" in OCaml

649 views
Skip to first unread message

AndyE

unread,
Jan 7, 2002, 12:55:34 PM1/7/02
to
Hi everyone.

I imagine this has been asked before , but anyway ... .

I'm puzzled by the lack of a "range operator" in OCaml (i.e.
something like
[ 1 .. 10 ] to denote the range from one to ten. The reason I
mention this is that I saw one of the OCaml entries on this page -
http://www.uni-karlsruhe.de/~uu9r/lang/html/ocaml.en.html

The entry which outputs the squares from one to ten is -

List.map(function n -> n * n) [1;2;3;4;5;6;7;8;9;10];;

Ok - this can be done with a do-loop , but I'm still amazed that
something like [1..10] hasn't been included in the language. Is there
a (good!) reason for this?

( p.s. - I'm meaning to ask this in a "positive" frame of mind, as I
*like* OCaml. It's just that I find this quite puzzling ! .... :-)

Many thanks in advance for your comments!

Jeffrey M. Vinocur

unread,
Jan 7, 2002, 3:29:16 PM1/7/02
to
In article <a1cnem$6f8$1...@cantaloupe.srv.cs.cmu.edu>,

AndyE <andy....@paradise.net.nz> wrote:
>
> List.map(function n -> n * n) [1;2;3;4;5;6;7;8;9;10];;
>
> Ok - this can be done with a do-loop , but I'm still amazed that
>something like [1..10] hasn't been included in the language. Is there
>a (good!) reason for this?

Well, it would be a bit odd to have a special syntax for making
lists of consecutive integers. In SML, there are "tabulate"
functions, which work like this:

Standard ML of New Jersey, Version 110.0.7, September 28, 2000
- List.tabulate;
val it = fn : int * (int -> 'a) -> 'a list

- List.tabulate(7,fn x => x);
val it = [0,1,2,3,4,5,6] : int list

- List.tabulate(4,~);
val it = [0,~1,~2,~3] : int list

- List.tabulate(5,fn x => "datapoint" ^ (Int.toString x));
val it =
["datapoint0","datapoint1","datapoint2","datapoint3","datapoint4"]
: string list


And these exist for many datastructures, working the same way:

- Array.tabulate(4,~);
val it = [|0,~1,~2,~3|] : int array

It looks like in OCaml you can do:

Array.init 30 (fun x -> x*x)

but I don't know if there is an equivalent for lists.

--
Jeffrey M. Vinocur * jm...@cornell.edu
http://www.people.cornell.edu/pages/jmv16/

David McClain

unread,
Jan 8, 2002, 10:20:27 AM1/8/02
to
Jeffrey M. Vinocur wrote...

"Well, it would be a bit odd to have a special syntax for making
lists of consecutive integers."

---------------

Why would this be an odd thing? I find that immensely useful in my other
languages!

- David McClain, Sr. Scientist, Raytheon Missile Systems Co., Tucson, AZ


Brian Rogoff

unread,
Jan 8, 2002, 1:23:29 PM1/8/02
to
On 8 Jan 2002, David McClain wrote:
> Jeffrey M. Vinocur wrote...
>
> "Well, it would be a bit odd to have a special syntax for making
> lists of consecutive integers."
> ---------------
>
> Why would this be an odd thing? I find that immensely useful in my other
> languages!

I imagine Jeff considers it a bit odd since the special syntax seems to
buy you so little. I imagine you'd like something like ".." to be like
range pattern matching, but is this really immensely better than, say,
"interval n m"? I'm a big fan of infix syntax but I've confused myself
frequently when overdoing it.

I'd rather that interval were in the standard library (*) and then you
could make an infix syntax of your own.

-- Brian

(*) http://caml.inria.fr/archives/199910/msg00084.html


George Russell

unread,
Jan 8, 2002, 2:14:02 PM1/8/02
to
Rather than providing operators for generating lists of integers,
why not provide versions of fold and iterate which instead of taking a list
as argument, take instructions for constructing a list of integers? Then you
will have something equivalent to "for" in imperative languages, and you
won't have to go to the trouble of constructing a list and then throwing it away.
Something like the following (I apologise for any syntactical errors; I haven't
written much ML lately):

signature FORLOOPS =
sig

type elem
type sequence

range :: elem -> elem -> sequence
(* range a b is a, a+1, ..., b, or nothing if b<a *)
range_step :: elem -> elem -> elem -> sequence
(* range a b step is like range only with step rather than 1 *)
range_step_unbounded :: elem -> elem -> sequence
(* range a step is like range a b step, but never stops *)

fold_sequence :: ((elem* 'a) -> 'a) -> 'a -> sequence -> 'a
iterate_sequence :: (elem -> ()) -> sequence -> ()
map_sequence :: (elem -> 'a) -> sequence -> [a]

end

and then include a structure
structure ForLoops : FORLOOPS where type int = elem

for various flavours of integers.

doug

unread,
Jan 9, 2002, 10:18:36 AM1/9/02
to
andy....@paradise.net.nz (AndyE) writes:
> I'm puzzled by the lack of a "range operator" in OCaml (i.e.
> something like
> [ 1 .. 10 ] to denote the range from one to ten. The reason I
> mention this is that I saw one of the OCaml entries on this page -
> http://www.uni-karlsruhe.de/~uu9r/lang/html/ocaml.en.html
>
> The entry which outputs the squares from one to ten is -
>
> List.map(function n -> n * n) [1;2;3;4;5;6;7;8;9;10];;

Okay, sure, you have a good point that the specific code you point out
looks like tedious work to type ... but I think it is written that way
because it is an example in documentation.

My opinion on the matter is that in FP, you do not need to create a
*sequence* as often as in imperative languages. This is because in
FP languages, you usually have powerful ways to create sequences
functionally. In imperative languages a range function is handy so
you can generate values to iterate over. In Python, you can't live
without range, for instance. In functional programming ... I think
you don't need it much at all.

But, if you really, really want a list sequence ...

Instead of the proposed "interval" function, I prefer this:

let lseq n f =
let rec loop l m =
if m < 0 then l else loop ((f m) :: l) (pred m) in
loop [] (pred n)

Which is analogous to the Array.init function in Ocaml (orthogonality
is good), but it produces a list. Now you can define an integer range:

(* generate list of integers from n through m *)
let range n m = lseq (m - n + 1) (fun x -> x + n)

And you can type your example in the toplevel in a nicer way ...

# List.map(fun n -> n * n) (range 1 10);;
- : int list = [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]

Of course, if you don't mind using arrays in the first place, then the
example would be:

# Array.map(function n -> n * n) (Array.init 10 (fun x -> succ x));;
- : int array = [|1; 4; 9; 16; 25; 36; 49; 64; 81; 100|]

But to return to my original position ... if you show me where you
wish to use a sequence in Ocaml, I think it is probably possible to
refactor your code to be more functional.

cheers,
doug

Jeffrey M. Vinocur

unread,
Jan 10, 2002, 10:02:56 AM1/10/02
to
In article <a1fdf1$nsn$1...@cantaloupe.srv.cs.cmu.edu>,

Brian Rogoff <b...@bpr.best.vwh.net> wrote:
>On 8 Jan 2002, David McClain wrote:
>> Jeffrey M. Vinocur wrote...
>>
>> "Well, it would be a bit odd to have a special syntax for making
>> lists of consecutive integers."
>>
>> Why would this be an odd thing? I find that immensely useful in my other
>> languages!

I meant to add a disclaimer about scientific computation; I
assume you refer to e.g. Matlab, and yes, in such contexts it is
appropriate. But in ML...it doesn't fit with the paradigm.


>I imagine Jeff considers it a bit odd since the special syntax seems to
>buy you so little. I imagine you'd like something like ".." to be like
>range pattern matching, but is this really immensely better than, say,
>"interval n m"? I'm a big fan of infix syntax but I've confused myself
>frequently when overdoing it.
>
>I'd rather that interval were in the standard library (*) and then you
>could make an infix syntax of your own.

Ah, this is something I hadn't even thought of. Sure, defining
the appropriate function is not difficult, and making it infix if
desired isn't either. The issue comes down to what the grammar
permits (and what the parser can handle) as an identifier; I know
SML at least disallows what you're looking for, but lots of other
identifiers would work (say "1 --> 10", that seems reasonable).

AndyE

unread,
Jan 11, 2002, 7:58:52 AM1/11/02
to
Hi everyone :-)

Just a brief post to say "many thanks!" for all of your posts in
response to my query . They've all been very helpful to me (as a real
newcomer to OCaml ! ) .

Bye for now !

- Andy

0 new messages