Assyのリベラル文学研究所もご覧ください。

プログラミングいろいろ

RubyによるWebプログラミングのようなもの

ある意味、プログラミングなんて、ただ使うだけだ、ということも出来る。
たとえば、ホームページをHTMLで書いていたとして、日記の月別一覧を色んなところに張り付けたい場合は、Rubyなら

2017.11.01
2017.11.02
2017.11.04
2017.11.05

というテキストファイルを作っておいて、その上で

File.open("diary_2017.11.txt") do |io|
  while line = io.gets
    line.chomp!
    puts "<p><a href=\"" + line + ".html\">" + line + "</a></p>"
  end
end

Rubyでいくらか書いてやるだけで、簡単に動くRubyCGIファイルを作ることが出来る。日付を追加する時はdiary_2017.11.txtだけを編集すれば良い。
だから、何をするにしても、プログラミングはただ使うだけだ。自分で何も作っていない。使うだけに終始する、それがプログラミングなのだ。
上のコードを綺麗な関数にすると以下のようになる。

def diary_list(path)
  File.open(path) do |io|
    while line = io.gets
      line.chomp!
      puts "<p><a href=\"" + line + ".html\">" + line + "</a></p>"
    end
  end
end

diary_list("diary_2017.09.txt")
diary_list("diary_2017.10.txt")
diary_list("diary_2017.11.txt")

また、オブジェクト指向でなぜ作るのか、という話が分からない人が多いが、フィールドは視点を変えてみるとグローバル変数と似ている。クラスの中だけで使われるグローバル変数だ。そういう風に考えると、JavaRubyカプセル化という発想も良く分かると思う。

タスクからシステムを作る

2018-02-27より。
僕は、出来ればプロジェクトマネジメントの研究をしたい。特に、グーグルの戦略と働き方に興味がある。あるいは、マイクロソフトの働き方に興味がある。そして、国連の活動に興味がある。先日は、国連の広報ブログを読んでいた。
プログラムとは、手順書だ。パソコンをアセンブリから見ると、ただの電卓だ。プログラムとは計算の手順であり、コンパイラは計算の手順をより基本的なものに変換する。プログラムを実現するのはカーネルだが、ファイルシステムなどは本来は必要ない。システムを具体的に実現するのがソフトウェアだ。
プログラミングとは、手順書を書くことでシステムのインフラ基盤を作る作業だ。
やることが定まっている全てのタスクは、きちんとシステムを作れば簡単に実現できる。それがプログラマだ。
普通、描画システムぐらい簡単に作れる。ブラウザではレンダリングエンジンと言う。一つ一つのシステムを作って、細分化させながら組み合わせれば、きっとIllustratorも作れる。
プログラミングは、ある意味自動実行とリクエストだ。だから、サーバーをやるとできるようになる。
コンパイラは、トークンを解析するシステム、文法を成り立たせるシステム、実行内容を作るシステム、アセンブラを吐き出すシステムを作れば作れる。
コンパイラは決して難しくない。機能と構文ごとにシステムを作れば作れる。Rustなら、借用やトレイトの解釈システムと実行システムを作れば作れる。

GUIプログラミングの方法

僕は、GUIプログラミングには主に3つの方法があると思っている。
まず、Windowsのメッセージループや、X11のイベントループ、Swingのリスナのように、「メッセージループ」を行うことでイベントを分類する方式。
次に、MFCのような、継承とオーバーライドでオブジェクト指向でメソッドを書き換える方式。
そして、GTK+VBのような、ウィジェットにコールバック関数でイベントドリブンを行う方式。
どの方式も一長一短があるが、少しずつレベルと抽象度が高くなっていく、と考えると良いだろう。理想はGTK+VBだ。

処理は画面のウィンドウではなく、CPUがやっている

パソコンの初心者が勘違いしやすいこととして、「パソコンの処理は、画面に出てくるウィンドウがやっている」ということがある。
本当は、ウィンドウはただやりとりを表示しているだけで、実際の処理はCPUとハードウェアがやっている。
ある意味、「実行ファイルがやっている」という考え方はおかしくはない。それは、OSが実行ファイルを実行する、という発想から生まれている。だが、本当の処理はCPUがやっている。画面に出てこない色々なことを全て、CPUがプログラムコードを実行してやっている。そのことを覚えておくと、パソコンが長い間停止して何をやっているのか分からない、という時でも、「ああ、CPUは今頑張っているのだな」ということが分かる。プログラムとは何なのか、コードはどんなことを書いてどんなことを実行させているのか、良く分かるようになる。

プログラミングの原則

驚き最小の原則

驚き最小の原則とは、特にPerlなどのプログラミング言語などの設計に言われる考え方で、「みんなが驚いたり勘違いしたりすることを極力なくして、当然そのように発想するように設計しよう」という設計の考え方。

車輪の再発明(はやめよう)

