ひしだまの変更履歴

ひしだまHPの更新履歴。
主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。

みんな大好き(嫌い)? セミコロン

2015-08-22 15:50:03 | プログラミング

「関数型プログラミングの関数とは何か」の話をしている最中に、セミコロン「;」について面白い話を聞いたので、別途書いておく。

C言語やJavaでは、文の末尾にセミコロンを付ける。
これくらいいいだろうと思うんだけど、何故か世間にはセミコロンが嫌いな人が居て、新しいプログラミング言語が出ると、特徴のひとつに「セミコロンが不要」とか言い出す始末^^;
おかげで、セミコロンレスJavaなんてものが大流行したりするわけだけどw 

例えばPascalという言語では、セミコロンは文と文の区切りを表す。
すなわち、(ブロック内の)最後の文の末尾には、セミコロンを付けない(付けるとコンパイルエラー!)。
大学でPascalを使ってた頃は、(C言語を先に独学で覚えていたこともあって)よくエラーになったもんだ…。
これに比べれば、常にセミコロンを付けるC言語やJavaは、文法がシンプルで良いと思う(笑)

Haskellになるともっと進んでいて、セミコロンは演算子なのだそうだ!
「前の処理で作られた環境を、次の処理へ受け渡す演算子」だと考えるんだって。うへぇ。


以前聞いた話なんだけど、プログラミング言語の文法にセミコロンがあると、コンパイラーは楽を出来るらしいんだよね。

文の末尾に必ずセミコロンがあるという文法になっていれば、文の途中で解釈できなくなってコンパイルエラーになったとしても、セミコロンが来れば、解釈をリセットして、続きをコンパイルすることが出来る。

個人的には、Scalaの以下のようなトラップを考えると、セミコロンくらい付けてもいーじゃんと思う。

val v = 1
           + 2

→vは(3ではなく)1。

Scalaは改行で文を終えることが出来るので、明確に続いていると分かる場合(行の末尾が+演算子になっているとか)でない限り、そこで文を終了させる。

JavaやC言語なら、以下のように途中に改行があってもvは3になる。

int v = 1
           + 2;

関数型プログラミングとは何かを簡単に説明

2015-08-22 15:18:55 | プログラミング

当ブログのタイトルは、「関数型プログラミングとは何かを簡単に説明しようと思ったんだけどやっぱり簡単ではなかった」というタイトルが長すぎたので、短くしたものです。(詐欺じゃん!(爆))

職場で「“関数型プログラミング”の“関数”って何?」って聞いたところ、自分が知らなかった・忘れていた視点があったので、考えていたこと・教わったことをメモしておきます。

ちなみに、自分は関数型プログラミングについては全く詳しくないので、以下、間違っている点や独自研究wとなっている事があるだろうと思います。


まず、「関数」という文字について。

元々は「function」の訳語として「函数」という字が当てられたそうで。これが中国語の発音でもfunctionに近いらしく、けっこう良い訳語らしい(笑)
しかし日本では常用漢字化に伴い、「函」という字が使えなくなったので、「関」が割り当てられたのだとか。


次に「関数型」という言葉について。
「関数型プログラミング」と言わずに「関数プログラミング」と言え、という人がいるみたいで。

たぶん、プログラミング界隈の用語に「型(type)」というものがあるので、「関数型」と聞いたら「関数を表す型(function type)」というものを想像しそうで、しかしそういう型があるわけじゃないから、型という単語を使うなという主張なのかなぁと思う。

しかしそれだと、「関数型」は「functional」の訳だから、「関数」だと「function」で、「al」がどこか行っちゃうw

個人的には、「オブジェクト指向」に倣って「関数指向」と呼んでみたらどうかなぁと思った。
ただ、オブジェクト指向は「Object Oriented」で「指向(oriented)」という語が元々入っているのに対し、関数指向だとそうじゃないんだよねぇ。

まぁそれはともかく、「関数型プログラミング言語」だと長いので、「関数型言語」と略すのは自然だと思う。「関数言語」という略し方は見たことが無いな^^;


さて、関数型プログラミング言語の特徴としてよく挙げられる事柄のひとつに、「関数が第一級オブジェクトである」というものがある。
ここで言う「オブジェクト」は(オブジェクト指向とは全く無関係で)、「プログラミング言語がサポートしている要素」というようなニュアンスかな。

Java8のStream APIScalaのコレクションでmapやfilterというメソッドに「関数」を渡して処理していくスタイルを、自分は関数型プログラミングの典型だと思っていた。
この為にはメソッド(サブルーチン)の引数に関数を渡せる必要があり、これにはプログラミング言語のサポート(専用の構文)が必要となる。

