如何在函数中处理多次后返回 int 变量?

问题描述 投票:0回答:3

我正在 OCaml 中编写一个函数,该函数读取字符串,验证它是否是整数并将其转换为整数,然后检查它是否包含在范围 [a,b] 内。验证工作正常,但我需要该函数最终返回数字。

let string_is_int s =
  try int_of_string s |> ignore; true
  with Failure _ -> false

let num_between a b = (
  let x = ref 0 in (
  (*validation loop*)
  let op = ref false in
  while not !op do        
    let x_string = read_line () in
    if string_is_int x_string then (
      let x_int = int_of_string x_string in
      if x_int>=a && x_int<=b then (
        op := true; 
        x := x_int;
      )
      else 
        Printf.printf "Invalid, enter again:  ";
    )        
    else 
      Printf.printf "Invalid, enter again:  ";         
  done
  )
)

let n = num_between 1 4;; 

我尝试在 while 循环末尾的括号后面添加“x”和“!x”,但出现错误

This expression has type unit 
This is not a function; it cannot be applied.

我知道 OCaml 没有关键字“return”。验证循环完成后如何返回 x?

function return ocaml
3个回答
0
投票

您的基本问题是 OCaml 中的

while
循环不返回值。它总是返回
()
,称为“单位”。

解决此问题的一种方法是编写自己的显式递归函数来返回所需的值。

另一种方法是将结果放在可以从循环外部访问的地方。事实上,你已经在这样做了。你只需要在最后添加这个:

done;
!x

如果您想尝试减少所使用的引用数量,您可以查看此函数,该函数返回它发现的第一个既是正方形又是回文数的 3 位数字:

let look () =
    let is_palindrome k =
        let s = string_of_int k in
        let slen = String.length s in
        let srev = String.init slen (fun i -> s.[slen - i - 1]) in
        s = srev
    in
    let rec loop k =
        if is_palindrome (k * k) then
           k * k
        else
            loop (k + 1)
    in
    loop 10

0
投票

欢迎来到 Stack Overflow!

这对我来说效果很好:

let num_between a b =
  let x = ref 0 in (
  (*validation loop*)
  let op = ref false in
  while not !op do        
    let x_string = read_line () in
    if string_is_int x_string then (
      let x_int = int_of_string x_string in
      if x_int>=a && x_int<=b then (
        op := true; 
        x := x_int;
      )
      else 
        Printf.printf "Invalid, enter again:  ";
    )        
    else 
      Printf.printf "Invalid, enter again:  ";         
  done
  );
  !x

它只是在

!x
循环结束后的括号后面添加
while
。您可能尝试将其放在错误的右括号之后(包含整个函数体的右括号,这是不需要的,我在这里将其删除;事实上,甚至不需要我留在此处的最外面的括号),或者也许您忘记了分号
;
!x
与前面的表达式分开。


0
投票

作为对此的补充,根本不需要使用 OCaml 的任何命令式功能来解决这个问题。我们只需要递归。退出情况将成功读取指定范围内的 int。

let read_int_between a b =
  match int_of_string_opt @@ read_line () with
  | Some n when n >= a && n <= b -> n
  | _ -> read_int_between a b
© www.soinside.com 2019 - 2024. All rights reserved.