user1514567
user1514567

Reputation: 91

Multiple operations within one match pattern Ocaml

I had an Ocaml issue resolved earlier but I am wondering if there is a best way to optimize my solution as I have tried all avenues and since I am very new to Ocaml I cannot really figure it out. I have a pattern function that does pretty printing and then another function that adds to a set. The pretty printing function is as follows:

let rec processoperatorchange fmt = function
| Zero -> Format.fprintf fmt "0"
| Pproc x -> Format.fprintf fmt "%s" x
| Procdef (p1, x) -> Format.fprintf fmt "%s(%s)"  p1  x
| Par (p1, p2) -> Format.fprintf fmt "(%a + %a)" processoperatorchange p1 processoperatorchange p2
| Concur(p1, p2) -> Format.fprintf fmt "(%a | %a)" processoperatorchange p1 processoperatorchange p2
| Rep(p) -> Format.fprintf fmt "!(%a)" processoperatorchange p

and I have another function that does the same thing but then changes the format of printing (this seems inefficient but I just cannot figure out the best way to make this better)

let rec processoperatorchange2 fmt = function
| Zero -> Format.fprintf fmt "0"
| Pproc x -> Format.fprintf fmt "%s" x
| Procdef (p1, x) -> Format.fprintf fmt "%s(%s)"  p1  x
| Par (p1, p2) -> Format.fprintf fmt "(%a | %a)" processoperatorchange2 p1 processoperatorchange2 p2
| Concur(p1, p2) -> Format.fprintf fmt "(%a + %a)" processoperatorchange2 p1 processoperatorchange2 p2
| Rep(p) -> Format.fprintf fmt "!(%a)" processoperatorchange2 p

Based on these functions, I have another function that calls to add to a set:

let op_change p set = concattoset (Format.asprintf "%a" processoperatorchange p) set |>
                    concattoset (Format.asprintf "%a" processoperatorchange2 p)

The code for concattoset is:

let concattoset s set = SS.add s set

However, is there a way I can optimize this code such that I can condense the two functions processoperatorchange and processoperatorchange2 into one function and add all this to the set? The main problem here is the I need to perform a change on a user defined input from the user and then add this change to a set and if there is no change, return an empty set but with the way its being done now, if there is no change I still add to the set because I do the function call to add to the set separately but can I condense all this into one function?

Upvotes: 1

Views: 528

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66818

Your functions are the same except for the characters used for Par and Concur. You can pass these characters as parameters. This gives you a function like this:

let rec processoperatorchange pc cc fmt = function
| Zero -> Format.fprintf fmt "0"
| Pproc x -> Format.fprintf fmt "%s" x
| Procdef (p1, x) -> Format.fprintf fmt "%s(%s)"  p1  x
| Par (p1, p2) ->
    Format.fprintf fmt "(%a %c %a)"
        (processoperatorchange pc cc) p1 pc (processoperatorchange pc cc) p2
| Concur(p1, p2) ->
    Format.fprintf fmt "(%a %c %a)"
        (processoperatorchange pc cc) p1 cc (processoperatorchange pc cc) p2
| Rep(p) ->
    Format.fprintf fmt "!(%a)"
        (processoperatorchange pc cc) p

If you call this function like this:

processoperatorchange '+' '|'

it acts like your original processoperator function. If you call it like this:

processoperatorchange '|' '+'

it acts like processoperator2.

So you can rewrite op_change like this:

let op_change p set =
    concattoset (Format.asprintf "%a" (processoperatorchange '+' '|') p) set |>
    concattoset (Format.asprintf "%a" (processoperatorchange '|' '+') p)

Upvotes: 2

Related Questions