例えば(Java7以前の)Javaでは「処理」を渡そうと思ったらそういう処理を持つオブジェクトを渡す形になっていた。このままでもコレクションのmapやfilterといったメソッドを呼び出す形式のライブラリーは作れるが、プログラミング言語のサポート無しでそういうコーディングをするのは面倒だ。

ところで、「○○プログラミング言語」は「○○を使ったプログラミングをやりやすくする言語」だと思う。
例えばオブジェクト指向プログラミングは、オブジェクトをサポートしていない言語でも出来る、という話がある。そりゃ、初期のC++はコンパイルするとC言語のソースを出力していたわけで、C言語でもオブジェクト指向プログラミングは出来る。けれど、やはりオブジェクトを扱う機能があってこそ、オブジェクト指向プログラミング言語を名乗れると思う。

なので、関数プログラミング言語なら、関数をサポートするのが条件だと思える。そういう意味で、「関数が第一級オブジェクトである」というのは関数プログラミング言語の唯一の特徴でしょう?(ドヤ)

しかしここで登場するのがJavaScript!
JavaScriptでは関数をサブルーチンの引数に渡すことが出来る。(主にコールバック関数として使う(イベントが発生したときに「渡した関数」が呼ばれる))
あるいはC言語でも関数ポインターという形で、サブルーチンの引数に渡すことが出来る。
ではC言語やJavaScriptが関数プログラミング言語かと言われると、個人的にはしっくり来ない。関数プログラミング言語の定義が「関数をサポートしている」ならば、合っているんだけどね…。

自分が関数型プログラミングの関数の使い道としてまず思い浮かべるのは、mapやfilter。すると、mapやfilterを使うライブラリーがあればいいのかな?
しかし前述の通り、「関数」が無くてもそういったライブラリーは作れる。
ライブラリーの有無でプログラミング言語全般の特徴を語るのも変だしなー。


別の視点として、関数型が何かを考えるに当たり、関数型でないものと比較してみるのは良さそう。
そこで出てきたのが手続き型(オブジェクト指向ではなく)。それは考えたことが無かった!

手続き型プログラミングは、「“状態を持つもの”に対し、その状態を変更する手続きを記述する」というスタイル。
状態を変更する手続きというのは、状態を変える命令(コマンド)を順番に発行するといった事になるらしい。そして、最終的な状態が得られる答えになる、と。
(ちなみに、“状態を持つもの”を格好良く言うと、“チューリングマシン”らしい)
(でも、オブジェクト指向プログラミングも、まさにこれだな。状態を持つもの=オブジェクトに対し、それを変更する手続き=メソッドを呼び出す)

では、これに対する関数型プログラミングがどうかと言うと、「サブルーチンは渡された引数だけを使って演算して答えを返す」「それを次のサブルーチンの引数に渡す」というスタイル。
引数の値が同じなら常に同じ値を返すとか、条件はもう少しあるみたいだけど。いわゆる参照透過性のことだね。個人的には「副作用が無い」と言う方をよく使うけど。
参照透過性を満たすサブルーチンのことを「関数」と呼ぶことになるのかな。
(状態を持たない)関数を呼び出していく方式なので、手続き型とは全く異なる。 

こちらの考え方を採ると、第一級オブジェクトとか、何の関係も無い(爆)
副作用の無いサブルーチンにするというコーディングはどの言語でも出来るし、言語のサポートというのも特に必要としない(C++にはconstという機能があるけど)。あくまでコーディングスタイルであり、それ用の言語というものは無い、ということになる。

そして、この考え方に立つと、JavaScriptが関数型プログラミング言語だと言われても違和感があった理由が分かる。コールバック関数は副作用が無いどころか、副作用を起こすためのものじゃんw(コールバックの呼び出し元に何かを返す為のものではない)
一方、mapやfilterに渡す「関数」は、引数を受け取り、それだけを使って値を返すもの。こちらは参照透過性の考えとずれていない。
つまり、自分の意識の中では、関数型プログラミング(言語)という概念に参照透過性を含めていたわけだ。 


元々自分が考えていたのは

  1. 「○○プログラミング言語」は「○○を扱うプログラミング」をサポートする言語である。
  2. 「関数型プログラミング」は「関数を使うプログラミング」である。
  3. なので、関数型プログラミング言語の条件は、関数が扱えること(関数が第一級オブジェクト)である。
  4. mapやfilterを持つコレクションは、関数が第一級オブジェクトであることを利用したライブラリーである。

