为什么在这个非常简单的打印命令中出现语法错误

Why syntax error in this very simple print command

我正尝试运行遵循非常简单的代码:

open Str
print (Str.first_chars "testing" 0)

但是,它给出了以下错误:

$ ocaml testing2.ml 
File "testing2.ml", line 2, characters 0-5:
Error: Syntax error

错误消息中没有进一步的详细信息。

print_endline 同样的错误;或者即使没有打印命令。因此,错误部分是:Str.first_chars "testing" 0

here关于上述函数的文档如下:

val first_chars : string -> int -> string

first_chars s n returns the first n characters of s. This is the same function as Str.string_before.

在第二条语句的末尾添加 ;;; 没有任何区别。

以上代码的正确语法是什么。

编辑: 使用@EvgeniiLepikhin 建议的以下代码:

open Str
let () =
    print_endline (Str.first_chars "testing" 0)

错误是:

File "testing2.ml", line 1:
Error: Reference to undefined global `Str'

并使用此代码:

open Str;;
print_endline (Str.first_chars "testing" 0)

错误是:

File "testing2.ml", line 1:
Error: Reference to undefined global `Str'

在上面的代码中仅使用 print 命令(而不是 print_endline),错误是:

File "testing2.ml", line 2, characters 0-5:
Error: Unbound value print

注意,我的 Ocaml 版本是:

$ ocaml -version
The OCaml toplevel, version 4.02.3

我认为 Str 应该是内置的,因为 opam 没有找到它:

$ opam install Str
[ERROR] No package named Str found.

我还尝试按照@glennsl 评论中建议的代码进行操作:

#use "topfind"
#require "str"
print (Str.first_chars "testing" 0)

但这也同样简单syntax error

你应该加上;;在 "open Str" 之后:

open Str;;
print (Str.first_chars "testing" 0)

另一种选择是声明代码块:

open Str
let () =
    print (Str.first_chars "testing" 0)

OCaml 程序是 definitions 的列表,它们按顺序计算。您可以定义值、模块、classes、异常,以及类型、模块类型、class 类型。但到目前为止,让我们专注于价值观。

在 OCaml 中,没有语句、命令或说明。它是一个 functional programming language,其中一切都是表达式,当表达式被求值时它会产生一个值。该值可以绑定到一个变量,以便以后可以引用它。

print_endline 函数接受类型 string 的值,将其输出到标准输出通道,returns 接受类型 unit 的值。类型 unit 只有一个值称为 unit,可以使用 () 表达式构造。例如,print_endline "hello, world" 是生成此值的表达式。我们不能只是将表达式放入文件中并希望它会被编译,因为表达式不是定义。定义语法简单,

let <pattern> = <expr>

where 是变量或数据构造函数,它将与模式中出现的 <expr> 和可能绑定变量生成的值的结构相匹配,例如,以下是定义

let x = 7 * 8
let 4 = 2 * 2 
let [x; y; z] = [1; 2; 3]
let (hello, world) = "hello", "world"
let () = print_endline "hello, world"

你可能会注意到,print_endline "hello, world" 表达式的结果没有绑定到任何变量,而是与 unit() 匹配,可以看出 (确实看起来像)一个空元组。你也可以写

let x = print_endline "hello, world"

甚至

let _ = print_endline "hello, world"

但最好在定义的左侧明确表示您所期望的内容。

所以,现在我们的合式程序应该是这样的

 open Str

 let () = 
    print_endline (Str.first_chars "testing" 0)

我们将使用 ocamlbuild 编译和 运行 我们的程序。 str 模块不是标准库的一部分,所以我们必须告诉 ocamlbuild 我们要使用它。我们需要新建一个文件夹,把我们的程序放到一个名为example.ml的文件中,然后我们就可以使用下面的命令编译它

 ocamlbuild -pkg str example.native --

ocamlbuild 工具将从后缀 native 推断出您的目标是什么(在本例中是构建本机代码应用程序)。 -- 表示 运行 编译后立即构建应用程序。上面的程序不会打印任何内容,当然,这里有一个程序示例,它会在打印 testing 字符串的第一个零字符之前打印一些问候消息,

open Str

let () =
  print_endline "The first 0 chars of 'testing' are:";
  print_endline (Str.first_chars "testing" 0)

这是它的工作原理

$ ocamlbuild -package str example.native --
Finished, 4 targets (4 cached) in 00:00:00.
The first 0 chars of 'testing' are:

此外,您可以使用 ocaml 顶层工具直接解释 example.ml 文件,而不是编译您的程序并 运行 生成结果应用程序,该工具提供了一个交互式口译员。您仍然需要将 str 库加载到顶层,因为它不是预先链接在其中的标准库的一部分,这是正确的调用

ocaml str.cma example.ml