Ocaml counterpart for `continue` and `return` in programming workflow

Hey, in python I would have the following:

def f(x): 
  fn = get_fn(x)
  if fn is None: 
    return

  df = read_csv(fn)
  if df is None: 
    return 

  x = df.mean()
  return x

I guess the corresponding approach in Ocaml would be:

let f x = 
  get_fn x
  >>|
  (
    fun fn -> read_csv fn
  )
  >>|
  (
    fun df -> calc_mean df
  )

I encounter issues here when the last pipe depends on the output from the first pipe: I end up packing the output into a tuple:

def f(x): 
  fn = get_fn(x)
  if fn is None: 
    return

  df = read_csv(fn)
  if df is None: 
    return 

  if 'mean' in fn: 
    x = df.mean()
    return x
  else:
    x = df.std()
    return x

In ocaml:

let f x = 
  get_fn x
  >>|
  (
    fun fn -> 
      (read_csv fn, fn)
  )
  >>|
  (
    fun (df, fn) ->
    match String.find fn "mean" with 
    | true -> calc_mean df
    | false -> calc_std df
  )

Is this how things are supposed to be?

Assuming (>>|) is Option.bind, I think this would be more idiomatic

let f x =
  get_fn x >>| fun fn ->
  read_csv fn >>| fun df ->
  match String.find fn "mean" with
  | true -> calc_mean df
  | false -> calc_std df

(this is

let f x =
  get_fn x >>| (fun fn ->
  read_csv fn >>| (fun df ->
  match String.find fn "mean" with
  | true -> calc_mean df
  | false -> calc_std df))

but writing those parentheses is useless and would make auto-indenters drift to the right)

If you parenthesize less aggressively, you should still have fn in scope when you need it, without constructing that tuple.

Also, your boolean pattern-match could instead be an if-then-else.

e.g.

let f x =
  get_fn x >>= fun fn ->
  read_csv fn >>| fun df ->
  if String.find fn "mean" then
    calc_mean df
  else
    calc_std df

This could equivalently be written with let-ops, e.g.

let f x =
  let* fn = get_fn x in
  let+ df = read_csv fn in
  if String.find fn "mean" then
    calc_mean df
  else
    calc_std df

(That is all without seeing your actual definitions/types, of course ā€“ Iā€™m assuming the standard (>>|) = let+ = Option.map and (>>=) = let* = Option.bind)

1 Like

Thanks, that makes sense. Looks way cleaner now :slight_smile:

Hey @bennos , how do I install the let* and let+ support? I presume this is some ppx package.

those are ā€œlet operatorā€ syntax actually, not ppx. Depending on your standard library choices they may be available with open Option.Let_syntax or you can set up your project with something along the lines of let (let*) = Option.bind and let (let+) x f = Option.map f x