だったが、今は、

  1. 関数が第一級オブジェクトである→関数プログラミング言語
  2. 参照透過性を考慮したプログラミングスタイル→関数型プログラミング(「言語」は無い)
  3. この定義だと、「関数型プログラミング」と「関数(型)プログラミング言語」は一致しない。
  4. mapやfilterを持つコレクションは、関数が第一級オブジェクトであることと参照透過性があることを利用したライブラリーおよびコーディングスタイルである。

という感じになった^^;

やっぱ混乱するわ~orz
コーディングスタイル(考え方)の話と、プログラミング言語の要素の話が同じ(似た)言葉で混ざっているのがよくないねー。

結局、教えてもらった一連の話の中で唯一確定したのは、「関数プログラミング言語」「関数型プログラミング」の「関数」は、数学の「関数」ではない、ということ。
プログラミング言語の「関数」の語源はもちろん数学の「関数」だろうけど、数学の関数には厳密な定義があり、それは参照透過性みたいな考え方とも違うのだそうだ。


直訳コメントは不要だと思う

2015-07-01 23:31:57 | プログラミング

不定期に何度も盛り上がる話題、今日は直訳コメントの必要性について(笑)
→『コードを直訳したコメントは必要なのか?「要る派」と「要らない派のまとめ」【 #社畜ちゃん台詞メーカー 】』 

コメントをどこまで付ければいいかということについてはなかなか結論が出ないけれども、「コードを直訳したコメント」はさすがに要らないと思う。


例えばこんなコードは直訳コメントなので、要らないんじゃないか。

// iに1加算する
i += 1;

これが以下のようなコメントなら、直訳ではない。

// ループカウンターをインクリメント
i += 1;

とは言え、このコードの前後を見てiがループカウンターであることがすぐ分かるのであれば、こういったコメントは不要だろう。
しかし、以下のようなコメントだったら?

// 年齢を増やす
i += 1;

これならコメントに意味が出てくる気がする。
しかし この場合は、変数名を何とかしろよって話だよな^^;

// 年齢を増やす
age += 1;

こうなると直訳コメントなので、このコメントは要らない気がする。


もうちょっと別の例。

// 猫の身長に入力データを設定する
dog.setHeight(inputData);

変数名がcatだったら、直訳コメントになって、不要なコメントだった^^;
あるいは、こんなの。

// 猫の身長に入力データを設定する
cat.setWeight(inputData);

これらの場合、コメントが間違っているのか、コードが間違っているのか?

自分の場合、コーディングする前に、どんな処理を行うか考える一環としてコメントに書くことがある。
それに沿ってコーディングしていくので、いわばコメントが実装仕様になっているわけだ。
その観点で言えば、たぶんコードが間違っているんだけど、コードを変えてコメントを変え忘れることもあるわけで、一概には言えないorz
(コメントとコードをまるまるコピペして、片方だけ修正が漏れるってことがよくある…。特にコメントの修正を忘れても、コンパイルエラーにもテスト失敗にもならないから…)

こういうミスを発見するためには直訳コメントであっても意味があるのかもしれない?
あるいは余計なことを考える羽目になるので、やはり直訳コメントは無い方が良い?(コードがミスってれば、テストで発覚するし) 


以下のようなコードだったら、コメントにも意味があると思う。

// 値が一番小さいデータを取得(リストは値の昇順でソート済み)
Hoge min = list.get(0);

これが、「リストの先頭データを取得」なんていう直訳コメントだったら、意味がないと思うけどねw

結局、「事実(どういう処理か)」はコードを見れば分かるので、それを日本語化した直訳コメントは要らない。
どういう「意図」でそういうコードになっているのか、というのはコードを見ても分からないので、コメントが欲しい。

少なくとも、コメントを書くにも結構な労力がかかるので、コードの1行1行に対して必ずコメントを入れろ、なんてのは全くナンセンスだと思う。
(そういう要求をされると、直訳コメントが増える気がするし)


SoftwareDesign2015.01 SI特集の感想

2015-02-21 15:17:22 | プログラミング

ちょっと前の号になるんだけど、『ソフトウェアデザイン 2015年1月号』の第2特集『ソフトウェア開発の未来』が面白かったので、感想を書いておきたい。

この特集ではSI(受託・請負型開発)について、3人の人が書いている。

  1. ソフトウェア受託開発の新しいビジネスモデルへの挑戦
    • 「価値創造契約」の利点と失敗点について
  2. なぜ「受注請負型SI」はなくならないのか
    • SIビジネスについてユーザー企業視点とSIベンダー視点で考察
  3. ユーザ企業の「一人情シス」という選択肢
    • SIerからユーザー企業へ転職してどうだったのか

