2016-05-23 2 views
1

Я хочу написать функцию, которая реализует основное использование grep: сопоставление шаблона в файле. И я хочу, чтобы match_file_pattern возвращал список совпадающих строк. Но код здесь не может скомпилировать, ошибка:как заставить начать следующее выражение в ocaml

Error: This expression has type string list but an expression was expected of type unit

И код:

let match_file pattern file_name = 
    let matched_lines = ref [] in 
    let ic = open_in file_name in 

    try 
    while true 
    do 
     let line = input_line ic in 
     if (Str.string_match (Str.regexp pattern) line 0) 
     then 
     matched_lines := line::!matched_lines 
    done;**(*!matched_lines*)**(*I need add this to compile successfully*) 
    with End_of_file -> 
    close_in ic; 
    List.rev !matched_lines;; 

Я думаю, что ошибка вызвана в ocaml, close_in ic; List.rev !matched_lines группируется в подвыражением «с» ключевое слово, поэтому его тип должен совпадать с выражением «try». Я пытаюсь найти способы разбить связь между close_in ic; и List.rev !matched_lines, но не удалось.

ответ

2

Вы можете использовать begin/end или круглые скобки:

let match_file pattern file_name = 
    let matched_lines = ref [] in 
    let ic = open_in file_name in 

    begin 
    try 
    while true 
    do 
     let line = input_line ic in 
     if (Str.string_match (Str.regexp pattern) line 0) 
     then 
     matched_lines := line::!matched_lines 
    done 
    with End_of_file -> close_in ic 
    end; 
    List.rev !matched_lines 
1

Тип контура unit, хотя он никогда не завершается. Элемент typechecker не знает этого, поэтому вам нужно сделать выражение под try тем же типом, что и обработчики исключений.

В этом случае вы можете использовать произвольный список, такой как [], но он вводит в заблуждение для читателя и не обобщает на случаи, когда может быть сложнее предоставить выражение правильного типа.

Идиоматическое решение здесь - разместить assert false, что вызовет исключение, если оно когда-либо будет оценено. В отличие от бесконечного while цикла, assert false известен проверки типов, чтобы не возвращаться и совместим с любым типом, поскольку значение никогда не производится:

 
try 
    while true do 
    ... 
    done; 
    assert false 
with ... -> ... 
0

Ваш код в порядке:

одна точка с запятой после done, для последовательности инструкций, а затем !matched_lines в качестве возвращаемого значения части кода запроса, затем with ....

Здесь нет двусмысленностей. Компилятор просто не учитывает, что End_of_file всегда поднимается.

Остальное - вопрос о стиле кодирования. Мне нравится размещать комментарий (* never reached *) в этих технически необходимых выражениях - было бы неплохо для предложения , а также ИМО.