# Formatting O'Caml code

This topic is 4146 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm having considerable trouble applying my typical indenting behavior (or in fact, any indenting behavior) to O'Caml in a way that makes sense. Here's the snip I'm messing with:
let rec map_test f test l =
(
match l with
[] -> []
);;


As is, it's already a mess, and I'm not sure what's traditional to make this look pretty and nice.

##### Share on other sites
Any reason why you're creating a list of one-element lists?

Either way, I would indent it as:

let rec map_test f test = function  | [] -> []  | h::t ->     (if test h then f h else h) :: (map_test f test t)

Or (but this is beyond the scope of the thread) :
let map_test f test =  List.map (fun x -> if test x then f x else x)

##### Share on other sites
Quote:
 Original post by ToohrVykAny reason why you're creating a list of one-element lists?
I thought @ appended lists. What exactly is the difference between :: and @? Actually, I don't really understand why your code differs but does the same thing. "match" removed and just "function" there, for example.

##### Share on other sites
Quote:
 Original post by PromitI thought @ appended lists. What exactly is the difference between :: and @?

Disregard my comment, I had read "::" instead of "@" in your code. @ appends arbitrary lists (which means both lists are evaluated and concatenated in potentially linear time), while :: constructs a new list from a head and a tail (which is universally faster than concatenation, and draws an elegant parallel with pattern matching).

Also, [a] is syntactic sugar for a::[].

Quote:
 Actually, I don't really understand why your code differs but does the same thing. "match" removed and just "function" there, for example.

let a x = match x with is equivalent with let a = function, so the second is usually more idiomatic because it's shorter. let a = fun is slightly different in its pattern matching potential (it can pattern-match several arguments at once).

##### Share on other sites
:: is the 'cons' operator and appends an element to the front of the list. @ joins two lists. In your case...I don't think there is much of a speed difference.

But normally, a @ b is essentially just:
a' = List.reverse(a), then a loop to :: each element in a' onto b.

...if I am not mistaken, which I may be. Either way, @ is 'slow'.

As for your indenting behavior ... well, I don't use OCaml, but SML is similar enough. As far as it goes, I don't see anything particularly wrong. Personally I just prefer to use 3 spaces so you don't get so much whitespace -- but you have the general idea in my opinion.

With most functional languages, I have generally found this statement to be true: if you code looks terse and ugly, there is probably a more elegant solution.

As Toohr points out, a List.map is much more elegant solution.

EDIT: Egads, Toohr beat me to a response. Ignore everything I say.

##### Share on other sites
:: creates a pair where the first element is the head of the list and the second is the tail, which is a list by itself. That is how lists are built in ml, ie. [1, 2, 3, 4] is actually 1 :: (2 :: (3 :: (4 :: NIL))).

So when you do x :: y the result is the list [x, y1, y2, y3, ..., yn] (x is anything and y is a list) whereas x @ y results in [x1, x2, ..., xn, y1, y2, y3, ..., yn]. The former is constant time O(1) where the later is linear time O(n).

Appending can be implemented by consing (::) all the elements of x on the list of y.

##### Share on other sites
Quote:
 Original post by visageBut normally, a @ b is essentially just:a' = List.reverse(a), then a loop to :: each element in a' onto b.

Functionally, in O'Caml, a @ b may be:
let prefix @ l1 l2 =  let rec aux = function     | [] -> l2    | h::t -> h :: (aux t)  in aux l1

It's not guaranteed to be tail-recursive.

An alternative is List.rev_append (List.rev a) b, which is tail-recursive but traverses the list twice.

Last but not least, it would theoretically be possible to implement concatenation as a very fast and constant-space native operation (by creating the list before creating its tail), but I don't think this is done.

##### Share on other sites
Quote:
 Original post by visageAs Toohr points out, a List.map is much more elegant solution.
Yeah, but it's homework, so I don't get to use library functions whenever.

##### Share on other sites
Quote:
 let a x = match x with is equivalent with let a = function, so the second is usually more idiomatic because it's shorter. let a = fun is slightly different in its pattern matching potential (it can pattern-match several arguments at once).

Interesting. I had thought the match with style was preferred because it is clearer the number of arguments required to fully apply the function. The let ... = function style requires that you look either side of the equals sign. On the other hand, I sometimes use the function style because the match with style results in a certain amount of local namespace pollution (i.e. you name something that is rarely used in the function body).

Something I've wondered, is there a concensus on when partially applied functions should be used? I tend too avoid using them to much since, to me at least, they tend to reduce readability (although they can be very useful in some situations). Is this idiomatic Ocaml?

##### Share on other sites
Quote:
 Original post by OralloyInteresting. I had thought the match with style was preferred because it is clearer the number of arguments required to fully apply the function. The let ... = function style requires that you look either side of the equals sign.

The number of arguments is not something very important. First, it's nearly impossible to use an incorrect number of arguments in your program without the compiler complaining (the only ordinary way being, essentially, let _ = foo a at file scope).

What is more important is function semantics, which should be obvious from the function name. If the name isn't enough, then the type and possibly the documentation provide additional information about the semantics. And once you know the semantics, you can't get the argument count or order wrong.

Quote:
 Something I've wondered, is there a concensus on when partially applied functions should be used? I tend too avoid using them to much since, to me at least, they tend to reduce readability (although they can be very useful in some situations). Is this idiomatic Ocaml?

It's idiomatic to use partially applied functions as arguments to other functions, or as local variables to increase readability. Some people also η-reduce functions to make code shorter, but it's not common except on extremely small and straightforward functions.

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 9
• 23
• 9
• 32
• ### Forum Statistics

• Total Topics
632625
• Total Posts
3007508
• ### Who's Online (See full list)

There are no registered users currently online

×