0

クリーンでこれを行う方法は?

擬似コード:

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

実際、私はいくつかのpdfをちらっと見ました。でも、想像してみると、 stdin と stdout を扱うのは難しい。stdio を使用するコード例を教えてください。

キーランの指示に従って、私は小さなプログラムを完成させました。

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
4

1 に答える 1

1

Clean 2.2マニュアルの第9章から:

Clean は純粋に機能的ですが、副作用のある操作 (I/O 操作など) は許可されています。セマンティクスに違反することなくこれを実現するために、従来型にはいわゆる一意性属性が提供されています。関数の引数が一意であると示されている場合、実行時に対応する実際のオブジェクトがローカルであることが保証されます。つまり、それに対する他の参照はありません。明らかに、このような「一意のオブジェクト」の破壊的な更新は安全に実行できます。

具体的にはStart、通常アリティ0(引数を取らない)の を*Worldtoからの関数にすることができ*Worldます。これは、副作用が許可されていることを意味します (副作用はもはや実際には副作用ではなく、世界に対する操作です)。

は型の一意性*を示します。つまり、world 引数のインスタンスを 2 つ持つことはできません。たとえば、次の場合、コンパイル時に一意性エラーが発生します。World

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

StdFile標準 IO を使用するには、 のモジュールの関数が必要ですStdEnv。必要になる機能は次のとおりです。

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

タイプを少し単純化しましたが、実際には class からのものですFileSystem世界から一意stdioのものを開き、新しい変更された世界を返します。ワールド内のファイルを閉じ、成功フラグと変更されたワールドを返します。 Filefclose

次に、その stdio ファイルから読み書きするには、次を使用できます。

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

freadline改行文字を含む行を文字列に読み取ります。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

freadlineとだけでなく、より多くの機能があります。アイデアについてはfwrites、 を参照してください。StdFile.dcl

于 2016-03-25T07:28:23.697 に答える