車輪の再発明とは、一度作った基本的なベースシステムをもう一度作り直す(再発明)のではなく、出来るだけ共有して再利用しよう、という考え方。UNIXなどの他、Windowsなどでも言われる。
後日注記:実際のところ、「絶対に動くサブルーチン」を作ってしまえば、あとはそのサブルーチンや関数を再利用するだけで絶対に動く。プログラミングではそういう発想をする。同じ処理を別々の場所に何度も書いていると、後で直すのにも時間がかかる。

Keep it simple, stupid.

Keep it simple, stupid.(シンプルを保て、愚か者め)とは、UNIXで言われる考え方で、「シンプル(単純)」な状態を保っておかなければ、すぐに使い物にならなくなる(設計の間違いを生む)、という考え方。
また、UNIX哲学として「システムのパワーは、プログラム自身からではなくプログラム間の関係から生じる」という考え方が言われている。ひとつのプログラムを使うのではなく、たくさんのプログラムを使って成り立たせるソフトウェアの環境がシステムのパワーを発揮する。特に、findやgrepのような小さなコマンドプログラムを組み合わせて使う、といった時に言われる。個別のプログラムだけがパワーを発揮するのではなく、プログラムをとりまくシェルやOSなどの環境の関係がシステムのパワーを発揮するという、システムエンジニアらしい考え方である。

設定より規約

Ruby on Railsで言われる考え方で、複雑な設定をするよりもある程度の規約をそれぞれが守るようにした方が、フレームワークの管理は簡単になる、という考え方。

目玉の数さえ十分あれば、どんなバグも深刻ではない

Linuxオープンソースで言われる考え方で、バグがいくらあったとしても、それを修正するための発見者や貢献者の目玉がたくさんある(たくさんの人がコードを検査している)のであれば、バグは深刻ではない、とする考え方。

新しい言語

Egison

江木聡志氏によって開発されたパターンマッチング指向の言語で、直感をそのまま表現することができる。記法はLispに似ているがパターンマッチングはHaskellの影響を受けている。
Egisonについて言うと、オンラインインタプリタチュートリアルが面白い。

1~7を選んだあとで、出てくる説明(英文だが簡単)についてコマンドインタプリタですぐにコードを書いて実行することができる。空行でエンターを押すと次の問題に行ける。ただし、練習問題は少し難しい感じがした。

Rust

Mozillaによる並列処理言語。

Golang

Googleによる並列処理言語。
goroutineで並行処理を簡単に書ける。

package main

func func1() {
  ...
}

func func2() {
  ...
}

func main() {
  go func1()
  go func2()
  
  ...
}

Nim

美しい言語です。

Julia

他の技術計算環境のユーザに馴染みのある構文を備えた、高レベル・高パフォーマンスな技術計算にための動的プログラミング言語

Lua

汎用スクリプト言語。高速で比較的容易に実装が可能。

TypeScript

MicrosoftによるJavaScriptの置き換え言語。

Elm

ElmはWebブラウザでUIを宣言的に作成する言語。JavaScriptコンパイルできる。
関数型でとても面白い。

Vala

GLibを使ったC#ライクな言語。Cに変換して使用するため、高速。

Genie

GLibを使ったPythonライクな言語。

Scala

Java仮想マシンで動くスケーラブルな言語。

Elixir

並列処理言語。Erlang仮想マシンで動く。

Pike

静的型付けも動的型付けも可能な面白い言語。変数の型を「intまたはfloat」のように型宣言することができる。

REBOL

通信や分散処理に特化したデータ交換言語。

Viscuit

子供を対象としたヴィジュアルプログラミング言語で、メガネと呼ばれる左右の穴に絵を描くことでプログラミングを行える。

Coq

証明支援システム。プログラミング言語Gallinaを用いる。

Elm

Elm

Elmは関数型で全ての値を不変(イミュータブル)にするWebブラウザのUI作成を行う言語。JavaScriptコンパイルできる。

なんとこんなコードが成り立つ

Elmではなんとこんなコードが成り立つ。

c = a + b
a = 3
b = 5

これは、Elmでは全ての値が不変なので、aとbはどこで使っても同じ3と5を指す。変数を定義の上で使っても下で使っても良い。
また、オブジェクトのプロパティすら不変なので、オブジェクトの値を更新したい時はその都度別の新しいオブジェクトが生まれる。

デジタル情報

二進数

コンピュータは、0と1を使った二進数で計算を行う。
この時、数値のとり得る値の範囲をbit(ビット)という単位で表す。1bitでは0と1の2つの値を表せる。
8bitを1byte(1B、1バイト)と呼び、大きくなるとKB(キロバイト、1024B)やMB(メガバイト、1024×1024B)となる。
CPUなどでは、bitは8bit, 16bit, 32bit, 64bit, 128bit, 256bitと2の累乗を倍々してアーキテクチャの性能が向上していく。
二進数とは、10進数では9の次が10とけた上がりをするが、2進数では1の次が10となる。
位取り記数法では、10進数の場合、10を基数として、1桁目は基数の0乗(すなわち1)、2桁目は基数の1乗(すなわち基数)、3桁目は基数の2乗、と計算できる。
そのため、二進数は2の累乗を用いることで、1101は1\times2^3+1\times2^2+0\times2^1+1\times2^0=13と計算できる。
二進数の一番上の桁をプラスマイナスを表すために使うことも多い。

