読者です 読者をやめる 読者になる 読者になる

わくわくとオーボエ

プログラミングの話題とかとか

スーパーフライデー?

雑記

フライが安くなる日 というのはなんとなく見えている
それ以外で思うことをなんとなくツラツラと書く。

IT企業の普段の業務

って多くの場合、(他社の)業務の効率化だと思うんですよね。
IT企業というのは主語が大きいけど、売上高を基準としていわゆるWeb系のベンチャー企業を除けば、
「貴社の業務を効率化」とか「その仕事引き受けます」みたいな文言は付いていることが多いような。

勤務時間を減らす策

作業効率を上げて早く帰りましょうとは言うものの、
思いつく範囲で、効果の示せる効率化なんてすでにやっていますよね。
やらない理由もないですよね。

「テストが手動で効率が悪い」「エクセル方眼紙が…」「PCスペックが…」みたいな話はあるかもしれないけど、
それが変わらないというのは、管理者レベルの人たちがそれを変えることによって「効率化できる」と思ってないからだと思うんですよね。
だから、首相とかが何を言おうとも、そういう方向の変化は起きない気がする。

じゃあどうするのか

業務時間を短くする圧力だけは高まっていく。

コンサルに頼るのが一番の解決策なのかなーとぼんやり思っている。
コンサルという職種は口が上手いだけな人も多そうで好きではなかったのだが(というか今もあれだが)、
外からそれらしき事を経営層に吹き込むことができるという点では素晴らしい。
同じことを説明するのにも、社内の下っ端からの意見より、高い金の対価として外部からもらった意見の方が信じる気になりやすいだろう。

本当は

こんな諦め気味な書き込みをしてしまう時点でダメとか言われそうな気がする。
でも、上の話に戻ってしまうけど、効率化しようとして効率化できるなら、すでにやってると思う。
違うのかな。

仕事の活用方法

雑記

大学時代の友人と飲み…ではなくて焼肉に行ってきた。(・ω・)オイシカッタ

とりとめもない話をしたのだけど、そのときの話題のひとつが、
「仕事ってプライベートに何か活かせたりするの?」
だった。

業界も職種も全然違う人なので、単純に興味で聞いたんだと思うけど、自分にとっては新鮮な発想だった。

仕事とプライベートを「切り離す」という話はよく聞く。その方が効率が上がるからという理由を話す人もいれば、業務外でPCに触りたくないみたいな人もいる。

逆に、家でもコーディングしてます、それが趣味ですからという人もいる。
自分はどちらかというとこちらか。ただ、資格勉強したりとかもするし、その時のモチベーションの1つは「業務で活かせる」だ。

「仕事をプライベートに活かす」という話は聞かない。結果的にそうなっている時もよくあるのだろうが、そういう表現は聞かない。
業務内容が趣味と一緒ですというのと、大きな違いがあるわけではないけど、発想がちょっと新鮮だった。
改めて自分の業務を振り返ってみると、ちょっと違う世界になるかもしれない。

こういう、ちょっとした気づきのもとをもらうことが多い。

手を動かしてみて学ぶ (日経ソフトウェアの特集記事を通して)

プログラミング 雑記

事の発端

先日、日経ソフトウェアの2016年11月号を買ってきました。

主な目的としては、付録のWPFについての冊子。なかなか情報無いのでね。前に連載してたのは知っていたけど、日経ソフトウェアはあまり買わないので。
(Software Design, WEB-DB Press, 日経ソフトウェア の順に買う頻度が減る感じかな。どれも興味のある刊しか買ってない。)

ただ、特集1の後半、PHPのLaravelなるフレームワークを使った開発例が載っててちょっぴり興味を覚えました。 というのも、Webの話題(特にセキュリティまわり)では何かとPHPに触れられるのに、自分自身はPHPを全く触れたことがなかったため。
加えて、Laravelというフレームワークは聞いたことが無かったというのもあり。(自分が知らなかっただけで、かなり有名らしいですね。)

そんなわけで、普段は流し読みだけのところ、実際にコードを打ち込みながら勉強してみました。
そんな時のあれこれのメモというか日記。

(特集記事も商品なので、極力ソースコードが出てこないようにしてます。読みにくいですがあしからず。)

作業

Ubuntuのバージョンは最新ではないのかとか、やや疑問に思いつつ、基本的に記事に従う形で進めることに。

