OCaml:Stream.peek不使用消费行?
我正在编写一个程序,该程序在输入文件上进行迭代,程序数可变,以“0”结尾。如果我从文件的顶部开始运行函数,它可以正常工作,但由于某种原因,通过查看下一个字符是否为“0”(表示文件的结尾)会占用一行 这是我的密码:OCaml:Stream.peek不使用消费行?,stream,ocaml,Stream,Ocaml,我正在编写一个程序,该程序在输入文件上进行迭代,程序数可变,以“0”结尾。如果我从文件的顶部开始运行函数,它可以正常工作,但由于某种原因,通过查看下一个字符是否为“0”(表示文件的结尾)会占用一行 这是我的密码: let line_stream_of_channel channel = Stream.from (fun _ -> try Some (input_line channel) with End_of_file -> None);;
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream != Some "0" do
run in_channel;
print_string "...\n";
done;;
从我所读到的来看,Stream.peek不应该占用一行代码,所以问题可能不是由此产生的,但如果不是,我就不知道它在做什么。有什么想法吗
编辑以下是我的整个程序:
let hello c =
print_char c;;
let hello_int c =
print_int c;
print_char '\n';;
let ios = int_of_string;;
let rec print_string_list = function
[] -> print_string "\n"
| h::t -> print_string h ; print_string " " ; print_string_list t;;
let rec print_int_list = function
[] -> print_string "\n"
| h::t -> print_int h ; print_string " " ; print_int_list t;;
let rec append l i =
match l with
[] -> [i]
| h :: t -> h :: (append t i);;
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let string_to_int_list str_list int_list=
let len = List.length str_list in
for i = 0 to len - 1 do
int_list := append !int_list (ios (List.nth str_list i));
done;;
let get_option = function
| Some x -> x
| None -> raise (Invalid_argument "Option.get");;
let chomp_line ns in_channel =
let s = input_line in_channel in
let len = String.length s in
let start_pos = ref 0 in
for i = 0 to len do
if i == len then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
else if s.[i] == ' ' then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
start_pos := i + 1;
done;;
let run in_channel =
let ns = ref [] in
chomp_line ns in_channel;
let n = ios (List.nth !ns 0) in
let p = ios (List.nth !ns 1) in
let s = ios (List.nth !ns 2) in
print_string "num dulls: "; hello_int n;
print_string "num programs: "; hello_int p;
print_string "num state transitions: "; hello_int s;
let dull_sizes = ref [] in
chomp_line dull_sizes in_channel;
let int_dull_sizes = ref [] in
string_to_int_list !dull_sizes int_dull_sizes;
print_string "size of dulls: "; print_int_list !int_dull_sizes;
let program_sizes = ref [] in
let program_dulls = ref [] in
for i = 0 to p - 1 do
let program = ref [] in
chomp_line program in_channel;
program_sizes := append !program_sizes (List.nth !program 0);
program_dulls := append !program_dulls (List.nth !program 1);
done;
let int_program_sizes = ref [] in
string_to_int_list !program_sizes int_program_sizes;
print_string "program sizes: "; print_int_list !int_program_sizes;
print_string "program dulls: "; print_string_list !program_dulls;
let transitions = ref [] in
chomp_line transitions in_channel;
let int_transitions = ref [] in
string_to_int_list !transitions int_transitions;
for i = 0 to s - 1 do
hello_int (List.nth !int_transitions i)
done
;;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream <> Some "0" do
run in_channel;
done;;
(!=)
是物理(指针)不等式,测试无法检测到您的结束标记0
。当查看0
时,Stream.peek返回Some 0
,但它与不等式检查右侧的Some 0
是不同的实体,因此循环在EOF崩溃之前不会终止
以下内容演示了正在发生的情况:
# Some 0 != Some 0;;
- : bool = true
# let x = Some 0 in x != x;;
- : bool = false
使用()
,这里是结构不等式。除了它和省略的run_in_channel
部分之外,代码对我来说很好
黄金法则:除非你真的需要,否则不要使用物理等式(==)
和(!=)
。通常,坚持结构等式(=)
和(
)
--编辑--
代码中还有一个问题最初没有透露
一旦您从\u频道中的创建流
。在您想通过中的关闭它之前,请勿自己触摸它!让流成为它的唯一读者
流的好处是,一旦创建,您就不必关心实际读数的发生。您仍然可以直接访问该频道,但它完全破坏了该频道带来的好处。不要这样做。在
运行中使用Stream.next
或Stream.peek
而不是input\u line
这很有帮助,但并没有解决我的问题。我认为问题在于,当我从我的in_通道生成流时,(在U通道的line_stream\u
函数中),我调用input_line通道
,这会消耗该行。有没有一种方法可以在不消耗线路的情况下生成一条流(这样我就可以偷看)?经过一些实验,我认为问题出在流中。毕竟,偷看。如果我在_频道中运行;在_频道中运行
程序完全按照我的意愿运行,但如果我这样做,则在_频道中运行
;打印字符串(获取选项(Stream.peek line_Stream));在_通道中运行(函数获取_选项以字符串形式从流.peek中查看的选项中获取值),程序会使用查看的行,因此无法工作。想法?如果没有run
的实际定义和示例数据,以及您对它们的期望,我不知道。我添加了所有相关的代码部分。程序还没有完成(目前它只打印数据),但我只对Stream.peek问题感兴趣。谢谢你的帮助。这不是使用流的正确方法。您在流式点播阅读器和您自己对频道的直接访问之间进行了一场奇怪的竞赛。创建流后,从中读取行。在通过中的close\u关闭频道之前,请勿直接访问频道。
# Some 0 != Some 0;;
- : bool = true
# let x = Some 0 in x != x;;
- : bool = false