Предложить пользователю создать список строк

Я хотел бы создать список строк, предложив пользователю для ввода. Моя конечная цель - уметь анализировать список строк по простой хеш-таблице с помощью простой процедуры.

`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. получить список строк
  2. обработать его (в вашем примере просто распечатать его обратно)

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 к нему с функцией специальной печати, как вы сделали в своей первоначальной функции.

Другие вопросы по тегам