見出し画像

Quil で関数型プログラミング2:副作用に悩む

Quil でクリエイティブ・コーディングを楽しみながら関数型プログラミングを学ぼうというこのシリーズ、前回は Quil のサンプルプログラムを動かし、リファレンスを参照しながら変更を加えて渦巻きを描くところまでやりました。

前回の記事はこちら。
https://note.mu/deconbatch/n/necaa1ffc5cdc

※ご注意
関数型にも Quil にも Clojure についてもド素人です。
故意にウソを書くことはありませんが、勘違いや理解不足による間違いがあるかもしれません。
いや、間違いなく間違ってます。

Clojure を学んでみよう

Quil の API は リファレンスもあるし、前回見たように Processing での経験がほとんどそのまま活かせるようなのでなんとかなりそうです。
関数型を学ぶという趣旨からすると、Quil よりも Clojure を学ぶ必要がありますね。

Clojure は Processing での Java に相当するもので、関数型のプログラミング言語です。

Processing → Java
Quil → Clojure

という関係ですね。

よし! では思ったようなロジックが Clojure でコーディング出来るように勉強していきましょう。

クリエイティブコーディングでよく使うロジックはなんだろう?
まずはループですかね。

ゼロから 2π までループで回しながらサインカーブでも書いてみましょうか。
Clojure でループは…?

『Clojureにはミュータブル (変更可能) なローカル変数がないので、ローカル変数を使ったループは難しい。』

ん? ループは難しい?
いや、その前に「ミュータブル (変更可能) なローカル変数がない」?
どういうこと?

『例えば、手続き型の言語では変数の値の変更が普通に出来ていましたが、Clojureでは変数がありません。』

なにっ!?「変数がありません」?
なにそれ!どうやってプログラム組むの!?

変数がない!?

プログラミング言語で変数が無いって何かの冗談でしょう?

Clojure じゃないけど、同じく関数型プログラミング言語 Haskell についての記事を見ると…

『Haskellは純粋関数型言語であるため、基本的には副作用がありません。
例えば関数の途中で入力値ではないグローバル変数(のようなもの)を参照したり書き換えたりすることはできず、そもそも一度値を定義した変数に違う値を代入することができません。』

うそーん!

どうも変数に値を「代入」するという考え方が無い?
変数に値を紐付けることを「束縛」と呼ぶらしいです。そして一度「束縛」した変数に異なる値を再代入することは無い?

つまり、
   x = x + 1;
が出来ないってことですね。

『x = x + 1
これを見て、「xとx+1が同じってどういうこと?」と混乱しない人のほうが稀でしょう。算数や数学ではこのような副作用を前提にした表記はしないからです。』

う〜ん、確かに数学ではこういう書き方はしませんね。
手続き型のプログラミングにどっぷり染まった今、何の疑問も違和感も感じずに x = x + 1 を受け入れてしまっていますし、これ無しでプログラムを書ける気がしない…

副作用無しでどうやって?

変数に異なる値を再代入することを「副作用」と表現するようです。

『副作用(ふくさよう)とは、ある機能がコンピュータの(論理的な)状態を変化させ、それ以降で得られる結果に影響を与えることをいう。代表的な例は変数への値の代入である。』

そして副作用の無いプログラムを「純粋」なプログラムと呼ぶらしい。
いやでも、入力の論理的な状態を変化させて出力するのがプログラムってもんじゃないの?
結果に影響を与えない純粋なプログラムって何それ?それって役に立つ?

『プログラムというものは、本質的に副作用を伴うものなので、これは避けて通れません。』

ですよね!

『しかし、何の制限もなく自由に副作用を発生させるプログラムは、多くの問題を発生させます』
『プログラムの純粋な領域と不純な領域を分離する』

なるほど、なるほど!
完全にまるまる純粋なプログラムを書けというわけではなく、どうしても副作用の発生する部分(不純な領域)を明確に分離して、できるだけ純粋な部分を多く確保して純粋なままに保つということなんですね!

純粋な部分はどんな場合でも必ず同じ結果が得られることが保証されるからテストも簡単だし、バグも発生しにくいという利点がある。
だから純粋な部分をできるだけ多くしたいという考えなんですね。

『オブジェクト指向では、副作用をなるべく小さい単位で「内側に封入」しようとします。』

そっかー。
今まで「副作用」という言葉で意識してたわけじゃないけど、同じ方向のことを別の方法で実現しようとしてきてたんですね。

で、どうしたら?

うん!意味はわかった。
でもどうしたらいいのかはわからん!

しょっぱなから関数型プログラミングの洗礼を受けた感じですね。
一行もコード書いてない…

次から本気出す!




この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