Programming basics

Mimir Yokohama

2017-12-24

プログラムとプログラミング

プログラムとは

コンピュータに対する動作を規定したもの

OSも、アプリも、全てプログラム

幅広いので領域も分かれている

「プログラム」という言葉は「食べ物」というくらい幅広い

プログラミングとは

普通はプログラムを作る行為ではない

作るものは最終的にはプログラムになる

ただし、実際に作るのはプログラムの「もと」

プログラミングによって作られるプログラムは 「人が書くためのもの」

コンピュータが動作するプログラムは 「コンピュータが理解するためのもの」

前者をソースコード、 後者をバイナリコードという

中にはバイナリコードを直接書く人もいる(いた)

しかし、実際はそれは今や超特殊な例であり、

プログラミングはソースコードを書く行為である

プログラミング言語

プログラミング言語とは

プログラミング言語は「規格」と「実装」がある

「規格」は、プログラミング言語の文法や語彙を定めたもの

実際にそのような規則で書いたソースコードを動かす方法があるかは別。

「規格はあるけれど実装がないので動かせない」言語も存在する

「実装」はソースコードをプログラムとして動作させる「処理系」と呼ばれるプログラムのこと。

実際に書いたソースコードがどのように動作するかは最終的に実装で決まる

(ただし、もしその実装が規格に背いていたならば、処理系のバグということになる)

C言語は明確な規格が存在し、これに対して「公式の処理系」というのは存在していない

それぞれの処理系は規格に沿っているはずだが、実際には同じソースコードを異なる処理系でコンパイルするのは難しい

Perl5は規格が存在しておらず、公式の処理系が存在する。

公式の処理系がどのように動作するか、ということが言語仕様を決めている形。

Rubyは規格化されているが、規格の更新速度は遅い。

そのため、Ruby公式処理系の実装から見れば「規格は古いRubyの仕様」という感覚となる

Perl6は公式によって規格が策定され、その規格を満たすよう処理系が実装されている。

どちらも公式によって進められているが、それぞれ別に進められており、規格のほうが先行している

プログラミング言語の種別

パラダイム別

手続き型言語

その世界で名前で呼び出すことで実行できる処理 (サブルーチン)を呼び出す方式

サブルーチンには値を与えることができる

次の例では文字列の書き出しを行うfwriteサブルーチンに 出力先としてSTDERR、出力する文字列としてHelloを与えている。

メリットは単純で、初歩的な記述がしやすいこと、 簡単な処理であれば短く書けること。

デメリットは、名前が涸渇しやすく、「名前としてはかぶるけれど機能は全く違う」サブルーチンを必要とする時に困ること

名前が涸渇しやすいという点は、モジュール化しづらいなど、 「プログラムが大きくなればなるほど顕著な問題になる」 という特性を持つ

また、サブルーチンの戻り値を値としてサブルーチンを呼び出す場合は左右いったりきたりするため、読みづらくなる。 次の例ではSTDERRに書き出す文字列はgethelloの戻り値である

オブジェクト指向言語

オブジェクトに対してメッセージを送る形式をとる方式。

手続き型言語が「アクションだけを呼び出す」ものであるのに対し、 オブジェクト指向言語では「何がどういうアクションをする」という形式になる

次の例ではSTDERRに対して出力を行うputsを行うように求めている。 出力内容としてHelloを与えている

オブジェクト指向言語は原則左から右というカタチが取られるため読みやすい。

また、名前がそれぞれオブジェクトに属しているため、名前の問題が低減される。

次の例ではMath(数学)の三角関数sin(サイン)と、 Moral(道徳)のsin(罪)のメソッドを呼び出している

どちらもsinという名前だが、別物である

関数型言語

プログラムを数学的「式」として記述する方式。

同じ式を与えたとき、同じ結果が得られる、という前提に基づいている

手続き型言語やオブジェクト指向言語はコンピュータの動作に着目している。

対して、関数型言語では式としての完全性を重視する。

手続き型言語では変数として名前を与えられた値、 オブジェクト指向言語ではオブジェクトは、 それぞれ処理によってその値が変化する可能性がある。

関数型言語では値は常に式によって導かれるもので、変化することはない。

次の例ではhPutStrLnという関数にstderrHelloという値を与えている。

手続き型言語との違いがわかりにくいので、標準入力から読んだ値を標準エラー出力に書く、ということをしてみる。

手続き型言語(PHP)

関数型言語(Haskell)

処理系形態別

インタープリタ型

一行ずつ(あるいは一文ずつ)読み込んで順に解釈するタイプ

たとえ文法が間違っていたとしてもその間違っている文に到達するまではエラーにもならない

昔非常によく使われた教育用言語のBASICなどがこの形式

現在ではシェルスクリプト以外ではほとんど使われない

例: BASIC, Bash, Zsh, cmd.exe, WSH

コンパイル型

実行する前に事前にバイナリコードを生成するタイプ

