I’ve been learning OCaml for a compiler course, and while parsing s-expression I encountered the following scenario
... match (sexp_list : sexp list) with ... | Symbol(id)::rest when (id == keyword_add) -> (parse_binary Add ...) | Symbol(id)::rest when (id == keyword_sub) -> (parse_binary Sub ...) | Symbol(id)::rest when (id == keyword_mul) -> (parse_binary Mul ...) ...
Basically, I need to look into the first item of the list to decide what expression to parse it into.
Obviously there is a lot of duplicated code above, so here is what I attempted next.
match (sexp_list : sexp list) with ... | Symbol(id)::rest when (is_binary_keyword id) -> (parse_binary (binary_op id) ...) ...
Basically I checked whether the id belongs to the set of binary keyword, then abstract out the different constructor logic into
binary_op function. But this function could throw an error, we have a soft guarantee from the
when guard here, that whatever we passed to
binary_op would be a parsable id, and we are doing extra work.
So this is what I would really like to write, but it’s not valid OCaml syntax.
match (sexp_list : sexp list) with ... | Symbol(id)::rest with (binop = (binary_op id)) when (is_valid binop) -> (parse_binary binop ...) ...
I had quite limited experiences with pattern matching, and I still think of it as very convenient
if checking on runtime type tags. In this situation this is my mental model of what I’m trying to accomplish
... if sexp_list has form Symbol(id)::rest let binop := (binary_op id) if (is_valid binop) return (parse_binary binop ...) else doNothing, fall through to next pattern match if ...
I’m curious how would people usually handle such situation in OCaml, i.e. when we want to use computation result from the
when guard (or other things) in pattern match.