読む順序としては、真ん中の2.を最初か最後に読むのがお奨め。
というのは、2.には“価値創造契約といった新型SIやユーザー企業への転職が上手くいかない理由”みたいな感じの話題が入っているから。書いている人が別々なので、こういうことも起きるよね^^;


で、主に2.についての感想になるが。

まず、SI市場の現状として、技術が高度化しているのに技術者の供給が細ってきている事(景気停滞時に採用を絞った事や、そもそも若年就労人口が減っている事)を挙げている。また、大型案件が失敗して訴訟に発展するケースも目立ってきている。
それでも受注請負型SIは、ユーザー企業側とSIベンダー側のニーズがマッチしている(SIer側は人月商売だと非常に売りやすい)ので、そうそう無くならない。

ユーザー企業側が受注請負型SIを欲する理由として挙げられている「経営陣の意思決定」に関する話は興味深い。
曰く、ユーザー企業にとってITは本業ではないので経営陣はITに詳しくないし、ITを金食い虫と見なしてしまう。なので、金額が確定しないIT投資は為されないし、「プロジェクト失敗の責任はユーザーにある」となる委任型の請負は却下される。
また、ユーザー企業にとってITは本業ではないのでIT部門に出世・昇進ルートは無い。(つまり、ユーザー企業へ転職しても下請けっぽい位置で止まり、給料は上がらんということですな)(3.の人の転職が成功したのは、転職先が“IT担当者が自分一人しかいないような中小企業”だったからなのかも)
自分はベンダー側の人間なので、ユーザー企業側の内部がどうなっているのか知らないけれど、こうやって説明されると納得いく感じ。

じゃSIをどうするかという選択肢として、挙げているのは2つ。やめる続ける(爆)
まぁ、やめても生活していけるなら、ほとんどの人は辞めるでしょうねぇ^^;
続けるけれども今までのようなやり方では上手くいかないという考えで1.の価値創造契約のような手法も出てきたと思うし、面白いアイデアだとも思うけれども、ベンダー側のニーズで出てきた手法であり、ユーザー企業側のニーズで出てきたものではないので、なかなか広まりにくいんだろうなぁと思う。(まぁ、それは1.を読んでいると、把握されていると思われる) 


以上。
自分が要約して書くとイマイチな感じになってしまうんだけど、当然ながら元の文章の方が説得力・読み応えがあって面白い。
部分的に切り取ってTwitterにつぶやいただけでも、何RTもされること間違いなしw
「我がSIは永遠に不滅なわけです」とか「ちょっとしたSQLが書けて、Excelを使いこなせるのであれば、どこでも食えます。鬱病にかかるリスクも減るでしょう。個人的には超お勧めではあります」とか「俺はおまえに金を払っているから言うことを聞けというユーザがいたのであれば、即刻、関係の再検討を迫るべきです。これは最後の手段ではありません。最初の手段です」とか「普通にできるSIを、普通にできるように準備し、奇をてらわずに普通に行う」とか。 


ここからは余談。上手くまとめられないので、思ったことを適当に箇条書き。

  • 3.の人が書いている悩みは、たぶん、(特に若手の)SIer技術者は同じことを考えると思う。
  • 本来、ユーザーがやりたい事があって、それを作るのがSIの仕事(ユーザー自身は作る技術を持っていないが、作る技術を持っているのがSIer)だと思う。
  • でもユーザー自身が技術を持つ(内製化する)のが一番、齟齬が少ないと思う。というか、システムの当事者意識が違ってくると思う。(ユーザー側の丸投げ精神や、SIer側の他人事のような感覚の問題)
  • 一方で、SIerがユーザーの肩代わりをする(ユーザー業務の知識を持つ(1.の問題意識のひとつ))のも方向性としてはありだろう。プログラミングを知らない人をSIerが雇うのは、業務知識方面(の適性)を期待してという面もあると思う。
  • いずれにしても、ユーザーとSIerの信頼関係が必要。(日本では、お金を払った側が偉い、上(偉い側)は下に何を要求してもよい、という風潮が強い。これは大企業-中小企業だけでなく、上司-部下、客-店員も同様。ひどかったのは、昔Twitterで見たやつ。買った商品を受け取った子供が店の人に「ありがとう」って言ったら、母親が「金を払ってるんだから礼を言う必要は無い」と言った、とか。僕は自分の為に労力を割いてくれた人にお礼を言うのは当然だと思っている(分かり易い例は、宅配。お金を払っているしそういう契約だとはいえ、家まで持ってきてくれたんだから、お礼を言う)。お互い人間なんだから、お互い気持ちよく尊重する関係を目指すべきだと思う。しかしこういう風潮は下からは変えられない。上の立場になったときこそ変える好機だと思うが、「今までそう振舞われてきたのだから、次は自分がそうしてよい」と考える奴が多すぎる)