なんか遅いしエラーでたけど...??

Composer(PHPのライブラリ管理ツール、これも今回知った)で、Laravelを使うアプリのプロジェクトを作成。

composer create-project (略)

と打つ。
待つ。
待つ。
……なにか間違ったかな(・_・)?

そう、妙に遅い。

そして、やっと動いたと思ったら、次のようなメッセージが。

Failed to decode response: zlib_decode(): data error

…? デグレードしてやり直して今度は成功しました的なメッセージも出たけど、なんのことやら。
そんなエラーに関して、当然ながら特集記事には書いてない。

こういう記事もあるので、みんな経験しているのだろうか。
Composerが超遅い件

またエラーだけど? @git

記事では、開発フローの体験ということでgitを使って(形だけだが)コードを管理している。
というわけで、記事に書いてある通りのタイミングで、書いてある通りにgit commitしようとする。

…あれ?またエラーでた。

これはgitを知っていたのですぐに気づいた。
git addしていないのだ。

この記事を書いた人は、実際にはコマンドを打っていないのだなと認識した。
そんなものなのだろう。

サーバーにアクセスできない @環境準備での失敗

gitにcommitもしたし、まずはサーバーにアクセス。
ブラウザにURLを打ち込みEnterを押す!

…アクセスできない。

これはすぐには理由が分からず。

