似非プログラマのうんちく

「似非プログラマの覚え書き」出張版

巳年じゃないけど Python やろうぜ(その 1)

どうもすっかりとご無沙汰しておりました。

忙しかったり体調崩したり、なかなかブログに本腰が入れられない状態がずっと続いていましたが、暇になったのでまた再開しようかと思います。今後も相変わらず不定期ですが、なにとぞよろしくお願いいたします。

きっかけ

昨年末に「来年こそ書初めするぜ !」と意気込み、さてどの言語にしようかと考えていたのですが、以前から Django に興味があったので「この流れで行くと Python書初めするのがええかのぅ」ということになりまして、結局 2 日遅れの 1 月 4 日にめでたく Python + Django にて書初めと相成りました。

それから 1 週間ちょい、ほぼ Python をメインにコードを書いておりました。今回はその奮闘記を題材にいたしとうございます。

まずは Python をインストールしなきゃ始まらない

まぁまずは肝心の Python をインストールしなきゃ始まらんわけです。

Python 3.6 リリース !

Welcome to Python.org

いつの間にか Python も 3.6 になってたんですね。というわけでダウンロードしてきました。インストール先は C:\Python\3.6 にしました。

Django、その前に

Django の前に、以前から興味のあった各種パッケージをインストールしていきます。

NumPy (NumPy + MKL)

Python数値計算するやつ。何か n 次元配列とか使えるみたい。Windows にインストールするときはちょい特殊で、下記のサイトから自分にあった whl ファイルを持ってきて pip install しないとダメっぽい。

Python Extension Packages for Windows - Christoph Gohlke

SciPy library

上記の NumPy もそうなのだが、SciPy プロジェクトのコアとなるパッケージの一つで、こいつのことを単に SciPy という人もいる。これも Windows では上記の配布サイトからやはり whl ファイルを持ってきてインストールする。先に NumPy + MKL を入れろと書いてあるので、NumPy + MKL → SciPy の順にインストール。

matplotlib

MATLAB っぽい感じでグラフとか表示できるらしい。Python 3.5 までは単に pip install matplotlib で行けたのだが、Python 3.6 用のは PyPI に転がってないのでやっぱり上記の非公式バイナリ配布サイトから持ってこないといけない。2.0.0 がリリースされて、Python 3.6 向けのパッケージも PyPI に置かれるようになりました。なので普通に pip install matplotlib で行けます。

ちなみに pip install すると依存するパッケージがゴロゴロと入ってくるが、それは pip が勝手に入れてくれるので問題なし。

SymPy

シンボリックに数式計算をしてくれるライブラリ。これも SciPy プロジェクトの一つ。これは普通に pip install sympy で大丈夫。

TensorFlow

Google 社が提供する Python 向けの機械学習ライブラリ。0.12 から Windows にも対応するようになった。matplotlib 同様、Python 3.5 までは普通に pip install tensorflow でオッケー。Python 3.6 については、非公式バイナリ配布サイトから持ってきてインストールする。一緒に wheel もインストールしてくれるので楽チン。

このあともまだまだいろいろとぶち込んでいきますが、続きはまた後ほど。

Apache Maven を使ってみよう(その 3)

Mavenプラグインについて

Mavenプラグインは主に以下のサイトで用意されている。
Maven – Available Plugins
Mojo – MojoHaus Maven Plugins Project

Exec Maven Plugin

前回の課題になっていた、Maven のビルドの実行の際に main を実行するためには、Mojo で用意されている Exec Maven Plugin を利用する。

pom.xml を修正する。

<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>jp.mydns.akanekodou</groupId>
  <artifactId>MavenSample</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>

  <name>MavenSample</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.4.0</version>
        <configuration>
          <mainClass>jp.mydns.akanekodou.App</mainClass>
        </configuration>
        <executions>
          <execution>
            <phase>test</phase>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

build 要素が新たに追加され、その直下に plugins 要素がある。Mavenプラグインにはビルドプラグインとレポーティングプラグインがあり、Exec Maven Plugin はビルドプラグインなので build 要素に追加することになる。

今回は mvn test を実行したら自動的に mvn test exec:java が実行されるように設定している。

mvn test を実行すると…

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running jp.mydns.akanekodou.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.148 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- exec-maven-plugin:1.4.0:java (default) @ MavenSample ---
Hello World!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.490 s
[INFO] Finished at: 2015-08-27T20:57:56+09:00
[INFO] Final Memory: 11M/212M
[INFO] ------------------------------------------------------------------------

確かに実行されている。

Apache Maven を使ってみよう(その 2)

Maven のビルドライフサイクル

Maven のビルドライフサイクルには多数のゴールが設定されている。ちなみにデフォルトのライフサイクルには何と

validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy

こんなにゴールが設定されている。

しかし、実際にはこれを全部使うことはない。以下、主だったものを説明する。

続きを読む

Apache Maven を使ってみよう(その 1)

当ブログではこれまで Apache Maven (以下、Maven) の話題は極力避けてきたが、昨今の開発事情を鑑みるに、最早 Maven なしでは開発がままならない状況になりつつある。Spring MVC では標準のビルドツールとして採用されるなど、Maven は避けては通れないものになっている。

Maven はなぜ便利なのか ?

ビルドライフサイクルの自動化

IDE を使っているとあまりピンと来ないかも知れないが、たくさんの Javaソースコードを一つ一つ手でコンパイルするのは大変な作業である。Maven でプロジェクトを管理しておけば、コマンド一つでコンパイルを含むビルドライフサイクルを全て自動化できる。

依存ライブラリの管理ができる

