如何阅读stdin?

时间:2016-03-25 05:10:37

标签: functional-programming stdio clean-language uniqueness-typing

如何在Clean中执行此操作?

伪代码:

loop:
    input = read_stdin
    if input == "q":
        break loop
    else:
        print "you input: ", input

实际上,我已经看了一些pdf。但我有想象力,处理stdin和stdout很困难。我可以使用代码示例来使用stdio吗?

按照Keelan的指示,我完成了我的小程序。

module std_in_out_loop
import StdEnv

loop :: *File -> *File
loop io
# io = fwrites "input your name: " io
# ( name, io ) = freadline io
# name = name % ( 0, size name - 2 )
| name == "q"
# io = fwrites "Bye!\n" io
= io
| name == ""
# io = fwrites "What's your name?\n" io
= loop io
| otherwise
# io = fwrites ( "hello " +++ name +++ "\n" ) io
= loop io

Start:: *World -> *World
Start world
# ( io, world ) = stdio world
# io = loop io
# ( ok, world ) = fclose io world
| not ok = abort "Cannot close io.\n"
| otherwise = world

1 个答案:

答案 0 :(得分:1)

来自Clean 2.2 manual,第9章:

  

虽然Clean纯粹是功能性的,但允许带有副作用的操作(例如I / O操作)。实现   在不违反语义的情况下,经典类型提供了所谓的唯一性属性。如果是一个论点   一个函数被表示为唯一的,保证在运行时相应的实际对象是本地的,即存在   没有其他参考。显然,可以安全地执行这种“独特对象”的破坏性更新。

具体而言,您可以使Start通常具有arity 0(不带参数),从*World*World的函数。我们的想法是,我们现在有一个改变世界的功能,这意味着允许副作用(它们不再是真正的副作用,而是对世界的操作)。

*表示World类型的唯一性。这意味着您不能拥有world参数的两个实例。例如,以下内容将给出编译时唯一性错误:

Start :: *World -> *(*World, *World)
Start w = (w, w)

要使用标准IO,您需要StdFileStdEnv模块的功能。您将需要的功能是:

stdio :: !*World -> *(!*File, !*World)
fclose :: !*File !*World -> !(!Bool, !*World)

我简化了类型,实际上它们来自类FileSystemstdio从世界中打开唯一 File,并返回新的修改过的世界。 fclose关闭世界中的文件,并返回成功标记和修改后的世界。

然后,要从该stdio文件读取和写入,您可以使用:

freadline :: !*File -> *(!*String, !*File)
fwrites :: !String !*File -> !*File

freadline将一行读入String,包括换行符。 fwrites将字符串写入文件,通常您希望在写入stdio时包含换行符。

把它放在一起:

Start :: *World -> *World
Start w
# (io,w) = stdio w                                // open stdio
# io = fwrites "What is your name?\n" io          // ask for name
# (name,io) = freadline io                        // read in name
# name = name % (0, size name - 2)                // remove \n from name
# io = fwrites ("Hello, " +++ name +++ "!\n") io  // greet user
# (ok,w) = fclose io w                            // close stdio
| not ok = abort "Couldn't close stdio"           // abort in case of failure
= w                                               // return world from Start

#语法对您来说可能不熟悉。它是一种let,允许您对文件(或其他东西)使用相同的名称,这比使用更方便,例如:

Start w = w3
where
    (io, w1) = stdio w
    io1 = fwrites "What is your name?\n" io
    (name, io2) = freadline io1
    //...
    (ok, w3) = fclose io10 w2

现在,您应该能够使用辅助函数loop :: *File -> *File在伪代码中执行您想要的操作,辅助函数递归调用自身,直到输入q

除了freadlinefwrites之外,还有更多功能,请参阅StdFile.dcl了解相关信息。