OCaml 测试字符串是否几乎为空或包含关键字
OCaml Test if a string is almost empty or contains keywords
我在 OCaml 中遇到了问题,我目前正在学习它,但我仍然是一个新手。我想创建一个函数,如果字符串为空或仅包含空格,则返回 true 并同时删除 begin
和 end
.
的任何出现
我已经试过了:
let isEmptyString s =
let rec empty i =
if i < 0 then true
else
let c = String.get s i in
if c = ' ' || c = '[=10=]9' then empty (pred i)
else false
in
s = Str.global_replace( Str.regexp "begin") "" s;
s = Str.global_replace( Str.regexp "end") "" s;
empty (pred (String.length s))
但很明显,这个函数没有像我希望的那样工作,因为我在调用它之后在 Formula.importNrAgentsFormula
中仍然获得 begin
...这是我调用它的方式:
while true do
let input = read_line () in
if not (isEmptyString input) then
let (nr, f) = Formula.importNrAgentsFormula input in
incr counter;
flush stdout;
match choice with
| "graph" -> printRes (Graph.isSat ~verbose:verb nr f)
| _ -> printUsage ()
else ()
done
如果有更多 OCaml 经验的人能够发现错误并向我解释,我将很高兴:)
提前致谢,
此致。
因为我在工作,所以我没有随身携带 utop,但乍一看,在您的第一个文件中,文档说:
val global_replace : regexp -> string -> string -> string
这意味着您不需要“;”因为那是用于 when 函数 return 单元并且是诸如
之类的语法糖
let () = print_endline("foobar")
此外,您需要使用 let 语句,因为您不能只重新分配 s 的值。我不建议隐藏变量,因为这在函数式编程中通常是不好的做法。使用类似:
let t = (Str.global_replace( Str.regexp "begin") "" s)
另外,你的函数做了两件不同的事情。您编写的辅助递归函数 returns true 和 false 这很好(我假设它有效)。然而,您最终使用它的目的是 returning。因此,对于第一个函数,如果 "begin" 和 "end" 已被替换,那么您并不是真正地 returning 字符串。因此,您应该让函数的最终输出实际上是一个类型为 (bool,string) 的元组。然后你可以在调用它时匹配它(例如
let b,s = isEmptyString "foobar" in
if not b then:
rest of your code
我相信你对你的功能有正确的想法。
同样在你的第二个函数中,有没有办法让你不使用任何 while 循环和计数器? (也希望你的计数器是用引用实现的,否则你将没有任何全局的东西)。我建议重试你调用第一个函数的地方,因为循环和计数器是命令式编程的核心而不是功能性的(这就是 OCaml 如此
fun
:)。如果不是,没关系,有时如果不使用 OCaml 的命令式功能,您就无法真正做到这些事情。如果这些建议不起作用,请告诉我。
我建议你让你的函数 isEmptyString
(isBlankString
而不是?)做它应该做的(只是检查它是否只包含空格或什么都不包含),它不应该修改原来的细绳。您可以在循环中执行此操作:
while true do
let input = read_line () in
let input = Str.global_replace( Str.regexp "begin") "" input in
let input = Str.global_replace( Str.regexp "end") "" input in
if not (isEmptyString input) then
...
编辑:抱歉编辑晚了,这里有一些关于你的错误的附加信息:
如果你 运行 你的函数在 OCaml 中,你会看到这个警告:
Warning 10: this expression should have type unit.
在 s = Str.global_replace( Str.regexp "begin") "" s;
线上。这是因为 OCaml 中的 =
运算符在这种情况下不是赋值运算符,而是相等运算符,所以在这一行中,您只需比较两个值和 return 一个布尔值。由于 OCaml 期望 e1
in e1;e2
到 return unit
,您会收到此警告。
在 OCaml 中,变量的值是不可变的,因此您可以:
- 按照@Jason 的建议使用另一个变量:
let t = Str.global_replace( Str.regexp "begin") "" s
- "shadow" 我上面建议的旧值:
let s = Str.global_replace( Str.regexp "begin") "" s
- 使用引用(指向内存中某个位置的指针):
let s = ref "before" in s := "after"
,然后您可以使用 !
运算符访问引用指向的值:!s
。但是,如果你正在学习函数式编程,我建议你一开始就尽量不要使用 OCaml 的任何命令式特性来发现这种新范式及其可能性。
我在 OCaml 中遇到了问题,我目前正在学习它,但我仍然是一个新手。我想创建一个函数,如果字符串为空或仅包含空格,则返回 true 并同时删除 begin
和 end
.
我已经试过了:
let isEmptyString s =
let rec empty i =
if i < 0 then true
else
let c = String.get s i in
if c = ' ' || c = '[=10=]9' then empty (pred i)
else false
in
s = Str.global_replace( Str.regexp "begin") "" s;
s = Str.global_replace( Str.regexp "end") "" s;
empty (pred (String.length s))
但很明显,这个函数没有像我希望的那样工作,因为我在调用它之后在 Formula.importNrAgentsFormula
中仍然获得 begin
...这是我调用它的方式:
while true do
let input = read_line () in
if not (isEmptyString input) then
let (nr, f) = Formula.importNrAgentsFormula input in
incr counter;
flush stdout;
match choice with
| "graph" -> printRes (Graph.isSat ~verbose:verb nr f)
| _ -> printUsage ()
else ()
done
如果有更多 OCaml 经验的人能够发现错误并向我解释,我将很高兴:)
提前致谢,
此致。
因为我在工作,所以我没有随身携带 utop,但乍一看,在您的第一个文件中,文档说:
val global_replace : regexp -> string -> string -> string
这意味着您不需要“;”因为那是用于 when 函数 return 单元并且是诸如
之类的语法糖let () = print_endline("foobar")
此外,您需要使用 let 语句,因为您不能只重新分配 s 的值。我不建议隐藏变量,因为这在函数式编程中通常是不好的做法。使用类似:
let t = (Str.global_replace( Str.regexp "begin") "" s)
另外,你的函数做了两件不同的事情。您编写的辅助递归函数 returns true 和 false 这很好(我假设它有效)。然而,您最终使用它的目的是 returning。因此,对于第一个函数,如果 "begin" 和 "end" 已被替换,那么您并不是真正地 returning 字符串。因此,您应该让函数的最终输出实际上是一个类型为 (bool,string) 的元组。然后你可以在调用它时匹配它(例如
let b,s = isEmptyString "foobar" in
if not b then:
rest of your code
我相信你对你的功能有正确的想法。 同样在你的第二个函数中,有没有办法让你不使用任何 while 循环和计数器? (也希望你的计数器是用引用实现的,否则你将没有任何全局的东西)。我建议重试你调用第一个函数的地方,因为循环和计数器是命令式编程的核心而不是功能性的(这就是 OCaml 如此
fun
:)。如果不是,没关系,有时如果不使用 OCaml 的命令式功能,您就无法真正做到这些事情。如果这些建议不起作用,请告诉我。
我建议你让你的函数 isEmptyString
(isBlankString
而不是?)做它应该做的(只是检查它是否只包含空格或什么都不包含),它不应该修改原来的细绳。您可以在循环中执行此操作:
while true do
let input = read_line () in
let input = Str.global_replace( Str.regexp "begin") "" input in
let input = Str.global_replace( Str.regexp "end") "" input in
if not (isEmptyString input) then
...
编辑:抱歉编辑晚了,这里有一些关于你的错误的附加信息:
如果你 运行 你的函数在 OCaml 中,你会看到这个警告:
Warning 10: this expression should have type unit.
在 s = Str.global_replace( Str.regexp "begin") "" s;
线上。这是因为 OCaml 中的 =
运算符在这种情况下不是赋值运算符,而是相等运算符,所以在这一行中,您只需比较两个值和 return 一个布尔值。由于 OCaml 期望 e1
in e1;e2
到 return unit
,您会收到此警告。
在 OCaml 中,变量的值是不可变的,因此您可以:
- 按照@Jason 的建议使用另一个变量:
let t = Str.global_replace( Str.regexp "begin") "" s
- "shadow" 我上面建议的旧值:
let s = Str.global_replace( Str.regexp "begin") "" s
- 使用引用(指向内存中某个位置的指针):
let s = ref "before" in s := "after"
,然后您可以使用!
运算符访问引用指向的值:!s
。但是,如果你正在学习函数式编程,我建议你一开始就尽量不要使用 OCaml 的任何命令式特性来发现这种新范式及其可能性。