Difficulty with recursive let

I’m trying to use the Microsoft FluentUI components and in particular to figure out how many items are selected in a list when the list selection changes. But this seems to require a recursive let and I can’t figure out how to make it work and why it doesn’t work. I’ve tried the basic recursive definition of factorial and that works, so I don’t know why this doesn’t.

module Recusive = {
  type selection

  @module("fluentUI")
  external createSelection: (~onSelectionChanged: unit => unit) => selection = "createSelection"

  @module("fluentUI")
  external getSelectedCount: selection => int = "getSelectedCount"

  let rec s = createSelection(~onSelectionChanged=() => {
    Js.log("Selection changed.")
    let count = s->getSelectedCount // compile error
  })
}

This is how I solved it. I’m still curious why the original won’t work…

module Recusive = {
  type selection

  @module("fluentUI")
  external _createSelection: (~onSelectionChanged: unit => unit) => selection = "createSelection"

  @module("fluentUI")
  external getSelectedCount: selection => int = "getSelectedCount"

  let createSelection = (~onSelectionChanged: selection => unit) => {
    let selRef = ref(None)
    let sel = _createSelection(~onSelectionChanged=() =>
      selRef.contents->Option.forEach(onSelectionChanged)
    )
    selRef.contents = Some(sel)
    sel
  }
}

Copy paste the error message please so we can help you.

Sorry about that.

This kind of expression is not allowed as right-hand side of `let rec’

playground

AFAIK, the compiler treats recursive functions and recursive data (non-functions) differently. For a data value to be recursive, then it can’t be defined by calling a function like that.

This works:

let rec infinite_zeros = list{0, ...infinite_zeros}

This does not work, even though it theoretically does the same thing:

let append = (x, l) => list{x, ...l}
let rec infinite_zeros = append(0, infinite_zeros)
// ERROR: This kind of expression is not allowed as right-hand side of `let rec'

I believe this is related to how the compiler has to statically analyze the values, but someone else can probably explain the details better than me.

As far your particular createSelection problem, that looks like an awkward API. I’m not sure if there’s a better way to use that in ReScript besides what you came up with.