はじめよう

この章の目標

本章では実際のPureScriptの開発環境を立ち上げ、幾つかの演習を解き、本書で提供されているテストを使って答えを確認します。 もし映像を見る学習の仕方が合っているようでしたら、本章を通しで進めるビデオが役に立つでしょう。

環境構築

最初にドキュメンテーションリポジトリにあるこのはじめの手引きを通しで進め、環境の構築と言語の基礎を学んでください。Project Eulerの解答例にあるコードがわかりにくかったり見慣れない構文を含んでいたとしても心配要りません。来たる章でこの全ての内容をとても丁寧に押さえていきます。

エディタの対応

PureScriptを書く上で(例えば本書の演習を解くなど)お好みのエディタを使えます。 エディタの対応についてのドキュメントを参照してください。

なお、完全なIDE対応のため、開いたプロジェクトのルートにspago.dhallがあることを期待するエディタもあります。 例えば本章の演習に取り組む場合、chapter2ディレクトリを開くとよいでしょう。

VS Codeを使っている場合、提供されているワークスペースを使って全ての章を同時に開くことができます。

演習を解く

ここまでで必要な開発ツールをインストールできているので、本書のリポジトリをクローンしてください。

git clone https://github.com/purescript-contrib/purescript-book.git

本書のリポジトリには各章に付属してPureScriptのコード例と演習のための単体テストが含まれます。 演習の解法を白紙に戻すために必要な初期設定があり、この設定をすることで解く準備ができます。 この工程はprepareExercises.shスクリプトを使えば簡単にできます。

cd purescript-book
./scripts/prepareExercises.sh
git add .
git commit --all --message "Exercises ready to be solved"

それではこの章のテストを走らせましょう。

cd exercises/chapter2
spago test

以下の成功した旨のテスト出力が出るでしょう。

→ Suite: Euler - Sum of Multiples
  ✓ Passed: below 10
  ✓ Passed: below 1000

All 2 tests passed! 🎉

なお、(src/Euler.pursにある)answer関数は任意の整数以下の3と5の倍数を見付けるように変更されています。 (test/Main.pursにある)このanswer関数のためのテストスートははじめの手引きの冒頭にあるテストよりも網羅的です。 前の方の章を読んでいる間はこのテストフレームワークの仕組みを理解しようと思い詰めなくて大丈夫です。

本書の残りの部分には多くの演習が含まれます。 Test.MySolutionsモジュール (test/MySolutions.purs) に自分の解法を書けば、提供されているテストスートを使って確認できます。

テスト駆動開発でこの次の演習を一緒に進めてみましょう。

演習

  1. (普通)直角三角形の対角線(あるいは斜辺)の長さを他の2つの辺の長さを使って計算するdiagonal関数を書いてください。

解法

この演習のテストを有効にするところから始めます。 以下に示すようにブロックコメントの開始を数行下に下げてください。 ブロックコメントは{-から始まり-}で終わります。

    suite "diagonal" do
      test "3 4 5" do
        Assert.equal 5.0 (diagonal 3.0 4.0)
      test "5 12 13" do
        Assert.equal 13.0 (diagonal 5.0 12.0)
    {-  Move this block comment starting point to enable more tests

ここでテストを走らせようとすると、コンパイルエラーに直面します。 なぜならdiagonal関数をまだ実装していないからです。

$ spago test

Error found:
in module Test.Main
at test/Main.purs:21:27 - 21:35 (line 21, column 27 - line 21, column 35)

  Unknown value diagonal

まずはこの関数に欠陥があるときに何が起こるのか見てみましょう。 以下のコードをtest/MySolutions.pursに追加してください。

import Data.Number (sqrt)

diagonal w h = sqrt (w * w + h)

そしてspago testを走らせて確認してください。

→ Suite: diagonal
  ☠ Failed: 3 4 5 because expected 5.0, got 3.605551275463989
  ☠ Failed: 5 12 13 because expected 13.0, got 6.082762530298219

2 tests failed:

あーあ、全然正しくありませんでした。 ピタゴラスの定理を正しく適用して修正しましょう。 関数を以下のように変えます。

diagonal w h = sqrt (w * w + h * h)

ここでもう一度spago testとしてみると全てのテストが通っています。

→ Suite: Euler - Sum of Multiples
  ✓ Passed: below 10
  ✓ Passed: below 1000
→ Suite: diagonal
  ✓ Passed: 3 4 5
  ✓ Passed: 5 12 13

All 4 tests passed! 🎉

成功です。 これで次の演習を自力で解くための準備ができました。

演習

  1. (簡単)指定された半径の円の面積を計算する関数circleAreaを書いてみましょう。 Numbersモジュールで定義されている pi定数を使用してください。 手掛かりimport Data.Number文を修正して、 piをインポートすることを忘れないようにしましょう。
  2. (普通)Intを取って100で割ったあとの余りを返す関数leftoverCentsを書いてみましょう。rem関数を使ってください。Pursuitでこの関数を検索して、使用法とどのモジュールからインポートしてくるか調べましょう。補足:自動補完の提案を有効にしていたら、IDE側でこの関数の自動的なインポートに対応しているかもしれません。

まとめ

この章ではPureScriptコンパイラとSpagoツールをインストールしました。 演習の解答の書き方と正しさの確認方法も学びました。

この先の章にはもっと沢山の演習があり、それらに取り組むうちに内容を学ぶ助けになっているでしょう。 演習のどこかでお手上げになったら、本書の困ったときはの節に挙げられているコミュニティの資料のどれかに手を伸ばしたり、本書のリポジトリでイシューを報告したりできます。 こうした演習の敷居を下げることに繋がる読者のフィードバックのお陰で本書が改善されています。

章の全ての演習を解いたら、no-peeking/Solutions.pursにあるものと解答とを比べられます。 カンニングはせず、演習を誠実に自力で解く労力を割いてください。 そしてたとえ行き詰まったにしても、まずはコミュニティメンバーに尋ねてみるようにしてください。 ネタバレをするよりも小さな手掛かりをあげたいからです。 もっとエレガントな解法(とはいえ本書で押さえられている知識のみで済むもの)を見つけたときはPRを送ってください。

リポジトリは継続して改訂されているため、それぞれの新しい章を始める前に更新を確認するようにしてください。