OCaml: Iterating through a list and skipping elements if of the wrong constructor
This may seem like an odd thing to do, and you're certainly welcome to suggest a better way to do it.
Here's my goal:
I want to scroll through each element of a list passed into a function. If it's of constructor Y, then I want to call some function on it. If it's of constructor Z, I want to skip it.
If there's a way to check this in an if statement, then that seems like the way to go since I don't need to write an else. However, I only know how to check this in a match.
For example:
let myFunct list =
List.iter (fun x -> match x with
| Y y -> otherFunction y
) list;;
Now, this gives me a warning about not being able to handle Z. So I could throw something in there like...
let myFunct list =
List.iter (fun x -> match x with
| Y y -> otherFunction y
| Z z -> (*skip*)
) list;;
Of course, I can't just leave Z's match blank....
How can I accomplish what I'm 开发者_如何学编程trying to do?
Just return unit (ie, ()
) the Z
case.
Are you sure you want List.iter
. It is primarily used to apply a function for its side effect.
A more idiomatic approach in functional programs is to filter the list using List.filter
and then apply a transformation to all the remaining elements using List.map
.
You could use List.filter
to filter the list based on the condition, then use List.iter
on the filtered list.
See the docs here for more info about the methods in the list module. http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html
I don't have access to the OCaml compiler at the moment but the code would look something like this:
List.iter (fun x -> ....) (List.filter (fun x -> ...) mylist)
Lambdageek's answer for List.iter
is right. You just need to use () as your result in any case where you don't have anything to do. All the different cases of your match
expression should return () when you're doing an iteration. That's what List.iter
is all about.
Everyone else is (rightly, in my opinion) worried that you might not really want to use List.iter
. It might be the first thing you think of when coming from other (imperative) languages, but iteration per se isn't at all as commonly used when doing functional programming. If you're learning OCaml in a course of some kind, it's even less likely that you want to use List.iter
. A course on OCaml would definitely begin by covering the functional parts. To think functionally you want to think about transforming values from one form to another (i.e., applying functions to them).
Let's say you did want to use List.filter
. Then, as you say, you'll end up doing a match
expression, but instead of returning () in all the different cases, you'd want to return a Boolean (true or false) in each case. If you return true, the value will be included in the resulting list. If you return false, the value won't be included in the resulting list. Once again, that's what List.filter
is all about. Here's some code that returns a new list containing just the elements of a given list that have a Z constructor.
let myFunc list =
List.filter
(fun x -> match x with Z _ -> true | _ -> false)
list
I'm not sure this helps, but I think what I'm trying to say is that using match
isn't difficult. You just need to cover every case. This is good, you want your code to work in every case!
精彩评论