当使用getLine和putStr时,IO发生不按顺序 [英] IO happens out of order when using getLine and putStr

查看:98
本文介绍了当使用getLine和putStr时,IO发生不按顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名Haskell初学者,我刚开始将我的头围绕Monad,但我还没有真正掌握它。我正在写一个游戏,其中包括询问用户输入和响应。这里是我的函数的简化版本:

$ $ p $ $ $ $ $ $ $ getPoint :: $ $ $ $ $ $ $ getPoint = $ $ $ $ $ $ putStr 输入x:
xStr< - getLine
putStr输入y:
yStr< - getLine
返回$ Point(读取xStr)(读取yStr)


completeUserTurn ::(Board,Player) - > IO(Board,Player)
completeUserTurn(board,player)= do
putStr $输入一些值:
var1 < - getLine
putStr $输入另一个值:
var2< - getLine
putStr $这次输入一个点:
point< - getPoint
if(...玩家输入合法值... )然后做
putStr $这就是如果你这样做会发生什么:{stuff}你想这么做吗?(y / n)
continue< - getLine
if继续==y然后
返回(...更新板...,...更新的播放器...)
else
completeUserTurn(板,播放器)

completeUserTurn(board,player)

发生的情况是,提示与出现在提示符之前的文本出现乱序。



下面是我编译上面的代码后发生的事情的一个例子:


1
输入一些值:输入另一个值: 2

3

4

这次输入一个点:输入x:输入y: y

这是正确的吗? (y / n):

粗体是我输入的内容。



显然,我有一些重大的概念错误,但我不知道是什么。请注意,它在解释器中正常工作,编译时失败。

解决方案

正如Michael所说,问题在于缓冲。默认情况下,输出会被缓冲,直到你打印一个换行符(或者如果你有很长的行,那么直到缓冲区已满),所以当你尝试使用执行同行提示时,你会经常看到这个问题。 putStr 就像你在做什么。



我建议定义一个像这样的小帮助函数来照顾你做脸部冲洗: p>

  import System.IO 

prompt :: String - > IO字符串
提示符文本=做
putStr文本
hFlush stdout
getLine

现在您可以简单地执行

  getPoint = do 
xStr< - promptEnter x :
yStr< - prompt输入y:
return $ Point(read xStr)(read yStr)


I'm a Haskell beginner, I'm just beginning to wrap my head around Monads, but I don't really get it yet. I'm writing a game that consists of asking the user for input, and responding. Here is a simplified version of my function:

getPoint :: IO Point
getPoint = do
    putStr "Enter x: "
    xStr <- getLine
    putStr "Enter y: "
    yStr <- getLine
    return $ Point (read xStr) (read yStr)


completeUserTurn :: (Board, Player) -> IO (Board, Player)
completeUserTurn (board, player) = do
    putStr $ "Enter some value: "
    var1 <- getLine
    putStr $ "Enter another value: "
    var2 <- getLine
    putStr $ "Enter a point this time: "
    point <- getPoint
    if (... the player entered legal values ...) then do
        putStr $ "This is what would happen if you did that: {stuff} do you want to do that? (y/n) "
        continue <- getLine
        if continue == "y" then
            return (...updated board..., ...updated player...)
        else
            completeUserTurn (board, player)
    else do
        putStr "Invalid Move!\n"
        completeUserTurn (board, player)

What's happening is that the prompts will appear out of order with the text that is supposed to appear before the prompt.

Here's an example of what's happening after I compiled the code above:

1
Enter some value: Enter another value:2
3
4
Enter a point this time: Enter x: Enter y: y
Is this correct? (y/n):

The bold are the things I typed in.

Obviously, I have some major conceptual error, but I don't know what. Note that it works correctly in the interpreter and fails when compiled.

解决方案

As Michael said, the issue is buffering. By default, output is buffered until you print a newline (or until the buffer is full if you have really long lines), so you'll most often see this issue when trying to do same-line prompts using putStr like you're doing.

I suggest defining a small helper function like this to take care of doing the flushing for you:

import System.IO

prompt :: String -> IO String
prompt text = do
    putStr text
    hFlush stdout
    getLine

Now you can simply do

getPoint = do
    xStr <- prompt "Enter x: "
    yStr <- prompt "Enter y: "
    return $ Point (read xStr) (read yStr)

这篇关于当使用getLine和putStr时,IO发生不按顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