免责声明:我是ReasonML初学者。

我最近开始使用ReasonML,并且发现与原始JavaScript相比,性能存在很大差异。这是我针对简单难题解决功能的示例(难题取自https://adventofcode.com/2015/day/1)

ReasonML

let head = str =>
  switch (str) {
  | "" => ""
  | _ => String.sub(str, 0, 1)
  };

let tail = str =>
  switch (str) {
  | "" => ""
  | _ => String.sub(str, 1, String.length(str) - 1)
  };

let rec stringToList = str =>
  switch (str) {
  | "" => []
  | _ => [[head(str)], tail(str) |> stringToList] |> List.concat
  };

let rec findFloor = code =>
  switch (head(code)) {
  | "" => 0
  | "(" => 1 + findFloor(tail(code))
  | ")" => (-1) + findFloor(tail(code))
  | _ => 0
  };

let findFloorFold = code => {
  let calc = (a, b) =>
    switch (b) {
    | "" => a
    | "(" => a + 1
    | ")" => a - 1
    | _ => a
    };

  code |> stringToList |> List.fold_left(calc, 0);
};

JavaScript
const solve = code => {
  let level = 0;
  for (let i = 0, l = code.length; i < l; i++) {
    const el = code[i];
    if (el === "(") {
      ++level;
      continue;
    }
    if (el === ")") {
      --level;
      continue;
    }
  }
  return level;
};

结果
  • JavaScript: 5毫秒
  • ReasonML(递归): 470毫秒
  • ReasonML(非递归): 7185ms

  • 这是预期的还是我的ReasonML函数实现太慢?

    在此先感谢您的澄清/建议。

    诚然,第二个解决方案(非rec)由于将字符串转换为数组而速度较慢,但​​这是因为在ReasonML中,字符串不是由字符列表表示的。

    最佳答案

    您可以在Reason中编写与在JS中相同的命令式代码,并且实际上使其更快(在我的计算机上提高了30%):

    let findFloorImperative = code => {
      let level = ref(0);
      for (i in 0 to String.length(code) - 1) {
        switch (code.[i]) {
        | '(' => level := level^ + 1
        | ')' => level := level^ - 1
        | _   => failwith("invalid code")
        }
      };
      level^
    };
    

    这个递归解决方案几乎一样快:
    let findFloorRecursiveNoList = code => {
      let rec helper = (level, i) =>
        if (i < String.length(code)) {
          switch (code.[i]) {
          | '(' => helper(level + 1, i + 1)
          | ')' => helper(level - 1, i + 1)
          | _   => failwith("invalid code")
          }
        } else {
          level
        };
    
      helper(0, 0)
    };
    

    基准测试结果:
    Reason, imperative:            19,246,043 ops/sec
    Reason, recursive, no list:    18,113,602 ops/sec
    JavaScript, imperative:        13,761,780 ops/sec
    Reason, recursive, list:       481,426 ops/sec
    Reason, folding, list:         239,761 ops/sec
    

    Source: re:bench

    10-06 00:26