2017-04-10 27 views
-3

我需要用ocaml處理來自stdin的用戶輸入。用戶將輸入命令,直到他鍵入退出,然後程序結束。這個怎麼做?我知道如何編程必要,但我想學習功能。用戶應該根據他的命令操縱堆棧中的數據。另外我想做一個解析器來處理用戶命令。Ocaml stdin接口

非常感謝您的幫助!

回答

0

下面是使用OCaml堆棧庫可以編寫的東西的草圖。它遠非完美,可以在很多方面得到改善,但總體結構在這裏。

就您的問題而言,最重要的部分是loop函數。它從標準輸入中讀取一行,並使用模式匹配來結束程序,或者評估給定和命令,並遞歸調用自身以等待另一個命令。

eval函數對給定參數使用模式匹配來做正確的事情。您可以找到Stack模塊here的文檔。

let stack = Stack.create() 

let eval args = 
    match args with 
    | ["push"; v] -> Stack.push v stack 
    | ["pop"] -> begin try print_endline (Stack.pop stack) with 
     | Stack.Empty -> print_endline "Stack is empty" 
    end 
    | ["show"] -> Stack.iter print_endline stack 
    | _ -> print_endline "Unrecognized command" 

let rec loop() = 
    match read_line() with 
    | "quit" -> print_endline "Bye" 
    | _ as command -> eval (String.split_on_char ' ' command); loop() 


let() = 
    loop() 

注意:我平時不太喜歡給人一種完整的解決方案的一個問題,這並不表明大量的研究想法,但嘿,你當你開始的地方新功能編程。

注2:此代碼僅適用於string堆棧。如果你打算存儲一個不同的類型,比如說int,或者你想要它是多態的,那麼你需要稍微調整一下這些代碼。

編輯:根據評論中的評論,下面是上述代碼的改進版本,它不使用全局變量堆棧。

let eval s args = 
    match args with 
    | ["push"; v] -> Stack.push v s 
    | ["pop"] -> begin try print_endline (Stack.pop s) with 
     | Stack.Empty -> print_endline "Stack is empty" 
    end 
    | ["show"] -> Stack.iter print_endline s 
    | _ -> print_endline "Unrecognized command" 

let rec loop s = 
    match read_line() with 
    | "quit" -> print_endline "Bye" 
    | _ as command -> eval s (String.split_on_char ' ' command); loop s 


let() = 
    loop (Stack.create()) 
+0

好吧!這是開始。非常感謝您的回答。嘿,我真的在做研究,我正在讀這本書的真實世界ocaml,但我仍然沒有找到像這樣的簡單例子。此外,我找到了一種做法,但採用更爲「迫切」的方式,使用引用,但那不是我的觀點,因爲我想盡可能地發揮功能。再次謝謝你! – dantopa

+0

好,真實世界OCaml可能是那裏最好的資源之一。學習如何「思考」功能是相當大的挑戰,tbh。如果您發現它有用,請考慮upvoting並接受答案。 – RichouHunter

+1

使用可變/全局變量堆棧實際上並不符合功能範例的精神。更傳統的方法是添加一個參數,作爲eval函數的堆棧。 – ghilesZ