"let()="和"let _ ="之间的区别是什么?

z_a*_*xis 12 ocaml

let () = Random.self_init();;
let _ = Random.self_init ();;
?- : unit = ()
Run Code Online (Sandbox Code Playgroud)

看来"let()"什么都不返回?

祝商祺!

jro*_*uie 20

let 是用于定义新变量的关键字,如以下构造中所示:

let pattern = expr
Run Code Online (Sandbox Code Playgroud)

例如

let a = 2
Run Code Online (Sandbox Code Playgroud)

将值分配2给名称a.(注意,这不是为现有变量赋值的方法,但这是另一个主题).

但是=标志左边的图案可能不仅仅是一个名字.例如

let (a,b) = (42,"foo")
Run Code Online (Sandbox Code Playgroud)

定义both ab,分别42"foo".当然,双方的类型必须匹配.这是这种情况:双方都是类型int * string.

=例如,也可以详细说明符号右侧的表达式

let foo =
  let temp = String.make 10 'a' in
  temp.[2] <- 'b';
  temp
Run Code Online (Sandbox Code Playgroud)

定义foo为字符串"aabaaaaaaa".(作为旁注,它还确保temp该代码片段是本地的).

现在,让我们使用两者:左边是匹配类型值的模式unit,右边是类型的表达式unit:

let () = Printf.printf "Hello world!\n"
Run Code Online (Sandbox Code Playgroud)

这解释了let () =构造.现在,关于let _,只需要知道_可以在模式中用作通配符:它匹配任何类型的值并且不绑定任何名称.例如

let (a,_) = (42,"foo")
Run Code Online (Sandbox Code Playgroud)

定义a42,并丢弃该值"foo"._意思是"我知道这里有一些东西,我明确地说我不会使用它,所以我没有说出来".这里_用于匹配类型的值string,但它可以匹配任何类型的值,如int * string:

let _ = (42,"foo")
Run Code Online (Sandbox Code Playgroud)

它没有定义任何变量,也不是很有用.当右侧有副作用时,这样的结构很有用,如下所示:

let _ = Printf.printf "Hello world!\n"
Run Code Online (Sandbox Code Playgroud)

这解释了问题的第二部分.



实用的目的

两者都被使用,无论是使用其中一种,都是一种品味问题.

let () =稍微安全一点,因为编译器会检查右侧是否为类型unit.除单位以外的任何其他类型的值通常都是错误.

let _ =略短(我见过这个论点).(注意,使用自动关闭括号的编辑器,击键次数是相同的;-)

  • 如果你评价副作用的"e",那么底线永远不会使用`let _ = e`.即使你需要忽略一个结果值,也可以使用`let()= ignore(e)`.有一天你会浪费你的时间因为你在'e`中有部分应用而没有任何反应.例如,编译`let _ = Printf.printf"%d"`报告没有警告.仅当您想要构造一个值并忽略它的某些部分时才使用`_`. (8认同)
  • `let是用于定义变量的关键字 - 请不要!`let`在范围内引入了新的绑定. (4认同)