「48時間でSchemeを書こう」の版間の差分

削除された内容 追加された内容
219 行
</syntaxhighlight>
 
=== Whitespace空白文字 ===
 
次に、パーサがより段々とより複雑な式を認識するようにいくつかの改善を施していきます。今のパーサはスペースが記号の前にあるとつかえてしまいます。
Next, we'll add a series of improvements to our parser that'll let it recognize progressively more complicated expressions. The current parser chokes if there's whitespace preceding our symbol:
 
<syntaxhighlight lang="bash">
debian:/home/jdtang/haskell_tutorial/code# ./simple_parser " %"
% ./simple_parser " %"
No match: "lisp" (line 1, column 1):
unexpected " "
</syntaxhighlight>
 
スペースを無視させるようにしてこれを直しましょう。
Let's fix that, so that we ignore whitespace.
 
First, lets define a parser that recognizes any number of whitespace characters. Incidentally, this is why we included the まず、どんな数のスペースも認識するパーサを定義しましょう。偶然にも、これが私たちがParsecをインポートした時<code>hiding (spaces)</code> clause when we imported を追加した理由です。Parsec: there's already a function には"[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#spaces spaces]" in that library, but it doesn't quite do what we want it to. 関数がありますが、これは私たちの期待する動作をしません(For that matter, there's also a parser called ついでに言えば、[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#lexeme lexeme] that does exactly what we want, but we'll ignore that for pedagogical purposes.というピッタリの関数がありますが、ここでは教育上の目的からそれを使わないことにします)
 
<syntaxhighlight lang="haskell">
spaces :: Parser ()
spaces =:: skipMany1Parser space()
spaces = skipMany1 space
</syntaxhighlight>
 
Just as functions can be passed to functions, so can actions. Here we pass the 関数を関数に渡せるように、アクションをアクションに渡すこともできます。ここではParser action アクション[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#space space] to the Parser action アクション[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#skipMany1 skipMany1], to get a Parser that will recognize one or more spaces.に渡して一つ以上のスペースを認識するパーサを作っています。
 
では、これを使うようにパーサを変更しましょう。
Now, let's edit our parse function so that it uses this new parser. Changes are in red:
 
<syntaxhighlight lang="haskell">
readExpr input = case parse <span style="color:red">(spaces &gt;&gt;>> symbol)</span> "lisp" input of
Left err -&gt; "No match: " ++ show err
Left Right valerr -&gt;> "FoundNo match: value" ++ show err
Right val -> "Found value"
</syntaxhighlight>
 
第二章で<code>>></code>("bind")演算子について軽く触れた時には、それは裏でdoブロックの行を繋ぎあわせるのに使われていると言いました。ここでは、スペースパーサと記号パーサを組み合わせるために明示的に使用しています。しかしながら、bindはParserモナドとIOモナドで全く異った意味を持ちます。Parserモナドでは、bindは「一つ目のパーサのマッチを試み、二つ目のパーサを残りの入力に対してマッチを試み、どちらかがマッチに失敗したら失敗する」という意味です。一般的には、bindは異るモナド間で非常に違った動きをします。モナドの目的は計算を構成する一般的な方法を提供することなので、それはいろんな違う種類の計算に適合できるく普遍性を備えている必要があります。それがまさに何をするかはモナドのドキュメントを読んでください。
We touched briefly on the &gt;&gt; ("bind") operator in lesson 2, where we mentioned that it was used behind the scenes to combine the lines of a do-block. Here, we use it explicitly to combine our whitespace and symbol parsers. However, bind has completely different semantics in the Parser and IO monads. In the Parser monad, bind means "Attempt to match the first parser, then attempt to match the second with the remaining input, and fail if either fails." In general, bind will have wildly different effects in different monads; it's intended as a general way to structure computations, and so needs to be general enough to accommodate all the different types of computations. Read the documentation for the monad to figure out precisely what it does.
 
このコードをコンパイル・実行してください。<code>spaces</code>を<code>skipMany1</code>で定義したので、もう普通の単なる一文字は認識しないことに注意してください。その代わり、記号の前にスペースを入れ''なければなりません''。これがどのように都合よいのかみてみます。
Compile and run this code. Note that since we defined <code>spaces</code> in terms of <code>skipMany1</code>, it will no longer recognize a plain old single character. Instead you ''have to'' precede a symbol with some whitespace. We'll see how this is useful shortly:
 
<syntaxhighlight lang="bash">
debian:/home/jdtang/haskell_tutorial/code# ghc -package parsec -o simple_parser [../code/listing3.2.hs listing3.2.hs]
% ghc -package parsec -o simple_parser simple-parser.hs
debian:/home/jdtang/haskell_tutorial/code# ./simple_parser " %"
% ./simple_parser " %"
Found value
debian:/home/jdtang/haskell_tutorial/code# ./simple_parser %
% ./simple_parser %
No match: "lisp" (line 1, column 1):
unexpected "%"
expecting space
debian:/home/jdtang/haskell_tutorial/code# ./simple_parser " abc"
% ./simple_parser " abc"
No match: "lisp" (line 1, column 4):
unexpected "a"
expecting space
</syntaxhighlight>
 
=== Return Values ===