速度的には有利だけれども、コードの修正を繰り返す場合は手間がかかる

また、バイナリコードになってしまっているため、異なる環境にもっていくと動作しない

現在でも採用例は多く、新規の言語も少なくない

例: C, C++, D, Go, Haskell, OCaml, Fortran, COBOL

スクリプト型

実行しようとするとき処理系にソースコードを与えるタイプ。 直感的にはソースコードを実行するように感じる。

修正から実行のフェーズが速いため、開発速度が向上する。 一方、実行するたびにソースコードから変換する必要があり、時間にはロスがある。

一般には開発速度を重視しており、開発しやすいことに重きが置かれているため、 実行速度は犠牲になっている場合が多い。

また、通常はソースコードはなんらかの中間形式(多くの場合はバイトコード)またはバイナリコードに変換されてから実行される。

現在は人気が高い。

例: Perl, Ruby, Python, Lisp, PHP, Lua, JavaScript

バイトインタープリタ型

実行する前にバイトコードと呼ばれる中間形式に変換し、 実行しようとするときにはVMと呼ばれる処理系がバイトコードを実行するタイプ

バイナリコードはマシンやOSに依存しており、 種類の違うマシンやOSでは動作しない。

バイトコードにしておけば、そのマシンで動作するVMさえあれば動作する、と考えられる。

コンパイル言語の速度とスクリプト言語の柔軟さの中間にある

バイトインタープリタ型の言語は少ないけれども、多くのスクリプト言語処理系は内部的にバイトインタープリタ型である

Rubyは1.8までは構文木にコンパイルし、構文木インタープリタで実行していたが、 1.9からは構文木をさらにバイトコードにコンパイルし、バイトコードインタープリタで実行する方式になった。