結論としては、PHPのビルトインWebサーバーでは、デフォルトではlocalhost指定でないと動かないということ。 自身のIPアドレスを指定するのと、localhost指定するのと、127.0.0.1指定するのと同値だと思っていたよ…(´・ω・`)これは自分の勉強不足。

気づくのに遅れた理由の一つが、環境が記事とちょっと違ったこと。
記事ではBash on Windowsを薦めていたのだが、なんとなく嫌だったのでVirtualBoxUbuntuを用意することに。
(それでも良いと書いてあったし。)

ただ、今思えば、おそらく記事で意図していたのはDesktop用のUbuntuUbuntu内のブラウザから、localhost指定でアクセスする前提だったのかと。

自分はUbuntu Serverを用意してSSHでアクセスしてて、VirtualBoxのNAT機能でアクセスしようとしていたので。 ちょっとした(自分にとっての)はまりポイントでした。

正直、これがPHPの用意している機能なのかLaravelの用意している機能なのかも分からないまま検索することに。
こちらも先人のおかげで解決しました。
Laravelのartisanでサーバを立ち上げた時にプライベートIPでアクセスできない問題と、その対処法 - Front-end beginner's luck

Postできない…?

やっとアクセスできるようになったものの、 まだすぐには記事通りに進まず。

POSTしようとすると、MethodNotAllowedHttpExceptionが投げられる。
なぜ。

理由はなんてことなく、以下2点。 - HTML上で<form method="POST"&gtとしなければならないところを、&ltform mehtod="POST"&gtとミスタイプしていた。 - IlluminateをIllumminateとミスタイプしていた。

特に1点目、この場合、GETでリクエストが飛ぶんですね。
POSTに対する処理は書いていたけど、GETに対する処理を書いていなかったから、エラーになっていたと。

PHP初めてだしLaraval+Bladeとかいうのも初めてだし、単純なことにもなかなか気づかず。
試しにGETで書いてみたり、最終的にはFiddlerで飛んでるリクエストを覗いたりして解決に。

IDEとか使わず、カスタマイズを何もしていないvim(そもそもvimを普段使わない)で書いたのが敗因でした。

思ったこと

雑誌の特集記事とか、だいたい眺めて終わりにしているんですが、
意外とハマりポイントあるんですね。

IDE使えば解決できることだったり、 元記事の誤植だったり、 いやそんなもの初めから気づけよ的な話だったりするかもしれませんが、 本題とは別のところでもハマりポイント=学びポイントはありますね。

手を動かせとはよく言う話ですが、たしかに必要だなと思いました。
(実際には時間との兼ね合いなんですけどね。)

その他

artisanの読み方がわからず

Javaのenumとswitchとコンパイル結果

プログラミング Java

目的

Oracleの配布しているJDKと、Eclipseで使われるJDKで、コンパイル後のファイル数が違うケースに気づいたのでメモ。
switch文でenumを使う時のコンパイル結果についてです。

本題

Javaenumが、ただの定数ではなくて特殊なクラスとして扱われるのは有名なことかと思います。EffectiveJava(読みかけ 汗)にも書いてありました。
クラスなので、コンパイルすればenum定義は一つの.classファイルになります。クラス内で定義したら、staticな内部クラスとして、やっぱり別の.classになります。

ところで、そんなenumの利点として、switch文の条件にできるという点があります。
では、このようなコードはコンパイルするとどういったファイル名になるでしょうか?

Person.java

public class Person {
    public void work(Day day) {
        switch (day) {
        case SAT:
            System.out.println("寝て過ごす");
            break;
        case SUN:
            System.out.println("遊びに出かける");
            break;
        default:
            System.out.println("働く");
            break;
        }
    }
}

Day.java

public enum Day {
    MON, TUE, WED, THU, FRI, SAT, SUN
}

Eclipseコンパイル結果は予想通り

自分は、当然Person.classとDay.classの2つになると思ってました。
そして、Eclipseを使うとその通りになります。(バージョンは4.2と4.5で確認)

Oracle JDKでは違った

でも、OracleJDK(1.7)のjavacを使ったら、
* Day.class * Person.class * Person$1.class の3つになりました。なぜだ(・д・)

javap Person$1.class とすると、

Compiled from "Person.java"
class Person$1 {
  static final int[] $SwitchMap$Day;
  static {};
}

だそうな???

検索すると次のような記事に当たります

enum 定数の switch 文の実装 - happynowの日記

Java列挙型メモ(Hishidama's Java enum Memo)

enumの値が変わったり増減したりしても、enumを使う側はコンパイルし直さなくても済むというのがenumの特徴です。そういった挙動を既存の文法だけで再表現するための実装として、Oracleのjavacでは内部的に勝手にクラスを作っていたんですね。そしてEclipseコンパイラでは別の実装になっていると。

感想

Javaではクラスごとに.classファイルが作られることになっています。
しかも無名のクラスは$1のような通し番号のついたクラスになったりします。

実装依存なのだとしても、コンパイル後のファイル数まで違ってしまうのはなんとも気持ち悪いというか。
たとえば1つの.javaファイルから100個の.classが作られることも許されているのかなみたいな。
コンパイル後のことなんて気にするなと言われれば、まぁそうなんですが...('_')ナンダカナー

全然別の話題ですが

またオーボエはじめました。

VS2015ならconstexprでコンパイル時演算でき…ない??

C++ プログラミング

事の経緯

前回・前々回と、C++のTemplateを使った処理について書きました。 そして、以前知人が

まだ実行時ソートで消耗してるの? 〜ScalaでHListを使ったコンパイル時クイックソート 〜 (前編) - だいたいよくわからないブログ

とかいう記事を書いてるのを思い出し、C++でもできるかなーと考え始めたわけです。(某煽り記事が話題になった時に書かれたのでタイトルはあれですが、中身はまじめな技術記事ですので念のため・ω・)

はじめはTemplateで上の記事の内容を真似ようかなと思ったものの、最近のC++ならconstexprがあるからソート処理くらいならそれでできそうだなと考え始めたわけです。

constexprとは

…いろんな記事が出てるので、そちらを見てください。自分もちゃんと使おうと思ったのは初めてなので。。

Visual Studio 2015でも使えるよね ってことはMicrosoftの出してる情報で確認しました。

constexpr (C++)

コンパイル時演算の確認方法

constexprは、コンパイル時に引数の値が決定できる場合はコンパイル時に処理を行います。 一方、実行時まで引数の値が分からない場合には、普通の関数のように振る舞います。 そのため、コンパイルが通ったからといってそれだけではコンパイル時演算できている保証はできません。。

コンパイル時に演算できているかの確認は上記情報によると、

注: Visual Studio デバッガーでは、内部にブレークポイントを挿入することで、constexpr 関数がコンパイル時に評価されているかどうかがわかります。 ブレークポイントにヒットすると、実行時に関数が呼び出されます。 ヒットしなければ、コンパイル時に関数が呼び出されます。

とのこと。翻訳前の英語も確認したけれど、ちゃんと同じ意味のことが書いてありました。

うまくいかない…??

ソートには比較が必須ですからね、まずは値の大小比較をする関数を準備せねば。 ためしに以下のようにコードを書き、実行してみました。 ブレークポイントで止まらないことを確認すればいいんだな。

F5をポチッ

f:id:wkwkhautbois:20160731204731p:plain

……止まった( ・_・)??

おかしい、コンパイル時に値が計算されていたらここに入るはずがない…。

原因として思いついたのは2点

  1. Debugモードでコンパイルしているとコンパイル時演算されない
  2. VC++コンパイラコンパイル時演算してくれない

1つめのDebugモードだからというのは有力だけど、このくらい簡単な計算だとconstexpr指定にしなくても最適化されてインライン展開されてしまうので、ブレークポイントで確認ができないという。 (だったらconstexpr指定しなくても良いという話もある。)

2つめのVC++コンパイラだからというのは、別のコンパイラで試せば分かるはず。 今のVS2015はコンパイラとしてClangを使うことができる。そちらに切り替えると、たしかにブレークポイントで止まらないのでコンパイル時に演算できてそうな雰囲気。

まとめ

少なくともVC++15のコンパイラでは、Debugビルドだとconstexprでも実行時処理になるみたい。

何がいけないのか知ってる人がいたら教えてほしいです。

引数が数値がかどうか判定(SFINAE)

C++ プログラミング

前回に引き続きC++の型まわりで。
整数でも実数でも良いから、とにかく数値を引数にとりたいときとかってありません?自分は時々あります。画像処理をしている時とか。
常にdoubleで扱うのもいいですけど、せっかく整数で扱えるなら整数のまま扱いたい。でもかといって、int用とdouble用みたいに分けたくない。そんなもやもやな時が。

やりたいこと

引数が数値かどうかによって処理を分岐する。
実行時ではなくコンパイル時に分岐をする。

実現方法

SFINAEという原理(?)を使い、template関数に対する以下のどちらかで実現する。

  1. 関数の(普通の)引数のオーバーロード解決を利用する
  2. テンプレート引数のオーバーロード解決を利用する。

この記事では、算術型 = 数値型 とみなす。厳密には、四則演算が定義されているかどうかなので違うけど、四則演算できるならまぁ良いじゃん的な。

先にコードを

SFINAEって?

templateクラスやtemplate関数のオーバーロードの解決方法の方針。
「当てはまりそうだったから試したけどだめでした!」→「よし次試すかー」
そんな感じで順に試していくというだけで、たいして難しい考え方ではないと思う。コンパイラ自体の実装は大変そうだけど。
詳しいことは各自検索で。以下のサイトなどを参考に。

d.hatena.ne.jp

数値かどうかの判定箇所

template関数の普通のオーバーロード解決 : 上のコードでいう f()
数値の場合

関数の引数に注目。第2引数の型が、std::enable_if<std::is_arithmetic<T>::value>::type* になっていますね。

void f(T arg, typename std::enable_if<std::is_arithmetic<T>::value>::type* t = 0)

std::is_arithmetic<T>::value は、Tが算術型だったときはtrueに、それ以外の時はfalseになります。つまり、たとえばTがintであれば(コンパイルの途中で)以下のように変換されます。

void f(int arg, typename std::enable_if<true>::type* t = 0)

ところで、std::enable_if<bool>::typeはテンプレート引数がtrueかfalseかによって定義変わります。 std::enable_if<true>は(template第2引数で特別指定をしなければ)void定義として定義るので、これはさらに

void f(int arg, void* t = 0)

に変換されます。なんか見慣れた感じに落ち着きましたね。(C++ではvoid*ってあまり使わないですけど。)問題なく展開できたので、f(3)とか書かれてたらこの関数が呼ばれます。

非数値(正確には非算術型)の場合

はじめに

void f(T arg, typename std::enable_if<std::is_arithmetic<T>::value>::type* t = 0)

を適用しようとすることには変わりません。そして、Tが非算術型の場合、std::is_arithmetic<T>::valueはfalseになるので、 std::enable_if<false>::type で定義される型を求めようとします。
しかし、 std::enable_if<false>にはtypeというものが定義されていません(・ω・;)こまりましたねー
すると、コンパイラは諦めて他のオーバーロード候補が無いか探します。他に無ければコンパイルエラーになります。これで、templateを使いつつも一部の型だけに適応することができますね!

今回は非数値でも処理ができるように、別途次のようにオーバーロードを定義しています。

void f(T arg, typename std::enable_if<!std::is_arithmetic<T>::value>::type* t = 0)

見た目ややこしいですが、std::is_arithmetic<T>::valueの結果を!で反転させています。だから、数値でないものに対してはこちらのオーバーロードが無事解決できるようになります。

template引数のオーバーロード解決 : 上のコードでいう g()

(普通の)引数は、これ以外にもオーバーロードしたいことがよくある。template引数を使って分岐した方が間違いが少なくなるし、型で分岐してることがなんとなく伝わりやすい気がする。

実装での基本的な考え方は同じなので省略。ただ、こちらではダミー変数を使ってあげないと、デフォルト引数を指定できないらしい。extern指定すれば、他ファイルに影響したり無駄なメモリが確保されたりもしないので、問題無いと言えば問題ない。

その他

数値判定以外にも、いろいろな判定をできるメタ関数が標準で揃っているみたい。以下の記事にまとまっている。

qiita.com

あとは、記事というかcppreferenceにはやっぱり必要な情報は載っていますね。

Type support (basic types, RTTI, type traits) - cppreference.com

まとめ

  1. template使うと対象の型をコンパイル時に絞り込めたりする。
  2. 可能性は無限大、可読性は微妙。
こちらも参照ください

qiita.com

C++で型クラスっぽいこと - Traits

C++ プログラミング

背景

昨日(一昨日か)の型クラス勉強会に参加してきました。
ただ、残念ながら自分はScalaHaskellもSMLも明るくないしUr/Webとかいうのは初耳だったので、整理を兼ねて++で型クラスっぽい実装を。
(C++分かるとか書いたらいろいろ飛んできそうなのでそんなことは書けないのですが)

@k_katsumiさんの発表(https://speakerdeck.com/kishikawakatsumi/type-classes-in-swift)をまねて、シーザー暗号の関数を作ってみました。

目的

  • Traitsの使い方を(自分が)理解する
  • 他言語での型クラスのありがたみを理解する

ソース

何やってるの?

最初にこういうコードを見た時はギョッとしました(・д・)が、昨日Swiftのコードを見た後にこれを考えたら以外とスッキリ。自分なりの考え方としては以下の通り。

  1. 最終的に encodeInCaesar(123) や encodeInCaesar("hoge")の形で呼び出せるtemplate関数encodeInCaesar(T t)を作りたい。つまり引数の型Tによって、内部の処理を分岐させたい。
  2. 対象の型ごとに処理が変わるように特殊化された型CaesarTraits<T>を用意する。encodeInCaesar(T t)の中でCaesarTraits<T>を使えば処理の分岐ができる。
  3. 特殊化しなかったらコンパイルエラーになるように、基本のCaesarTraits<T>では何もメンバ関数を定義しない。

CaesarTraits<T> を通してデータにアクセスするという取り決めがSwiftのprotocol定義、CaesarTraits<T>を対象の型ごとに特殊化するというのがSwiftのExtension定義に相当してます。

C++のtemplateはダックタイピング的で、使い方が同じあれば型の意味とか関係なくコンパイルできてしまいます。一方で、templateは特殊化することで、特定の型について別の挙動を与えることができます。前者がparametric polymorphism、後者がad-hoc polymorphism。encodeInCaesar()関数はparametric polymorphismを利用していて、その先では実はad-hoc polymorphismになっている。だから全体としてはad-hocに振る舞う。
という認識なんですが、合ってますかね(・o・)??

まとめ

  1. 落ち着いて考えたらC++でもTraits使って型クラス的なものが書けた。
  2. でも書くのちょっと大変だしコンパイルエラーがわかりにくくて辛いのではやく文法としてのConcept (http://en.cppreference.com/w/cpp/language/constraints) がほしい。Conceptが採用されるとコンパイラの解析が楽になってエラーも見やすくなるはずなのだけど…いつ正式採用されるのかな...

その他

Wordpress.comでたまーに書いてたんですけど、ちょっとはてなブログに移ってきてみました。間違ったこと書いてそのままなのは良くないと思うので、優しいマサカリをお願いします。

参考

  1. https://speakerdeck.com/kishikawakatsumi/type-classes-in-swift
  2. http://faithandbrave.hateblo.jp/entry/20110318/1300427444
  3. http://faithandbrave.hateblo.jp/entry/20130226/1361862112