しょぼちむメモには敵わない

2014-12-16 00:12:11 | プログラミング

しょぼちむ Advent Calendar 2014およびAsakusa Framework Advent Calendar 2014の16日目です。
(しょぼちむアドベントカレンダーの前日はあちょすさん、翌日はきしださんです)


いつも騒がしい楽しい関西方面で最近売り出し中のしょぼちむさん。
関西方面というのは、Twitterの技術系関西クラスターのことです。
最近、その人たち(雪だるまさんとか裏の紙さまとか関西の技術者の実力を東京勢に思い知らせてくれた人とか小さなお酒(ビール)さんとかなんで来たんと言われる人とかみう×2さんとか)の話題でよく出てくるのがしょぼちむさんです。(しょぼちむさんがどこの人なのかは知らないけどw)

そのしょぼちむさんが作っているサイトが、syobochim MEMOです!
実は僕も技術メモのサイトをこっそりひっそり作っているので、けっこう親近感があったのでした(笑)
しかし僕のサイトは、しょぼちむさんに完全に負けていますorz
見た目の綺麗さ・華やかさが全然違いますorz さすがの女子力。(というか、こっちは一面灰色だしw)

でも負けっぱなしは悔しいので、ちょっと粗探ししてみました。(<●>ω<●>)


という訳で気になるのは、各ページに日付の記載が無い事です。

大抵の場合、ウェブページは一度書いたら消すことがありません。つまり、長いこと経つと、書いた対象の最新状態と乖離していきます。日付が書かれていれば、「古い内容かもしれない」ということが読み手に分かります。
(ちなみに、仕事で入手した紙の書類でも、日付を記入しておくと色々便利だったりします)
(ちなみに、当ブログも以前は日付時刻が表示されていたはずなのに、いつの間にか無くなっていますorz どういうこっちゃ) 

ただ、しょぼちむメモはGitHubで作っているようなので、変更の履歴管理が出来るのが良いですね。
僕のサイトもバージョン管理したい気はするのですが、今更なので何もしていません…。
う、またしょぼちむさんに負けたorz


もうひとつ気になるのは、各ページに書いている対象のバージョンの記載が無い事です。

例えばJavaScalaだと、バージョンによって使える文法や機能が違ったりします。(→Javaの新機能
たぶん、しょぼちむメモに書かれているKotlinも同様でしょう。
なので、自分がどのバージョンについて書いているかを記載しておいた方がいいです。
(初めて扱うものについては、自分がどのバージョンを使っているかまで気が回らないかもしれませんが、覚えておく方がいいです。仕事や転職の面接時に、どのバージョンを使っていたか聞かれたりするかもしれません) 

とか言って、自分で出来てない事も多いんですが(汗)
例えばUNIXのコマンド辺りになると、バージョンと言ってもどうすればよいのやらって感じです^^;
有名なところではBSD系とSystemV系で、同名のコマンドでも使い方が微妙に違ったりします。psコマンドでも、オプションが「ps aux」のものと「ps -ef」のものがあります。
自分のUNIXコマンドのページでも、初期の頃はその違いが分からなくて、ごっちゃにしたまま今に至っており、人のことは言えませんorz


えー、ところで、今日はAsakusaFWのアドベントカレンダーを兼ねたいので、なんとか絡めないといけないのです(爆)
しょぼちむメモにAsakusaFWの事が書かれたりすると、関係性が出てくるのですが(笑)
しょぼちむさんはKotlinアイドルらしいので、AsakusaFWアイドルに勧誘するという手もあるかもしれない?!

そうそう、AsakusaFWもバージョンが上がって色々変わってきている面があります。
ソースの書き方自体は(AsakusaFWは後方互換性を重視しているので)ほとんど変わっていないのですが、環境構築・ビルド方法は大きく変わっています。
WordCountの例も、最新の0.7.1に合わせて修正してみました。昔(0.2.1)から比べると、ほんと環境の作り方が簡単になったなぁ、と思います。
見る人によって参考となるバージョンは違うと思いますが、これも、ウェブページに日付やバージョンが明記されているから区別できるのです。

よし、つながった!(笑)