例: Java, .NET(C#)

業務分野・職業スキル別

システム開発系

システム開発ではC, C++が優勢。 Windows向けにはC#、MacではObjective-CまたはSwiftが使われる。 JavaやGoを使う職場もある。

分野としても難易度が高く、人材も少ないが、働き口も少なく配属されにくいところが多い。

Web系

開発の花形とも言えるWeb系。

Java, Ruby, PHPが3大勢力で、PHPはシェアを減らしている真っ最中。 PHPの仕事は主に旧来から使われているCMS(WordPressやEC-Cubeなど)のものが多い

働き口が非常に多い一方、劣悪な労働環境も多いと言われている。

特にJava関係は環境が刷新されず開発環境も悪いケースが少なくない模様。

ゲーム系

分野にもよるものの、Windows向けの本格的なゲームではC, C++, C#が多く、 比較的ライトなゲーム、特にアドベンチャーゲームやノベルゲームではRuby, Python, JavaScriptの比率も高い。

モバイルゲームではJava, JavaScript, Swift, Pythonの比率が高い。

モバイルアプリ

Android向けではJava, iOS向けではSwiftがネイティブ言語である

そのほかクロスプラットフォームライブラリを介してJavaScript, Python, C#などが人気。

ロボット系

C言語、あるいはC類似の言語が多い。

Java, JavaScript, Pythonでの制御も多く、 稀にRubyを用いることもある。

金融系

金融系(特に勘定系システム)においてはCOBOLがほとんどである。

旧時代の遺物とも言うべき“恐ろしい”言語であるが、 COBOLを使えるエンジニアは貴重であり、銀行に入れるだけの経歴さえあれば かなりの好条件が期待できる。

型付け別

静的型付け

ある名前がどのようなデータを取るかということを宣言したらそれ以外のデータ型を取ることはできない。 たとえば「この変数は整数がある」と言えば、その変数に文字列を入れることはできない。

自分で明確に管理することができ、開発時にIDEが適切な値の候補を絞り込んでくれる。 不適切な代入は早期に発見できる、といったことがメリット。

ただし、その分冗長な記述が増え、管理の手間も増える。

例: C, C++, D, Java, Go, Perl

動的型付け

その名前にどのような値が入っているかということは感知せず流動的である。 記述が少なく楽になる。

例: Ruby, Lua

オプショナルな静的型付け

静的型で指定することもできるし、動的型を使用することもできる。 あるいは、静的型で指定したとしてもそれは「そう言っているだけ」で違う型のデータを入れても怒られない。

例: JavaScript, PHP, Zsh

結合別

静的結合

関数やサブルーチンに与えるべき値の型は明確に決まっており、 それ以外を与えた時点で(例え解釈可能であっても)エラーになる。

例: C, C++, Java, Go

動的結合

与えられた値は型ではなく値としての正当性が問われる。 多くの場合、想定したものと異なるデータ型である場合、暗黙に変換が行われる。

例: PHP, Zsh, Perl

ダックタイピング

オブジェクト指向特有。

値はデータ型がなにかではなく、目的とするメソッドを持っているかを問われる。 要求するオブジェクトが必要とするメソッドで答えることができるのであれば、その結果を値とする。

この名前は

もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである

というダックテストに由来する。

多様性別

TMTOWTDI

Perlのスローガンであり、“There’s More Than One Way To Do It” (やり方はいろいろある)

様々な書き方を許し、様々なアプローチを許し、 プログラマが書きやすいように、書きたいように書くことができるものである。

One True Way

たったひとつの正しいやり方があり、あることをしたいのであればその書き方をしなければならない、というもの。

書き方が少ない分、読むコスト、そして読めるようになるための学習コストが少ない、という。 Pythonが強くこの考え方を採用する。

向き不向きの話

理系・文系

IT業界には「文系プログラマ」とバカにする風潮がある

だが、実際のところ「語彙を編纂する」という作業は至って文系的な作業である。

文章を組み立てるのと同じく、主語があり、動詞があり、目的語があり、それを助詞でつなぐものだ。

しかし、文系的作業によるプログラミングは「既存の組み合わせで目的とするものを編纂する」色合いが強い。

アルゴリズムなどプログラミングを根底から変えるものはほとんどが数学であり、文系的アプローチからは生まれにくい。 パフォーマンスチューニングなどの理系分野もあり、「研究分野は理系、文系は作業員」という面がなくもない

しかし別の言い方をすれば:

「文章を書けない文系」にも「数学のできない理系」にもアドバンテージはない。

実際のところ文系プログラマと嘲笑う理系プログラマのレベルなど底辺に近い。

なぜならば、ある程度の実力があれば「文系」「理系」などよりもはるかに誇るべき成果を手にすることができるのであり、 「理系」ということをレーゾンデートルとして自分を上に見せようとしている時点で「自分に他のカードがない」ということをひけらかしているためだ。

Ruby作者のまつもとゆきひろ氏は「数学がとても苦手」と公言している。

Perl作者のLarry Wall氏は言語学者である。

逆に文系の最たるものに思われる組版システムであるTeXを開発したDonald E. Knuth氏は数学者である。

結局のところ、文章力がなければプログラミングはできないし、 数学ができなければ発明は難しいのである。

大学がどこでも、学部がどこでも、個人の資質で欠けているものを補ってくれるわけではない。

向いている人

次に示すのはRubyのハローワールドコードである。

これを実行するとHello world!と出力される。

$ ruby hello.rb
Hello, world!

代わりに一行読み込んで変数とし、それを出力の中に組み込んでみる。

次のコードはJavaScriptである

ボックスに名前を入れてボタンをクリックすると挨拶し、

さらに青色のボックスは右に移動する。

次のコードはPerlである

-pオプションと併用することで、入力した内容から数字だけを抽出する。

次のコードはYAMLで書かれたダミーデータからテキスト処理で名前とふりがなを抽出し、

名前 (ふりがな)

の形式にする。-nオプションつきのPerlである。

わくわくする?

今は見ているだけ

でも、あなたの指先が自在にこうして編纂するとしたら

あなたの思ったことを、

あなた指先が編み綴り、

コンピュータがその命のままにそれを成し遂げるとしたら

もっとわくわくする?

「ふーん」と思った人は向いてない。

わくわくした人は才能がある。

向くべき方向

意識の問題

プロになることは、底辺にすぎない

一般の職業プログラマのレベルは48時間の学習で到達できるレベルに収まることが多い。

おおよそプログラミングスキルもピラミッド構造になっている。 職業プログラマのレベルとは、上辺と最底辺を除いた範囲にある。

むしろ職業プログラマに高いスキルは好まれない。

IT業界の一般的構造として、代替が効く安い人材が好まれるためだ。

高いスキルを使われると代替人材が入手しづらくなるため、 むしろ嫌われる傾向がある。

一般的なIT業界の構造は製造業のライン従業員のそれに非常に似た仕事を求められる。

わかりきった、定形の作業を淡々とこなすのであり、 創造性は求められないばかりが、邪魔であるとされる

「仕事ができるスキル」を求めるのであれば、どちらかといえばスキルの話ではなく身の処し方の話になる。

この違いは非常に自由用である。

プログラミングの学習というのは人生における投資である。

それによって生産性を向上させればそのために費やした時間も回収することは全く難しくない。

プログラミングによってよりよい人生を手にすることも可能だ。

自分がありたい方向性を定めることは極めて重要だ。

目指す方向性

一般職業プログラマ

一般職業プログラマは底辺レベルでは数時間程度の学習でインスタントに製造されて人材が投入されている。

スキルとは無縁に近いが、ただし一般職業プログラマでもある程度レベルの高い人物はいるのであり、 あとはどれだけプログラミングが、コンピュータが好きか、という問題になる。

一般職業プログラマを目指す場合、 プログラミングよりも、業界での身の処し方のほうが重要な要素である。

どのように生き残り、どのように立場を確保し、賃金を確保するかといった話だ。

流れ作業でこなすための「決まったスキル」であり、その実施自体は「理解してなくても適用すべきものを選択する能力さえあれば良い」ということになる。

スキル・プログラマ

主にフリーランスとして、プログラミング技術で食べていくという人が少数ながら存在する。

このようなスキルプログラマは多くは派遣社員であり、暮らしぶりはタフなものである場合が多い。

スキルプログラマの一部は高い賃金を獲得できている。

スキルプログラマとしての行き先は、いずれ自分を買ってくれる企業との契約(雇用)を目指した流浪人であるか、 もしくはスペシャリストとして起業するための前段であるかである。

苦しい状況、楽しみのない日々でもタフに生きられる精神と肉体も必要となる。

スキルプログラマは、一般に業務で多く必要とされるものそれぞれに通じているか、 もしくは業務で必要とされる特定のものを極めて知悉しているかのどちらかである。

多くの企業にとって人材を必要としているポイントに合致し、主力級として活躍できる使いやすい人材であるか、

もしくは特定の分野で人材要求自体は高いがレベルの高い要求を達成することのできるスタッフがいない場合に起用できるかということだ。

辛く険しいが、職業プログラマの中では望む人の多い道でもある。

しかし、業務の退屈さは緩和されないようだ。

フルスタックエンジニア

プログラミングはスキルの一部、インフラ構築、システム設計、サーバー構築、アプリケーション設計、データベース設計、アプリケーション開発、運用、 そのすべてに活躍する人材である。

通じ用の職業エンジニアは特定分野の特定のことだけを学ぶ。

全般的な知識を持ち、いずれのポジションもこなすことができるフルスタックエンジニアは貴重であり、賃金も高い。

しかも、それぞれの分野に対してなにかひとつできるでは通用しなくなり、分野ごとの知識も広汎になる。

しかも仕事が遅ければ結局のところできる仕事はひとつとなり価値が発揮されない。

IT業界では特殊人材であり、求められるものも他のエンジニアとは異なり、 担当箇所が増えるほどに自由度が上がり創造性も増す。

ただし、換えがきかず、賃金が高く、依存度も上がり、通常の流れ作業の部品として扱う構造に合致しないということで、 求人の口はかなり少ない。

フルスタックエンジニアは貴重であるが、かといって採用はされにくいのが現実である。

フルスタックエンジニアは単にスキルの問題ではなく、「コンピュータが好き」であり、 「コンピュータを探求したい」という人でなければ務まらない。

IT業界におけるハッカー的ポジションがフルスタックエンジニアだ。

なお、フルスタックエンジニアは社内SEとして安い賃金で酷使されるポジションに置かれることも少なくない。

この場合はその価値を認めてくれているかどうかで雲泥の差になる。

生産性

コンピュータはどれほど退屈な作業でも、どれほど大量の作業でも文句を言うことはない。

そして、コンピュータにとって処理しやすい動作において、コンピュータは人間よりはるかに高速である。

そのため、人間の操作1つに対して1つの反応を返す対話的操作において、ほとんどの時間コンピュータはその能力をほとんど使わず眠っている。

そうした作業をコンピュータに任せれば、人間は時間を他のことに回すことができる。

もちろん、生産的な時間に使っても、楽しい時間に使っても、休息に当てても構わない。

例えば次のスクリプトは 1.HTM1000.HTMというファイルを、 0001.html … 1000.html という形式に変更するZshスクリプトである。

生産性を向上させるプログラムは通常短く簡単なものだが、 自分がしようとしていることをいかにロジックに置き換えられるかというスキルが求められる。

生産的プログラミングを行うためには少なくとも中級以上の腕前が必要になるだろう。

ハッキング

あなたが使っているプログラムが必要な機能がない、あるいは機能が微妙に気に入らないとする。

そのプログラム自体は有用なのだが、痒いところに手が届かない、そんなときだ。

“それなら自分で書いてしまおう”

これがハッキングである。

生産的プログラムよりも発展的、ほしいもの、必要なものは自分で作る、 気に入らないのなら自分で直す、というスタイルである。

お金のためではなく、自分のよりよいコンピュータライフのためにスキルを行使する。

それが誰にとっても有用なものであったなら、公開したり、コントリビュートするという道もあるだろう。

OSS開発への参加

OSS(オープンソースソフトウェア)は “ボランティアによる開発” と言われることも多いが、実際にはそのようなことはない。

特に大規模なソフトウェアにおいては、何らかの形でお金をもらって開発している人のほうがずっと多い。

OSSはソースコードが公開されており、その利用も自由である。

この改修も自由であり、あなたが有志であるならばそのソフトウェアに対して貢献することもできる。

(ただし、開発への参加プロセスがオープンであるかどうかはプロジェクトによる)

OSSの開発参加はあなたの人生において生きがいになるかもしれないし、 あなたのブランド力を高めることにもなるかもしれない。

多くのメジャーなOSSは、大多数のIT企業では触ることもできない高度で大規模なソフトウェアであり、 あなたが望むなら(そしてそれに見合う能力があるのならば)その開発に携わることができる。

原則としてソフトウェアの世界では「作る人が使っているものを作るほうが上」である。

コンパイラであるgcc、基礎ライブラリであるglib、 あるいはOSであるLinuxやFreeBSDなどの開発はプログラミングにおける頂点のひとつでもある。

ソフトウェア開発

サービスとして公開する、OSSとして公開する、製品として販売する、道は色々あるが、そのためのソフトウェアを作るというのはひとつの到達点である。

多くのIT企業では、WordPressなど既存のソフトウェアを使った「構築作業」であるが、 そのWordPressそのものなどサービスを構成するソフトウェアを開発するのは「自社開発」「プロプライエタリ開発」といって憧れとなっている。

それを自分ひとりで、あるいはその代表者として開発するという道である。

自社ソフトウェアを開発する企業の社長になることは必ずしもスキルと密接な関係があるわけではなく、 経営能力や商才のほうが重要になってくる場合が多い。

だが、自らがリードして開発するのであれば、それに足るスキルと、 人の動向を見極めるセンスが必要となる。

ソフトウェアだけでなくサービスまでを提供する話でいうならば、たとえばTwitterやFacebook、instagramなどを自分で立ち上げるという話だ。

もちろん、技術的に高度なソフトウェアを作っても構わない。

これもまた、ひとつの到達点であり、その野望を抱く人は少なくない。 もしもうまくいけば巨万の富を手にする可能性もあるだろう。

言語選択

特定の言語でのプログラミングを習得するのであればその言語を中心に学習することになるだろう。

特に、職業プログラマとしての定型業務のためであればほとんど暗記のようなものである。

プログラミングを幅広く学習するための教材としては、 Mimir YokohamaではPerlとJavaScriptを推奨している。

Mimir Yokohamaの基本的な考え方としては、理解しないまま作法を覚えるのはむしろ上達を妨げるというものだ。

プログラミングの基礎学習において重視しているのは

  • プログラミングの楽しさを味わう
  • 条件、反復などのプログラミング的感覚に慣れる
  • コードを見たときに構造を直感的に理解できる感覚を養う

このため、プログラミング初学においてMimir Yokohamaとしては:

  • 余計な要素の記述が少なく、意図や思考との一致度が高いほうが良い
  • 記述の特殊性が低く、最大公約数のような言語仕様が好ましい
  • 視覚的フィードバックなど、自分の記述が理解しやすい
  • トライアンドエラーが容易

が良いとしている。

JavaScriptは決して普通な言語ではない。

プロトタイプベースオブジェクト指向言語というのはむしろ非常に特殊であり、 コンパクトな言語仕様ゆえの特殊性がある。

むしろ世の中ではJavaScriptの特殊性を「劣っている」とみなすほど

しかしながらその特殊性に関わる以前のところとして見ると、非常に前述の条件を満たす。

オブジェクトの理解には良いけれどオブジェクト指向の作法には使わない、 イベントドリブンプログラミングは触らないなどの条件で初学に使用している。

PerlもC言語などでなじまれてきた記法に近く、 また後の言語に対する影響も多いため、やはり標準的な記述ができる。

ただし、文字列操作、参照と値、オブジェクト指向などは極端な特殊さが目立つ。

これらについては深く踏み込まないように使用している。

Perlディスに関して

ネットでPerlについて調べると、極めて多くのPerlディス記事が見つかる。

これは主に歴史的経緯による。

Perlは1987年生誕と、かなりの歴史を持つ。

WWWの発展期からPerl/CGIという仕組みがwebアプリケーションにおいて極めて多様された。

Webアプリケーション, CGI, Perlという3つの異なる概念が混同されていたほどである。

2003年頃から「ブログ」が流行り始め、Movable Typeというソフトウェアが大流行した。 Movable Typeは主にPerlで書かれ、一部PHPが使われていた。

しかし、MT側のアクションが顰蹙を買ったこともあり、 2005年以降人気はPHPで書かれたWordPressに移行する。

この頃から“Linux + Apache + MySQL + PHP”を意味するLAMPという語の流行、 そしてメディアが先導した“Web 2.0”という語の流行から 「Perlは過去の遺物の象徴」という思想によるPerlバッシングがはじまる。

現在に至ってはLinux以外の3要素はすべて衰退に向かっている状況であるが、 PHPでエンジニアになった、PHPで仕事をしている、あるいはWordPressは使っているからPHPは触れる、 という人が少なくなく、 結果としてこのような風潮が非常に根強くなっている。

実際、Perlに対して罵詈雑言を浴びせている人が賞賛しているのは大抵PHPである

あえて今webアプリケーションの言語としてPerlを採用するメリットは特にないが、 そもそもPerlはWeb向けの言語ではなくテキスト処理言語である。

さらにいえば、Unix系システムにおいてはPerlは日常作業を行う基本的なツールであり、 Perlを使えないということは「コマンドラインでの作業能力に乏しい」というのと同義となる

Perlの習得は(Windowsユーザーであっても)日常作業への貢献度が高いが、 実際にはPerlが特段問題があるわけでもなく、 Perlディスはほとんどの場合Perlへの理解もないまま「Perlを批判することでわかっているということをアピールする」目的となっている。

しかし、Perlが素晴らしいわけでもない。

個人的な好みはありながらも、それでも快適でないケースや、苦痛なケースがそれなりにある。

データ構造とリファレンスに関しては、オブジェクト指向化しない限り苦痛以外に何者でもないし、 そのオブジェクト指向が面倒な上に非常に書きづらい。

なお、このあたりはすべてPerl5の話で、Perl6という最新の全く別の言語が存在する。

Perl6はPerl5と互換性がないばかりか、Perl5までに積み上げたものの全否定すらしている

Perl6は「素晴らしい」のではなく「野心的」だと思うが、 前述のような「Perlは古い」という感覚はなにも日本だけのものではないので、 どうにも情報が少なく学習しづらい状況にある。 また、Perl6はそもそも未完成である。

プログラミングの要素

プログラミングは根源的には以下の4つしかない

  • 値に名前をつける
  • 計算する
  • 条件によって処理を分岐する
  • ジャンプする

「ジャンプする」はプログラムの流れを極めて追いにくくする。

BASICやFortranではこれが標準的な手法だったが、 現代では非推奨、あるいは禁止として、別の手段が提供されている。

次のようなものだ:

  • ループする
  • 処理をまとまりにして名前をつけ、呼び出す

基本的な要素について見ていこう。

値に名前をつける

手続き型プログラミングでは「変数」と呼ばれる。

計算する

プログラムにおける計算とプログラミングにおける計算は別物であるため、 計算ではなく処理呼び出しというのが普通だろう。

以下は計算ではあるが、実際は処理呼び出しである。

条件式

条件式は「条件が真であれば以下を実行する」という書き方が一般的。

「真(true)」や「偽(false)」を「論理値(boolian)」という。

ループする

ループは主に2種類だ。

条件式を伴って、条件が真である限り(あるいは偽である限り)繰り返すというもの。

そしてイテレータと呼ばれる「集まりの要素ひとつずつに対して繰り返す」 というもの。

次の例ではapple, orange そして grapeをジュースにする。

初期化式、条件式、継続式の3つの式が書ける3 part for loopというものもある。

しかし、ほとんどの場合コレクションの各要素のためにしか使われてこなかったため、 モダンな言語ではイテレータに置き換えられる傾向がある。

処理に名前をつけて呼び出す

手続き型言語では「サブルーチン」あるいは「関数」、 オブジェクト指向言語では「メソッド」と呼ばれることが多い。

次の例では与えられた値を2乗する関数powerを定義する。

先程定義した関数powerを呼び出す。

プログラミング上達の道

楽しむ

プログラミングは根源的に楽しい行為である。

たとえ、毎日の単純作業のようなプログラミングに苦痛をもらし続けるエンジニアでも、 休暇中にのびのび好きなようにプログラムを書きたい、という人は意外なほど多い。

Ruby開発者のまつもとゆきひろ氏は次のように語っている。

Rubyは純粋に楽しみのために設計され、言語を作る人、使う人、学ぶ人すべてが楽しめることを目的としています。 しかし、ただ単に楽しいだけではありません。Rubyは実用性も十分です。実用性がなければ楽しめないではありませんか。

コンピュータに仕事をさせる

Perlの作者であるLarry Wall氏はプログラマの三大美徳として

  • 無精(Laziness)
  • 短気(Impatince)
  • 傲慢(Hubris)

を挙げている。

氏の言葉を借りよう。

無精: エネルギーの総支出を減らすために、多大な努力をするように、あなたをかりたてる性質。 こうして労力を省くために書いたプログラムは他人にも使われるようになり、 そのプログラムに関する質問にいちいち答える労力を省くためにドキュメントを書くようになる。

短気: コンピュータがサボっているときにあなたが感じる怒り。 あなたの司令に反応するだけでなく、実際の司令を予測する―少なくともそのようなふりをする― プログラムを書く原動力になる。

傲慢: ゼウスの怒りにふれるほど、プライドが高いこと。 また、他人にケチをつけられないようなプログラムを書く(そして維持する)ための原動力になるもの。

とにかく書く

実際のところ書いていればいいというものではないのだが、 書いて積み重ねて失敗しなければわからないこともある。

少なくとも人の批判をしたり、貶したりする時間があるなら、コードを書いたほうが尊敬されるだろう。

論理性を磨く

プログラミングは本質的に論理である。

プログラミング言語の違いも、結局のところその論理をどのように表現するかの違いに過ぎない。 同じ命題に対して回答にたどり着くための式はひとつではないが。

よって論理的思考力の形成は極めて重要である。

別に将棋やチェスをする必要はない。 その事象が必ず収束する条件を考えるのだ。

プログラミングの極意

最も重要なのは、論理性である。

プログラミングの世界では「真」または「偽」というのは極めて重要な概念である。

これに慣れる、ということはとても重要な話である。

そのために、日常的に論理的に、そして実行フローをもって考えるということはとても良い。

たとえば、私があなたと食事をすることになったとしよう。

私はとても中華料理が食べたい。 しかしながら、あなたと食事をするのははじめてであり、あなたの食の好みはわからない。

そこで、あなたが食べたいかどうかにかかわらず、中華料理が嫌いでなければ中華料理を食べることにする。

私は中華料理が食べたくて仕方がないので、第二の案はない。なので、あなたが中華料理を嫌いだった場合は、あなたの食べたいところへ行くことにする。

これは次のように考えられる

if( you.dislike.include?(中華料理) ) { go(you.want) }
else                                 { go(中華料理店) }

プログラムに「曖昧」は原則としてない。

この条件では、あなたが中華料理の気分ではなかったとしても、あるいは昨日の夕食が中華料理ではなかったとしても、 それともあなたがとてもオムライスを食べたかったとしても、中華料理が嫌いでない限りは中華料理店に行くということだ。

もう少しマイルドにしよう。

もしあなたに希望があったならばそれに従う。 あるいは中華料理が嫌いだった場合もだ。

そうでないならば中華料理店に行く。

するとこうなる。

if( you.want || you.dislike.include?(中華料理) ) { go(you.want) }
else { go(中華料理店) }

しかしきっとこれは失敗するだろう。

あなたに希望がなかったときに中華料理が嫌いかどうかを訪ねている。 そして中華料理が嫌いだった場合はあなたの希望の店にいくことにしている。

しかしそのときは希望は特にないのだから、これはエラーになるに違いない。

では、希望がなくて中華料理が嫌いなら話し合いをすることにしよう。

if( you.want ) { go(you.want) }
elsif( you.dislike.include?(中華料理) ) { conference }
else { go(中華料理店) }

これでだいぶ穏当になったが、しかしまだ問題だ。

特に希望のないあなたと、どうしても中華料理がたべたい私との間での話し合いはあまり建設的なものにならないだろう。

お腹がすいているのだからケンカになってしまうかもしれない。それはよくない。

せめて建設的な話し合いのために候補を考えておくべきだ。

どうしても中華料理の気分なのでなかなか大変だが、いくつかの候補を用意し、 イテレータで回して順に提案してみることにしよう。

if( you.want ) { go(you.want) }
elsif( you.dislike.include?(中華料理) ) {
  [焼肉, ハンバーガー, 蕎麦, ラーメン].each ->($i) {
    if(you.accept($i)) { go($i) }
  }
}
else { go(中華料理店) }

もっと掘り下げながらロジックを構築していくことはできるが、 コードブロックがスライドに収まらなくなるためやめておこう。

学び方

もちろん、Mimir Yokohama

Mimir Yokohamaの授業はもちろん、良いものである。

教材もあなたに合わせて作られるのだから、あなたにとって一番良い学習になるのは間違いない。

単に講義をするだけではない。 トレーニングや、最適な自習方法の提案など、完全なフォローが待っている。

本での学習はあまり勧めない

コンピュータ関連の書籍は、少し聞きかじった程度のレベルで書かれた、誤りや不適切な内容の多いものが溢れている。

もちろん、すぐれた書籍もあるが、それを見つけ出すのはかなり大変であり、 結果回り道をする可能性は高い

回り道ならばまだよくて、頭の中の回路がこんがらがって学習困難になる場合もある。

それでも本が良い、という場合、「当たりが多い」として信頼されているのが オライリーによって出版されている書籍である。

ハッカーならばオライリーの書籍なしには暮らしていけないだろう。

ウェブ媒体は玉石混合

公式のリファレンスなどを除けば、良いものも多いが、内容などないに等しいものも少なくない。

精査することであなたの貴重な人生の時間を無駄にする可能性は、低くない。

公式ドキュメントは不可欠

ドキュメントは宝である。

もし充実した公式のドキュメントがあるならば、それを無視するべきではない。

多くの場合、公式ドキュメントが最も正確である。

もちろん、公式ドキュメントすらでも正しい保証はないのだが、 まず最初に読むべきものであることは間違いない。

また、公式に近いドキュメントも有効である。

例えば、HTML, CSS, JavaScriptに関する情報は、公式であるW3Cよりも、 Firefoxの開発元であるMozilaによる MDN(Mozilla Developer Network)のほうが優れた情報を掲載している。

ただ、このようなドキュメントは英語である可能性が高い。

プログラミングをしたいのであれば、英語ドキュメントが読めることはとても大事だ。

英会話の能力ではない。英文が読める能力でもない。 英語ドキュメントを読む能力である。

最悪ソースコードがある

ドキュメントがなくても、使われているものであれば重要な手がかりが存在する。

ソースコードだ。

ソースコード学習を推奨する人は非常に多いし、私もソースコードと共に育った人間だが、 決してソースコード学習を推奨はしない。

現代のソースコードは付属する要素が多く、分量的にも学習には適さないものが大半である。

OSSであればサンプルコードが付属していたりする。

このようなものは有用だが、それなりにスキルがないと読み解くことも難しい。

もちろん、初歩的なチュートリアルコードと向き合うことには価値がある。

自習する場合には、非常に時間はかかるものの、インターネット上にあるチュートリアルコードを探してみるのも悪くない。

【宣伝】

Mimir Yokohamaの開発サービスではEducational Codeオプションをご用意 レベルにあわせた読みやすく、理解しやすい記述と、 記述内容と意図、動作などに対するコメントが書かれた学習用コードで納品

「自分で作るのはまだちょっと難しい」コードを教材を兼ねてぜひご注文ください

なお、web文書に掲載されているコードや、雑誌に掲載されているコードを信用してはいけない。

書いているだけで、動くかどうか確認していないことのほうがずっと多い。

チュートリアルの不完全さ

実のところ、私が2017年現在までにコンピュータ関連の書籍、雑誌に費やした額は、800万円近い。

コンピュータ関連書籍一冊の値段は、およそ5000円程度が相場である。

その経験からしても、チュートリアルにある情報というのは大概にして不完全である。

その情報だけでは論理的に確定できないのだ。

そのため、非常に多くの文献を照合し、網を狭めていって論理的に確定するところまで持っていかなくてはいけない。

かなり大変な作業である。

Mimir Yokohamaの授業はこの完全性を担うものである。

「教わる」のはあまり有効ではない

サービスとして教えながらなんということを言うのだ、という話でもあるが、 基本的にプログラミングというのは教わるものではない。

特に職場で誰かについて教わるというのは、不毛な結果を招く可能性が高く、推奨できない。

後輩が自分より有能になって自分の立場がなくなる、というのは誰しも嫌なものである。 そのため、到達点を自分が知りうるものよりも上に設定する人は稀である。

そうでなくとも、そもそも自分の能力限界以上に教えるということは不可能だ。

また、本来的にエンジニアとは流動的なものである。 ひとところにとどまればその中での身の処し方や、立場、利益が占める割合も大きくなる。

エンジニアでなければ「尊敬できる先輩を見つけてついていく」形が良いのかについても疑問はあるものの、 少なくともエンジニアにとってそれは良い道ではない。

基本的には上を見て、得られるものはすべて吸収する、というのがよい考え方である。

もちろん、この授業から得たものを糧に、私の届かない頂まで到達してくれても構わない。 それは初学に携わった者として本望であり、遠慮はいらない。

基本的に教えることができるレベルというのは、自身の60から90%程度である。

ただし、教わることで成長できる度合いは、教えられる限界に近づくほど低下する。 それでいながら、自力で成長できる度合いは自身の能力が向上するほど一旦は向上する。

このことから、「教わるのはなるべく初学段階から、可能な限りレベルが高い人に教わる」ことが重要となる。

ただし、単にレベルが高いだけでなく、教えるのが好きで、かつうまい人である必要がある。

大抵のハッカーは教えることは極めてうまい。

ただし、ハッカーをその気にさせることが難しいだろう。

(Mimir Yokohamaの出発点でもあった)

もちろん、Mimir Yokohamaは他のどの手段よりも最善の手段を提供する。

しかしながら授業としては中級までしかないのは、それ以上のレベルは教えることで成長を妨げる可能性があるからだ。

自らが羽ばたけるところまで連れて行く、それがMimir Yokohamaの基本的なスタンスである。

最終的には技術で殴り合え

我々は知識や思考力を含めたスキルを以て相手に挑むことを「技術で殴る」と表現する。

多くの場合は質問の形か、あるいは提案などに対する反論の形で行われる。

質問に対して適切に答えられるか、疑念や批判、要望に対して答を持っているかというのは結局のところ力の差である。

メーリングリストで、イシューリポートで、あらゆるところでハッカーたちは技術をぶつけあっている。

その最たるものはやはりカンファレンスである。

カンファレンスでの発表は誉れ高く、賞賛に包まれることだろう。

しかし、我こそはという者は挑みかかるべく耳を澄ませている。

ほとんどの場合は、どれほど聞き、考えたところで一分の隙も見つけられないだろう。 相手を認め、賞賛を送る以外にはないのだ。

あるいは果敢に挑んだところで相手は登壇者、その実力を前に粉々に砕かれることになるだろう。

それでも知識を蓄え、思考力を磨き、もてる技術のすべてをさらけ出して挑み、 そして打ち砕かれることを繰り返しながら成長することができる。

OSSの世界は優しくはない。しかし、その挑戦は受け入れてくれることだろう。

誰かに教わるべきこともなく、 本も、webも、ドキュメントも自分の疑問に答を持たなくなる日が訪れたときは、 そこに挑むことをおすすめしたい。