Предложить пользователю создать список строк
Я хотел бы создать список строк, предложив пользователю для ввода. Моя конечная цель - уметь анализировать список строк по простой хеш-таблице с помощью простой процедуры.
`let list_find tbl ls =
List.iter (fun x ->
let mbr = if Hashtbl.mem tbl x then "aok" else "not found"
in
Printf.printf "%s %s\n" x mbr) ls ;;`
Построение списка строк выполняется с помощью оператора cons::, но я не могу получить запрос на создание списка строк. Функция списка simpe возвращает все, что помещено в него в виде списка:
`let build_strlist x =
let rec aux x = match x with
| [] -> []
| hd :: tl -> hd :: aux tl
in
aux x ;;`
До сих пор я был в состоянии установить приглашение, но создание списка строк не прошло так хорошо. Я склонен думать, что я должен использовать Buffer или Scanning.in_channel. Это то, что я до сих пор:
`#load "unix.cma" ;;
let prompt () = Unix.isatty Unix.stdin && Unix.isatty Unix.stdout ;;
let build_strlist () =
let rec loop () =
let eof = ref false in
try
while not !eof do
if prompt () then print_endline "enter input ";
let line = read_line () in
if line = "-1" then eof := true
else
let rec build x = match x with
| [] -> []
| hd :: tl -> hd :: build tl
in
Printf.printf "you've entered %s\n" (List.iter (build line));
done
with End_of_file -> ()
in
loop () ;;`
Я получаю сообщение об ошибке, ключевое слово "строка" имеет тип строки, но ожидалось выражение типа 'список. Должен ли я создавать список строк, используя Buffer.create buf, а затем Buffer.add_string buf prepending [с последующими кавычками "другой" и точкой с запятой? Это кажется излишним. Может быть, я должен просто вернуть список строк и игнорировать любые попытки "взглянуть на то, что у нас есть"? Печать будет выполнена после проверки хеш-таблицы.
Я хотел бы иметь подпрограмму, чтобы я мог использовать ocaml для сценариев и взаимодействия с пользователем. Я нашел некоторые идеи онлайн, которые позволили мне написать скелет выше.
1 ответ
Я, вероятно, разбил бы проблему в несколько шагов:
- получить список строк
- обработать его (в вашем примере просто распечатать его обратно)
1-й шаг может быть достигнут с помощью рекурсивной функции следующим образом:
let build_strlist' () =
let rec loop l =
if prompt () then (
print_string "enter input: ";
match read_line () with
"-1" -> l
| s -> loop (s::l)
) else l
in loop [];;
Посмотрите, как эта функция зацикливается на себе и создайте список l
как это происходит. Как вы упомянули в своем комментарии, я исключил обязательную часть вашего кода, чтобы сохранить только функциональную рекурсию. Вы могли бы достичь того же, сохранив вместо этого императивную часть и исключив рекурсию, но рекурсия кажется мне более естественной и, если она написана правильно, приводит в основном к одному и тому же машинному коду.
Как только у вас есть список, просто примените List.iter
к нему с функцией специальной печати, как вы сделали в своей первоначальной функции.