Ocaml 每行读取一个文件行,并将读取的每行存储在单个列表中

Ocaml 每行读取一个文件行,并将读取的每行存储在单个列表中,ocaml,Ocaml,我是一名学生,参加了一个月左右的练习。 我正在尝试用Ocaml编写一个函数。此函数必须读取每行有一个单词的文本文件,并且必须将所有单词存储在列表中。 但问题是这个程序必须是递归的(这意味着没有循环,没有“while”) 到目前为止,我所能做的就是创建一个读取文本文件的函数(非常类似于BASH命令“cat”) 我只是不知道怎么做。Ocaml几乎不是我最喜欢的语言 open Printf let file = "example.dat" let () = let ic = open_i

我是一名学生,参加了一个月左右的练习。 我正在尝试用Ocaml编写一个函数。此函数必须读取每行有一个单词的文本文件,并且必须将所有单词存储在列表中。 但问题是这个程序必须是递归的(这意味着没有循环,没有“while”)

到目前为止,我所能做的就是创建一个读取文本文件的函数(非常类似于BASH命令“cat”)

我只是不知道怎么做。Ocaml几乎不是我最喜欢的语言

open Printf

let file = "example.dat"

let () =
     let ic = open_in file in
     let rec build_list infile =
          try
               let line = input_line infile in
               line :: build_list(infile)
          with End_of_file ->
               close_in infile;
               [] in
     let rec print_list = function
          [] -> ()
          | e::l -> print_string e ; print_string " " ; print_list l in
     print_list(build_list(ic))
编辑:我之前提出的算法过于复杂。试着去理解这个

为了理解这种递归,我们假设build_list工作正常。也就是说,假设build_list正确地将打开的文件作为参数,并返回文件中的行列表

现在,让我们看看函数的主体。它从文件中读取一行并再次调用build_list。如果文件中有N行,再次调用build_list应该会返回文件中剩余N-1行的列表(因为我们自己刚刚读取了第一行)。我们将刚刚读取的行附加到从build_list返回的列表中,并返回结果列表,该列表包含所有N行

递归将继续,直到到达基本情况。基本情况是当文件有结尾时。在本例中,我们返回一个空列表

编辑:我之前提出的算法过于复杂。试着去理解这个

为了理解这种递归,我们假设build_list工作正常。也就是说,假设build_list正确地将打开的文件作为参数,并返回文件中的行列表

现在,让我们看看函数的主体。它从文件中读取一行并再次调用build_list。如果文件中有N行,再次调用build_list应该会返回文件中剩余N-1行的列表(因为我们自己刚刚读取了第一行)。我们将刚刚读取的行附加到从build_list返回的列表中,并返回结果列表,该列表包含所有N行


递归将继续,直到到达基本情况。基本情况是当文件有结尾时。在本例中,我们返回一个空列表。

这里是
build\u list
的另一个定义,它是尾部递归的。如果您的输入可以有许多行,那么可以使用它来代替@MitchellGouzenko的定义

let rec build_list l =
    match input_line ic with
    | line -> build_list (line :: l)
    | exception End_of_file -> close_in ic; List.rev l

这里是
构建列表
的另一种定义,它是尾部递归的。如果您的输入可以有许多行,那么可以使用它来代替@MitchellGouzenko的定义

let rec build_list l =
    match input_line ic with
    | line -> build_list (line :: l)
    | exception End_of_file -> close_in ic; List.rev l

这将适用于小输入文件,但
build\u list
的定义不是尾部递归的,并且会导致大输入的堆栈溢出。围绕递归调用的
try…with
防止其成为尾部调用。好的调用。。。我使用ocaml已经有一段时间了:)您认为新的
构建列表更好,还是旧的更好(需要将空列表作为参数传递)?当然,假设我修复了
try…with
位,我很不好意思向OP承认这一点,OP显然不是OCaml的粉丝,但在编写OCaml代码时,你必须学会识别尾部调用
try…with
是其中一个比较棘手的例子。有人能给我解释一下“build\u list”函数应该做什么吗?我不知道,但我尝试编写它,它返回一个“语法错误”,因为表达式“exception”这将适用于小的输入文件,但是
build\u list
的定义不是尾部递归的,并且会导致大输入的堆栈溢出。围绕递归调用的
try…with
防止其成为尾部调用。好的调用。。。我使用ocaml已经有一段时间了:)您认为新的
构建列表更好,还是旧的更好(需要将空列表作为参数传递)?当然,假设我修复了
try…with
位,我很不好意思向OP承认这一点,OP显然不是OCaml的粉丝,但在编写OCaml代码时,你必须学会识别尾部调用
try…with
是其中一个比较棘手的例子。有人能给我解释一下“build\u list”函数应该做什么吗?我不知道,但我试着写它,它返回一个“语法错误”,因为表达式“exception”该函数做什么?实际上我正在使用的文件大约有500-600行长,所以我不认为在某个点会有堆栈溢出这是我找到的最好答案。我不明白为什么我在互联网搜索中找到的所有其他答案都用这些复杂的方式来尝试,而一个简单的匹配工作得这么好。这个函数做什么呢?实际上我使用的文件大约有500-600行长,所以我认为在某个点上不会出现堆栈溢出。这是我找到的最好的答案。我不明白为什么我在互联网搜索中找到的所有其他答案都用这些复杂的方式来尝试,而一个简单的匹配却很好。