プロジェクトが依存するライブラリを一つ一つ探してくるのは大変な作業。しかし Maven なら、設定ファイルである pom.xml に記述しておけば Mavenリポジトリから勝手にダウンロードしてくれる。さらに、依存するライブラリが依存する別のライブラリがあれば、ほとんどのケースでそれらも勝手にダウンロードしてくれる。

プラグインによる拡張性

Maven には様々なプラグインがあり、それらを組み込むことで Maven をより使いやすいものに出来る。場合によっては自分でプラグインを作ることも出来る。

Scala や Groovy も O.K.

Maven さえあれば、Java VM 上で動く Scala や Groovy と言った言語での開発も可能。しかも Scala や Groovy を別途インストールする必要がない。

こういった理由により、Maven の使い方を覚えることは非常に有効であり、開発の手間を大いに省くことが可能になる。そこで今回からは Maven の基本的な使い方を連載していこうと思う。

続きを読む

Ruby で FizzBuzz を満喫する

Scala にだいぶSAN値を削られたのでここいらで Ruby に日和ろう(苦笑)。

その 1 : Object#tap を利用する

to_fizzbuzz = -> n {
  "".tap do |_|
    _ << "Fizz" if n % 3 == 0
    _ << "Buzz" if n % 5 == 0
    break n if _.empty?
  end
}

puts 1.upto(100).map(&to_fizzbuzz)

RubyObject#tap はブロック内で自分自身に対して行われた破壊的変更が保証される。break が発動するとそれらの変更を破棄して強制的に別の値を返すことが出来る。発動しなければブロック内で行われた破壊的変更を適用した自身が返ることになる。

さくっと lambda 奴を使っておくと Enumerable#mapProc オブジェクトを渡す Ruby らしい書き方で処理が記述できる。

その 2 : Hash を利用する

Scala 編で Map を使ったやつの元ネタ。

Applicators = {3 => :Fizz, 5 => :Buzz}

to_fizzbuzz = -> n {
  fb = Applicators.select{|_| n % _ == 0}.values.join
  fb.empty? ? n : fb
}

puts 1.upto(100).map(&to_fizzbuzz)

やってることはほぼ一緒。メソッド名が違うだけ。

その 3 : Enumerable#zip を利用する

fizz = [nil] * 2 << :Fizz
buzz = [nil] * 4 << :Buzz

1.upto(100).zip(fizz.cycle, buzz.cycle) do |n, *f|
  puts f.any? ? f.join : n
end

ネットで見つけてきた。nilany の使い方が Ruby っぽくてお気に入りである。

続きを読む

Scala でとことん FizzBuzz する(その 4)

最初にお詫び。前回の記事にかなり大幅な修正を加えています。再度確認をしていただけるとありがたいです。

追記 : 今回作ったソースファイル群(+ テストコード)を GitHub で公開しました。
akaneko3/FizzBuzzScala · GitHub

続きを読む

Scala でとことん FizzBuzz する(その 3)

さぁ、改造を続けよう。

FizzBuzz アルゴリズム再考

ちょっとひねって、次のような写像を考える。

何も書いていないところは空文字列を対応させていると考える。これを利用して、FizzBuzzアルゴリズムを少し変更する。

  1. 何らかの方法で "", "", "Fizz", "", "Buzz", "Fizz", "", "", "Fizz", "Buzz", "", "Fizz", "", "", "FizzBuzz", ... と繰り返される列を用意する。
  2. 1 から順に上記の列と対応させていく(zip)
  3. 上記で得られた列を順に処理していくとき、「数字と空文字列」の組み合わせのときは数字を、「数字と空でない文字列」の組み合わせのときは文字列を返すようにする。

これを Scalaトレイトを利用して抽象クラスとしてあらかじめ作っておく。

package jp.mydns.akanekodou.scala.fizzbuzz

abstract class FizzBuzz {
  protected val fb : Stream[String]

  def fizzbuzz : Unit = {
    1 to 100 zip fb map {
      case (n, "") => n
      case (_, s) => s
    } foreach println
  }
}

Java のインターフェースと違い、Scala のトレイトにはこうした共通処理をあらかじめ実装しておくことが出来る。今回、ついでなので表示するところまでまとめて実装してみた。

2015/04/12 追記 : 今回のケースではトレイトを使う必要はありませんでした。お詫びの上、通常の抽象クラスに訂正させていただきます。

もう一つ、Scala の機能である「暗黙引数」を利用している。一見するとメソッドの引数のデフォルト値をあらかじめ与えるのと似ているが、あちらはあらかじめ引数を初期化しておかないとダメなのに対し、こちらはメソッド呼び出し時までに暗黙引数を初期化・確定させておけば良い。

Java の抽象クラスは「抽象メソッドが含まれるクラス」であるが、Scala の場合は抽象メソッドに加えて上記のような抽象フィールドを含むクラスも抽象クラスとして定義しなければならない。

2015/04/12 追記 2 : MainFizzBuzz 系クラスを継承させる方法が何となく行儀が悪く見えたので止めました。

その他のファイルも適宜書き換えていこう。

package jp.mydns.akanekodou.scala.fizzbuzz

class FirstFizzBuzz extends FizzBuzz {
  def toFizzBuzz(n : Int) : String = {
    if (n % 3 == 0) {
      if (n % 5 == 0)
        "FizzBuzz"
      else
        "Fizz"
    } else if (n % 5 == 0) {
      "Buzz"
    } else {
      ""
    }
  }

  val fb = Stream.from(1).map(toFizzBuzz)
}

toFizzBuzz は最早 String 型しか返さないことが明白になった。

package jp.mydns.akanekodou.scala

import jp.mydns.akanekodou.scala.fizzbuzz._

object Main extends App {
  (new FirstFizzBuzz).fizzbuzz
}

Main.scala がだいぶすっきりした。

いよいよ本格的に改造していくぞ !

続きを読む