以下のedXコースSystematic Program Design - Part 1の日本語解説①。
このコースでは、特定の言語の書き方ではなく、汎用的な良いプログラムの書き方を学ぶ。例えば:
- 目的 - そのプログラムに何をさせるのか
- 分解 - プログラムをどう(小さな問題に)分解するのか
- 可読性 - 読みやすく、改造が容易なものにする
そのため、コースを通じて人気の特定言語ではなく、Racketという元はプログラミング教育を目的として開発された言語を用いて学習を行う。
内容に問題があればご連絡ください。
Dr.RacketでBeginning Student Languageを使用する
Dr.RacketはRacketを使用するための環境である。
Dr.Racket起動時に左下にBeginning Student Languageとある場合は、既に設定されている。そうでない場合はトップメニューからLanguage > Choose Language > How to Design Programs > Beginning Studentで設定できる。
Dr.Racketの画面構成は以下のようになっている。
上のDefinition Areaにプログラムを記述し、右上のメニューからRunすると、Interaction Areaに結果が表示される。例えば上のエリアに (+ 3 4)
と記述しRunすると、下のエリアに 7
が表示される。
- コメント: セミコロン
;
以降はその行はすべてコメントとみなされ、Runしても無視される。 - コメントボックス:1行以上をコメント化したい場合、その部分を選択してトップメニューの Insert > Insert Comment Box
用語
- primitive: BSLの基本的な構成要素であり、プログラムを設計するときに使用する。
-
primitive operator: このprimitiveを操作するための要素で、
+
、-
、string-append
,substring
,image-width
などがある。 - operand: operatorの後に続く要素。
-
Expression: 値を生成するために評価されるプログラムの要素で、
(<operator> <operand> ...)
のような形で表される。
例:(+ 3 4)
この式に従って値が処理され、結果が生成される。
上記の例のように、expressionの中に別のexpressionが含まれることもある。
処理を開始すると上図のように左から右、中から外へと各operandにoperatorが適用される。
Number
参考:Numbers: Integers, Rationals, Reals, Complex, Exacts, Inexacts
> (+ 2 2)
4
> (sqr 3)
9
> (sqrt 16)
4
> (cos pi)
#i-1.0 ; #i…はinexact number。正確に表示できなかった数字
無理数の扱い:
コンピュータは有限の数しか扱えないため、上記の(cos pi)
や(sqrt 2)
などのように無理数を出力する場合、結果は#i1.4142135623730951
となる。#i
は限りなく近い値であるが正確ではない値を表す。
Ex: pythag-starter.rkt
直角三角形の2つの短辺の長さが3と4であるとします。長辺の長さはいくらでしょうか。ピタゴラスの定理が次のように教えていることを思い出してください。?の値を生成するBSL式を作成します。
(sqrt (+ (sqr 3) (sqr 4)))
計算は括弧の扱いなども含めて、通常の数学と同様の順番で行われる。
String
参考:Strings
ダブルクオーテーション"
で囲まれた部分(のダブルクオーテーションを含まないもの)がstringとなる。"apple"
"123”
> (string-append "apple" " " "banana")
"apple banana"
> (string-length "apple")
5
> (sbustring "Caribou" 2 4)
"ri"
; 数字のstringは文字列。numberではないため以下はエラー
> (+ 1 "123")
+: expects a number, given "123"
0-based Indexing
(sbustring "Caribou" 2 4)
が"ri"
となるのはなぜだろう?それは、"Caribou"
で各文字が選ばれる方法が、0から始まるインデックスによるものだからである。つまり、文字それぞれに0 = C
, 1 = a
, 2 = r
…のようにインデックスが割り振られている。
また、(sbustring "Caribou" 2 4)
のように二つのインデックスで範囲を指定する場合、2つ目のインデックスの値は含まれないため、(sbustring "Caribou" 2 4)
は"ri"
となる。
Image
参考:Images
(require 2htdp/image) ; 画像を扱う場合この記述を行い画像処理用のパッケージを読み込む必要がある
(rectangle 30 60 "outline" "blue")
(require 2htdp/image)
(text "hello" 24 "orange")
(require 2htdp/image)
(overlay (circle 10 "solid" "red")
(circle 20 "solid" "yellow")
(circle 30 "solid" "green"))
Definition
定数を命名し指定することで、プログラムの可読性が上がり、後に変更もしやすくなる。慣習的に定数名は大文字で書かれる。
(require 2htdp/image)
(define WIDTH 400)
(define HEIGHT 600)
(* WIDTH HEIGHT) ; 240000
(define CAT 🐈) ; BSLでは実際に利用する画像(以下の画像)を直接🐈に配置する
CAT
(rotate -10 CAT))
(rotate 10 CAT)
Function Definitions
関数は一度定義した後、呼び出すたびに記述された処理を行う。都度与えられた値によって、別の値を生成したりできる。
下記のように記述し定義する:
呼び出す時は以下のようにする:
Stepperで処理を確認する
BSLのRunボタンの隣にあるStepを使用すると、BSLのルールに従って各expressionが一つずつ処理される。これを使用することで、プログラムのどの時点で意図しない処理、バグが起きているか発見しデバッグが効率的に行える。
Primitiveを探す
sqr
やstring-append
などこれまでに紹介したPrimitive以外にも、BSLで既に定義されたPrimitiveはたくさんある。これを探す際には公式ドキュメントを参照する以外にも、当てずっぽうで記述してみてもよい。これまでに見てきた通り、rectangle
が長方形を描写するものであったり、名称はある程度予想しやすいものである。
またRacket上で文字列を選択し、右クリックメニューから"Search in Help desk for ..."を選ぶと、Racketのヘルプからその文字列での検索も可能。
Problem Bank
以下は問題と、私が書いた回答プログラムになります。模範解答は元講義のProblem Bankのリストにあるものをご覧ください。
more-arithmetic-expression-starter.rkt 難易度★☆☆
数値3、5、7を乗算する2つの式を作成してください。最初の式は *
が3つ以上の引数を受け入れられるという事実を利用する必要があります。2番目の関数では、まず3に5を乗算し、次にその結果に7を乗算して結果を構築する必要があります。
答え
(* 3 5 7)
(* (* 3 5) 7)
evaluation-prims-starter.rkt 難易度★★☆
次の式の評価を過程ごとに書き出してください: (+ (* 2 3) (/ 8 2))
答え
(+ (* 2 3) (/ 8 2))
(+ 6 (/ 8 2))
(+ 6 4)
10
次の式の評価を過程ごとに書き出してください: (* (string-length "foo") 2)
答え
(* (string-length "foo") 2)
(* 3 2)
6
tile-starter.rkt 難易度★☆☆
DrRacketのsquare
、beside
、above
関数を使用して、次のような画像を作成してください。
答え
(require 2htdp/image)
(above (beside (square 20 "solid" "blue")
(square 20 "solid" "yellow"))
(beside (square 20 "solid" "yellow")
(square 20 "solid" "blue")))
glue-starter.rkt 難易度★★☆
"Super" "Glue"という文字列を1つの文字列"Super Glue"に結合する式を書いてください。2つの単語の間にスペースを入れるのを忘れないように。
答え
(string-append "Super" " " "Glue")
compare-images-starter.rkt 難易度★☆☆
以下の2つの定数に基づいて、3つの条件を評価する式を作成してください:
(define IMAGE1 (rectangle 10 15 "solid" "red"))
(define IMAGE2 (rectangle 15 10 "solid" "red"))
-
IMAGE1
はIMAGE2
よりも高い -
IMAGE1
はIMAGE2
より細い -
IMAGE1
はIMAGE2
と同じ幅と高さである
答え
(require 2htdp/image)
(define IMAGE1 (rectangle 10 15 "solid" "red"))
(define IMAGE2 (rectangle 15 10 "solid" "red"))
(> (image-height IMAGE1)
(image-height IMAGE2))
(< (image-width IMAGE1)
(image-width IMAGE2))
(and (= (image-width IMAGE1)
(image-width IMAGE2))
(= (image-height IMAGE1)
(image-height IMAGE2)))
more-foo-evaluation-starter.rkt 難易度★☆☆
与えられた関数に基づいて、式の評価を過程ごとに書き出してください:
(define (foo n)
(* n n))
(foo (+ 3 4))
答え
(foo (+ 3 4))
(foo 7)
(* 7 7)
49
even-more-foo-evaluation-starter.rkt 難易度★☆☆
与えられた関数に基づいて、式の評価を過程ごとに書き出してください:
(define (farfle s)
(string-append s s))
(farfle (substring "abcdef" 0 2))
答え
(farfle (substring "abcdef" 0 2))
(farfle "ab")
(string-append "ab" "ab")
"abab"
cflag-starter.rkt 難易度★☆☆
カナダ国旗 (カエデの葉なし) の背景は次のとおりです:
これを生成する式を作成してください(正式な各カラーの比率は1:2:1です)。
答え
(require 2htdp/image)
(beside (rectangle 20 40 "solid" "red")
(rectangle 40 40 "solid" "white")
(rectangle 20 40 "solid" "red"))
even-more-arithmetic-expression-starter.rkt 難易度★☆☆
次の数式を表すBSL式を作成してください。単に18と書かないように: (6 + 3) × (9 - 7)
答え
(* (+ 6 3)
(- 9 7))
triangle-starter.rkt 難易度★☆☆
triangle
, overlay
, rotate
を使用して次のような画像を生成する式を作成してください。三角形のサイズは任意です。
triangle
, overlay
の使用方法については、DrRacketのヘルプを参照してください。
答え
(require 2htdp/image)
(overlay (triangle 50 "solid" "green")
(rotate 180
(triangle 50 "solid" "yellow")))
bobble-evaluation-starter.rkt 難易度★☆☆
与えられた関数に基づいて、式の評価を過程ごとに書き出してください:
(define (bobble s)
(if (<= (string-length s) 6)
(string-append s "ible")
s))
(bobble (substring "fungus" 0 4))
答え
(define (bobble s)
(if (<= (string-length s) 6)
(string-append s "ible")
s))
(bobble (substring "fungus" 0 4))
(bobble "fung")
(if (<= (string-length "fung") 6)
(string-append "fung" "ible")
"fung")
(if (<= 4 6)
(string-append "fung" "ible")
"fung")
(if true
(string-append "fung" "ible")
"fung")
(string-append "fung" "ible")
"fungible"
debug-rectangle-starter.rkt 難易度★☆☆
以下のコードのコメントを外し、エラーを修正してください:
; (rectangle 10 solid red)
答え
(rectangle 10 20 "solid" "red")
arithmetic-expression-starter.rkt 難易度★☆☆
20に等しい数式 (7 - 2) × 4
を表すBSL式を記述してください。単に20と書かないように。
答え
(* (- 7 2) 4)
overlay-starter.rkt 難易度★☆☆
star
とoverlay
を使用して次のような画像を生成する式を作成してください。星のサイズは任意です。
star
とoverlay
の使用方法については、DrRacketのヘルプを参照してください。
答え
(require 2htdp/image)
(overlay (star 15 "solid" "blue")
(star 30 "solid" "yellow")
(star 45 "solid" "blue"))
function-writing-starter.rkt 難易度★☆☆
2つの数を取り、大きい方を返す関数を作成します。
答え
(define (larger x y)
(if (> x y)
x
y))
foo-evaluation-starter.rkt 難易度★★☆
与えられた関数に基づいて、式の評価を過程ごとに書き出してください:
(define (foo s)
(if (string=? (substring s 0 1) "a")
(string-append s "a")
s))
(foo (substring "abcde" 0 3))
答え
(foo (substring "abcde" 0 3))
(foo "abc")
(if (string=? (substring "abc" 0 1) "a")
(string-append "abc" "a")
"abc")
(if (string=? "a" "a")
(string-append "abc" "a")
"abc")
(if true
(string-append "abc" "a")
"abc")
(string-append "abc" "a")
"abca"