2016-09-22 4 views
5

Я использую Visual Studio 2012, а также функцию, которая вызывает Console.ReadLine() не будет выполнятьПочему функция, содержащая Console.ReadLine(), не завершена?

let inSeq = readlines()

в этой простой программе

open System 
open System.Collections.Generic 
open System.Text 
open System.IO 
#nowarn "40" 

let rec readlines() = 
    seq { 
     let line = Console.ReadLine() 
     if not (line.Equals("")) then 
      yield line 
      yield! readlines() 
} 

[<EntryPoint>] 
let main argv = 
    let inSeq = readlines() 

    0 

Я экспериментировал и исследую это, и не могу видеть что, вероятно, очень простая проблема.

+0

Есть ли строка на консоли для чтения функции? Он ожидает ввода и блокирует, пока не получит линию. – Prune

+0

Я не совсем уверен, что вы спрашиваете. Выполнение в отладчике VS 2012 сбрасывается до последней строки программы, не дожидаясь ввода. – octopusgrabbus

+0

Я вижу ... и Рид опубликовал ответ, над которым я работал, но лучше справился с этим. – Prune

ответ

7

Последовательности в F # не оцениваются сразу, а оцениваются только по мере их перечисления.

Это означает, что ваша функция readlines эффективно ничего не делает, пока вы не попытаетесь ее использовать. Делая что-то с inSeq, вы заставите оценку, которая, в свою очередь, заставит ее вести себя так же, как вы ожидаете.

Чтобы увидеть это в действии, сделать что-то, что будет перечислять последовательность, например, подсчет количества элементов:

open System 
open System.Collections.Generic 
open System.Text 
open System.IO 
#nowarn "40" 

let rec readlines() = 
    seq { 
     let line = Console.ReadLine() 
     if not (line.Equals("")) then 
      yield line 
      yield! readlines() 
} 

[<EntryPoint>] 
let main argv = 
    let inSeq = readlines() 

    inSeq 
    |> Seq.length 
    |> printfn "%d lines read" 

    // This will keep it alive enough to read your output 
    Console.ReadKey() |> ignore 
    0 
+1

Ваш ответ объясняет много странного поведения, которое я наблюдал в отладчике. Благодарю. – octopusgrabbus

+1

@octopusgrabbus Да - последовательности IEnumerable , и являются «ленивыми». –

0

Если изменить последовательность в список в readLines() вы не имеете к «Activate» последовательности запуска входной рекурсии:

open System 
open System.Collections.Generic 
open System.Text 
open System.IO 
#nowarn "40" 

let rec readlines() =  
    [let line = Console.ReadLine() 
    if not (line.Equals("")) then 
    yield line 
    yield! readlines()] 

[<EntryPoint>] 
let main argv = 
    let inList = readlines() 

    printfn "END" 
    Console.ReadLine() |> ignore 
    0 

нераскрытый рекурсивный подход может быть что-то вроде этого:

let readLines _ = 
    List.unfold (fun i -> 
       let line = Console.ReadLine() 
       match line with 
       | "" -> None 
       | _ -> Some (line, i)) 0 

 Смежные вопросы

  • Нет связанных вопросов^_^