16進数

二進数を表現するのに便利なのが16進数。2進数と並んで良く使われる。
2進数と16進数は親和性が高く、0000=0 ~ 1111=F(10進数で15)として四桁の2進数の変換が容易で、FFとすればそのまま八桁にできる。
2進数の四桁をそのまま0~Fにできるため、特に値が大きくなってくると10進数に直すよりも16進数に直した方が扱いやすい。
16進数は0xをつけて0x0Fのように表す。

機械語

機械語は、16進数の命令とレジスタへの記憶を使って、CPUに順次命令を行う。

文字データ

文字データは単純に数値に直される。この時、文字コードによってどの文字がどの数値に対応するかが決まる。
英語の文字コードはASCII。日本語はShift-JIS、EUC-JP、UTF-8などが良く使われる。またISO-2022-JPはインターネットメールで良く使われる。

画像・写真データ

画像・写真データは、画像を四角形のピクセル(点)の集まりに変換し、ピクセルごとに数値にする。
この時、解像度(どれくらいの大きさの点にするか)によって画像の粗さとサイズが決まる。
画像データには、

画像形式 説明
JPEG 非可逆圧縮で写真向き
GIF 256色のみだがアニメーションなども可能
PNG 可逆圧縮でWebなどの画像向き
TIFF 画像データに追加情報が付属。スキャナなどで使われる
MPEG 動画形式
PDF どの環境でも同じ見た目を再現できるポータブルな文書形式
BMP 圧縮しない巨大なビットマップ形式
Camera Raw カメラで写真を撮った時の生データ

などがある。

音声データ

音声データは、音声の「波」に変換される。
音声データを一定の時間間隔で離散的に記録することを「標本化」(サンプリング)といい、一定の精度で丸みをつけたりして近似して記録することを「量子化」という。
標本化の際には、「標本化定理」という定理があり、元の最大周波数の2倍以上のサンプリング周波数があれば、正確にサンプリングすることができる。

デジタル情報は劣化しない

デジタル情報は、いくらコピーしても劣化しません。
これは、「似たような図形を描いてください」と伝言ゲームをするのではなく、「コンパスを使って10cmの円を描いてください」と伝言ゲームをするのに近い。
アナログなコピーでは「見た目」をコピーするため、何度もコピーしていると劣化してしまう。
デジタルなコピーでは「情報の値」をコピーするため、何度コピーしても同じ値を維持できる。

さまざまなデータフォーマット

XMLとHTML

XMLは、拡張可能なマークアップ記述言語。HTMLと同様にタグを入れ子にした記法によるフォーマットで、設定ファイルやドキュメントの記述などに使われるほか、AjaxMozillaXULなどもXMLを用いて行われている。
以前はHTMLをXML化したXHTMLが新しい技術として注目されていたが、HTML5の登場によってHTML5が完全に時代を塗り替えたため、XMLは日蔭に追いやられた感がある。
Javaのクラスライブラリなどでも、XMLに対応していて、Javaでプログラムの設定を行うならXMLを使うのが便利である。Antと呼ばれる、XMLベースのMakeのようなビルドシステムは、Java周辺で良く使われている。JavaXMLは親和性が高い。

JSON

また、最近人気のデータフォーマットとして、JSONがある。JSONJavaScriptと親和性が高く、最近のAjaxやMongoDBなどにも使われている。
JSONJavaScriptPythonなどと親和性の高いデータ記述フォーマット。Ajaxなどで使われたりするほか、MongoDBなどのNoSQLデータベースでも使われる。

iniファイルとレジストリ

伝統的な設定ファイルの書式として、iniファイルがある。iniファイルでは、テキストベースのシンプルなデータ記述を行い、コマンドやデーモンなどのアプリケーションの設定に良く使われている。
また、Windowsではレジストリという独自の設定データベースがある。GNOMEではXMLベースのGconfを長らく使っていたが、XMLでは遅いため、バイナリブロブによるdconfへと置換が始まっている。

troff

troffは伝統的なUNIXのドキュメント方式で、UNIXのmanコマンドなどに使われている。

Officeとその他の文書形式

その他のドキュメント記述フォーマットとして、古いものではTeX, PostScript, PDF, MS-Office, OpenDocumentなどがある。

TOML, YAML

また、設定ファイルの記法としては、githubによるTOMLなどがある。他に、シリアライズ用のYAMLなどがある。

Markdown, MediaWiki

また、MarkdownというHTMLよりも簡単な記述フォーマットも存在する。MediaWikiであれば、Wikipediaと同様のWiki記法を使うことができ、MediaWikiの機能であるテンプレートなどを使用できる。

ブログ記法

ブログであれば、Movable Typeはてななどのブログ専用記法も人気である。

Stack Overflow

この文章を読んでもプログラミングのやり方がさっぱり分からないという方は(ほとんどの方がそうだと思います)、海外サイトのStack Overflowという良質なコミュニティ(質問サイト)があるので、そこで修業すると良いかもしれません。