ししちにじゅうはち 4x7=28

よんたったー https://twitter.com/keita44_f4

elpyの設定メモ

Emacsにelpyを設定して四苦八苦した結果をメモ。
他にも苦しんでる人のために。
必要なPython環境をWindowsに用意する方法は前エントリを参照。

苦しんだ点とかまとめ

  • elpyはpython modeと一緒に動くメジャーモード
    • key-mapについて
      • python modeとelpy modeのkey-mapは別々に存在する
      • elpy起動時にpython modeのkey-mapをelpy modeのそれで上書きする
      • ショートカットの設定はelpy側のkey-mapに設定する
    • elpyの起動について
      • .pyファイルに対してpython modeとelpy modeの両方をオンしないといけない
      • python-mode-hookにelpyの起動をねじ込んだ
  • elpyの起動には(package-initialize)がいる

参考になったところ

設定したEmacsの設定ファイル(init.el)

;;; python mode
(add-hook 'python-mode-hook
          '(lambda ()
             (setq indent-tabs-mode nil)
             (setq indent-level 4)
             (setq python-indent 4)
             (setq tab-width 4)
             (package-initialize)       ; なぜかこれが無いとelpyが動かない
             (elpy-enable)
             (elpy-mode)
             ))

;;; elpy mode
;; pythonのrope、jediのパッケージを入れておくこと
;; 公式はさらにflake8、importmagic、autopep8、yapfを推奨している
(add-hook 'elpy-mode-hook
          '(lambda ()
             (elpy-use-ipython)
             ;; quickrunをC-cC-cに設定
             (define-key elpy-mode-map "\C-c\C-c" 'quickrun)
             ;; company-mode + rope/jediを使うためautocompletionをオフ
             (auto-complete-mode -1)
             ; companyによる補完のキーマップを設定
             (define-key company-active-map (kbd "\C-n") 'company-select-next)
             (define-key
               company-active-map (kbd "\C-p") 'company-select-previous)
             (define-key
               company-active-map (kbd "\C-d") 'company-show-doc-buffer)
             (define-key
               company-active-map (kbd "<tab>") 'company-complete)
             ))

;;; py-autopep8
;; pythonのautopep8のパッケージを入れておくこと
(add-hook 'python-mode-hook 'py-autopep8-enable-on-save)

;;; python flymake
;; pythonのpyflakesのパッケージを入れておくこと
(require 'tramp-cmds)
(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
     ; Make sure it's not a remote buffer or flymake would not work
     (when (not (subsetp (list (current-buffer)) (tramp-list-remote-buffers)))
      (let* ((temp-file (flymake-init-create-temp-buffer-copy
                         'flymake-create-temp-inplace))
             (local-file (file-relative-name
                          temp-file
                          (file-name-directory buffer-file-name))))
        (list "pyflakes" (list local-file)))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))
(add-hook 'python-mode-hook
          (lambda ()
            (flymake-mode t)))

苦しんだ話

  • 最初は、2つ目の.pyファイルを開かないとelpyがenableにならなかった。
  • さらに、python modeでquickrunのショートカットを設定したせいで、elpyが起動するとquickrunが動かないように見えた
  • elpyのバグかと思って見てたら、お互いのショートカットが別々に存在していた。
  • elpyではC-cC-cをpython-shell-send-bufferとやらで上書きしていて、c\:/〜/ipython.exeなる謎のエスケープが入ったipythonが呼ばれてて混乱した。

2016年4月のWindows+msys2+Emacsでうまく動くPython環境について

Windowsのいろいろうまく動くPythonのインストールにむっちゃ苦労したのでメモしておく

動かしたいもの

  • Python2.7(できればPython3.4も)
  • Emacs + pyflakes(flycheckすごい便利)
  • Emacs + pep8(自動でコーディングルールを整えるのすごい便利)
  • matplotlib(グラフプロットするGUIライブラリ)
  • scipy(計算ライブラリ)

それぞれ試したものとまとめ

  • Anaconda
    • WindowsGUIやpyflakesが問題なく動く
    • 複数のPython環境を管理できる
  • canopy
    • WindowsGUIやpyflakesが問題なく動く
    • 無償版だとライブラリが少ない
  • msys2のpacman -S msys/python3とpip
    • LinuxにあるblasライブラリがWindowsに無いため辛い
    • pyflakesをEmacsから呼ぼうとすると、Windowsパスとmsysパスの違いのせいでうまく動かない
  • msys2のpacman -S mingw-w64-x86_64-python3とpip
    • openblasはpacmanで入れれる
    • やっぱりpyflakesがEmacsから呼べない
  • 公式Pythonバイナリとpip
    • Windows用バイナリなのに、scipyでblasライブラリで同様にこける

うまくいった環境

Anacondaのダウンロード
condaコマンドで欲しいライブラリをいれる
  • conda install ***
condaに無いものはpipで入れる
  • pip install ***
EmacsPython環境をつくる
msys2やEmacsのPATHの設定
  • Anacondaのパスを追加
    • [AnacondaPath]/Anaconda3と[AnacondaPath]/Scriptsと[AnacondaPath]/Library/binの3つ
    • condaのactivate/deactivateを使うのならば、[AnacondaPath]/envs/[envname]と[AnacondaPath]/envs/Scriptsと[AnacondaPath]/envs/[envname]/Library/binを使えば良い
    • path書き換えるコマンド作ってもよい

未解決の問題

  • matlibplotを使ったPythonコードをquickrunすると、一定時間後に「QObject::killTimers: timers cannot be stopped from another thread」を吐いてmatlibplotで表示したGUIが落ちる
  • 【追記】quickrunはタイムアウト時間を設定してあるせい。「quickrun-timeout-seconds」を負数にすればタイムアウト設定をOFFにできる。

Raspberry Pi 2でのWekanの動かし方

まとめ

  • Raspberry PiでWekanは動くらしい
  • 個人的にはWekanをRaspberry Piで動かせなかった
    • Wekan(prebuild)は起動途中でnodeパッケージがELFエラーする
    • MeteorでWekanをbuildしようとすると、パッケージcfs:gridfsのArmv7向けがなく失敗する

参考元

概要

Node.jsの準備
→Meteorのインストール
→Wekanのビルド
→Wekanのインストール

  • apt-getしておくツール
    • git-core mongodb mongodb-server make g++ gcc build-essential libssl-dev curl

Node.jsの準備

gitレポジトリからnode.jsを持ってくる。
Wekanの都合から、node.jsはv0.10.40をいれないといけない。
nvm(Node Version Manager)とnpm(node package manager)を使うのがメジャーなようなので、採用する。
なお、node.jsのインストールは時間がかかる。
また、source ~/.nvm/nvm.shを.profileに記述する。

$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ ~/.nvm/nvm.sh
$ nvm install v0.10.40
$ npm update -g npm

Meteorのインストール

MeteorはWekanのビルドに必要なだけなので、$HOMEへ置く。
管理者権限は必要ない。
そこそこ時間がかかる。

$ cd $HOME
$ git clone --depth 1 https://github.com/4commerce-technologies-AG/meteor.git
$ $HOME/meteor/meteor --version

途中でcurlの認証書エラーがする場合は、必要に応じて証明書をアップデートする。
ただし、ラズパイの証明書のアップデート方法を調べるのがめんどかったので、今回は-kオプションを使いエラーを無視した。

--- ./git/meteor/meteor 2016-04-07 14:41:11.560265384 +0900
+++ ./meteor/meteor     2016-04-07 22:41:14.946819041 +0900
@@ -1,6 +1,8 @@
 #!/usr/bin/env bash

 BUNDLE_VERSION=0.5.16
+CURLFLAGS='-k'

 # OS Check. Put here because here is where we download the precompiled
 # bundles that are arch specific.
@@ -100,7 +102,7 @@

     # test if we can download the dev_bundle tarball
     function __check_tarball_download() {
-      CHECK_TARBALL=$(curl --head --location --silent "$DEV_BUNDLE_URL_ROOT$TARBALL" --output /dev/null --write-out '%{http_code}')
+      CHECK_TARBALL=$(curl $CURLFLAGS --head --location --silent "$DEV_BUNDLE_URL_ROOT$TARBALL" --output /dev/null --write-out '%{http_code}')
       # Write down a message instead doing a false download
       if [ "$CHECK_TARBALL" != "200" ] ; then
         if [ -n "$METEOR_UNIVERSAL_FLAG" ] ; then
@@ -127,11 +129,11 @@
     elif [ -n "$SAVE_DEV_BUNDLE_TARBALL" ] ; then
         # URL duplicated in tools/server/target.sh.in
         __check_tarball_download
-        curl --location -# "$DEV_BUNDLE_URL_ROOT$TARBALL" >"$SCRIPT_DIR/$TARBALL"
+        curl $CURLFLAGS --location -# "$DEV_BUNDLE_URL_ROOT$TARBALL" >"$SCRIPT_DIR/$TARBALL"
         tar -xzf "$SCRIPT_DIR/$TARBALL" -C "$BUNDLE_TMPDIR"
     else
         __check_tarball_download
-        curl --location -# "$DEV_BUNDLE_URL_ROOT$TARBALL" | tar -xzf - -C "$BUNDLE_TMPDIR"
+        curl $CURLFLAGS --location -# "$DEV_BUNDLE_URL_ROOT$TARBALL" | tar -xzf - -C "$BUNDLE_TMPDIR"
     fi

     # In case that we have to use the universal system environment, make sure

(Additional)Meteorのインストールの確認

心配な人はMeteorのexampleを動かす。
時間はかかる。

$ cd $HOME
$ $HOME/meteor/meteor create --example todos
$ cd todos
$ $HOME/meteor/meteor
$ # この後に、http://[IP Address]:3000/ にアクセス

以下のようなエラーが起きた場合は、localesをen_GB.UTF-8からen_US.UTF-8に変更すると治る。
公式githubで議論されてる。

$ ~/meteor/meteor
[[[[[ ~/tmp/meteor-test/todos ]]]]]

=> Started proxy.
Unexpected mongo exit code 1. Restarting.
Unexpected mongo exit code 1. Restarting.
Unexpected mongo exit code 1. Restarting.
Can't start Mongo server.
MongoDB failed global initialization

Looks like MongoDB doesn't understand your locale settings. See
https://github.com/meteor/meteor/issues/4019 for more details.
$ sudo dpkg-reconfigure locales # en_US.UTF-8にする
$ ~/meteor/meteor
[[[[[ ~/tmp/meteor-test/todos ]]]]]

=> Started proxy.
=> Started MongoDB.
   Starting your app
$ # この後に、http://[IP Address]:3000/ にアクセス

Wekanのビルド

TODO、うまくいってない。

$ git clone https://github.com/wekan/wekan.git
$ cd wekan
$ git checkout v0.10.1

Wekanのインストール

公式提供のautoscriptを使う。
ただし、公式のレポジトリからzipを落とす部分を、自分でビルドしたWekanを使うように書き換えて実行する。
また、sudoではなくsudo suしてrootアカウントにならないとディレクトリ権限がおかしくなりエラーで落ちる。
気づかずにだいぶハマった。

$ git clone https://github.com/anselal/wekan/blob/master/autoinstall_wekan.sh
$ vi ./wekan/autoinstall_wekan.sh
$ sudo su
# ./wekan/autoinstall_wekan.sh
- wget https://github.com/wekan/wekan/releases/download/v0.10.1/wekan-0.10.1.tar.gz
+ # wget https://github.com/wekan/wekan/releases/download/v0.10.1/wekan-0.10.1.tar.gz

終わると、/etc/init.d/wekanと/usr/local/bin/get-ip-addressと/etc/network/if-up.d/show-ip-addressが作成される。
ポート番号などの設定は/etc/init.d/wekanの変数を書き換える。
get-ip-addressの中身は単純なbash script。
ちなみに、Debian testingを使った際は、ifconfigのフォーマットが合わないので改変する必要がある。

回路図CAD+プリント基板CADな感想

某人が雑にブログをさくさく書くのやってるの、よいので真似しよう。
軽い気持ちでネットに知識を保存して、世界をちょっとだけよくするのよい。

CR-5000

  • 図研
  • 多くの企業で採用されている実績のある回路・基板CAD
  • 日本語おk、なはず
  • 強い
    • けど高いのでまだ使ったことない

Eagle

  • CadSoft
  • 100x80mmや部品数・レイヤーに制限ありまでは無料
  • 英語
  • 有料になると急に5〜20万と本気を出してくる
    • 回路図・基板・自動配線の3つのうちたくさん買うほど高額
    • えげつない
  • 強い
    • 老舗なのか、他フリーCADはEagle形式をインポートできるのを強みに言う

Design Spark PCB

  • RS compornents関係
    • RSの部品Noをつけた部品リストを出せる機能がある
    • 国内のPCB試作メーカにすぐに見積もり・発注が出せる機能とかある
  • 完全無償で商用利用もおk
  • 英語
  • Eagleのデータをインポートできる
  • 移動とか基本が普通CAD系の操作感で使いやすい

KiCAD

  • OSSな回路・基板CAD
    • ライブラリはGithubで公開、プルリクも受け付けてる
  • 完全無償で商用利用もおk
  • 日本語化バイナリが存在する
  • Eagleのデータをインポートできる
  • 普通のCAD系とちょっと基本操作が違ったのが違和感あった

というわけでDesign Spark PCB使って回路の勉強してる。

ヌードルメーカーで家二郎

この記事はNoodleMaker Advent Calendar 2014 20日目の記事です。

各所で話している通り、


こんな目に会いました。

本気には本気で返す

というわけで家二郎を作ることになりました。
今回はフィリップスのヌードルメーカーで家二郎ができることを報告します。

機材・材料

  • 機材
    • フィリップスヌードルメーカー
    • 一口IHコンロ
    • 鍋4つ
      • スープ大鍋
      • 麺茹で大鍋(フライパンで代用)
      • 油加熱小鍋
      • カエシ鍋
    • レンチンできる大きめのタッパー(ヤサイ茹で用)
  • 材料(約5人分)
    • スープ(約鍋1杯、丼10杯分くらい?)
      • げんこつ(豚の骨)1本約300g
      • 玉ねぎ 1個
      • キャベツの芯 1個
      • ネギの青い部分 1個
      • にんにく 1欠片
      • 生姜 1欠片
    • カエシ
      • 醤油 300ml
      • みりん 80ml
      • 豚肩ロース 800g
      • キャベツ 半玉
      • もやし 3袋
      • にんにく 1欠片〜
      • 豚背脂 500g

スープ

下茹で

ハンマーなどで割ったげんごつを30分ほど煮ます。
自分はビニール袋に入れてアパートの塀にぶつけて割りました。

30分茹でたら洗って肉や血合いを取ります。

本茹で

野菜・チャーシュー・背油とげんこつを一緒にしてアクを取りながら約4〜8時間ほど煮ます。




野菜・チャーシュー・背脂は2時間ほどで取り出します
玉ねぎは醤油をかけて食べました。

8時間後

こんな感じに乳化した状態になります。

カエシ

材料を混ぜて加熱。
みりんのアルコールを飛ばして置いておきます。

チャーシュー(スープ・カエシと平行)

茹でる

前述、スープと一緒に2時間ほど煮ます

スープに漬ける

前述のカエシに食べる30分ほど前から漬けて置きます。
時々ひっくり返すこと。

切る

うまい

油(スープと平行)

下茹で

前述、スープと一緒に2時間ほど煮ます

本茹で

食べる前に小鍋に入れて包丁でザクザク細かく切ります。
その後、軽く沸騰するまで火にかけて、火から下ろします。
あとは余熱でいい感じにとろけます。

ヤサイ

キャベツは一口サイズほどに切ります。
もやしと一緒にタッパーに入れてレンジ500Wで約1分半チンします。

水に塩・重曹を溶かしておく。
小麦粉をヌードルメーカー(2.5mm各麺)にセットする。
8分でヌードルメーカーをスタートさせる。
水はじっくり少しずつ1分ほどかけて入れる。
麺は1人前ずつでカットする。

湯で時間は約4分〜5分です。

ニンニク

みじん切り

できあがり

カエシ1:スープ4:油1くらいで丼に入れる。
茹で上がった麺を入れる。
野菜・ニンニク・チャーシューを盛る。
アブラ増しの場合はさらにアブラを上からかける。
カラメの場合はさらにカエシを上からかける。



まとめ

  • フィリップスのヌードルメーカーで家二郎はできる
  • 一口コンロのIHでも頑張れば家二郎はできる
  • mzpギルティ

SML with マイコンボード

この記事はML Advent Calendar 2014 14日目の記事です。

最近は、お仕事でマイコンボードプログラミングを書いています。
現在はBeagle Bone Black(以下BBB)をいじっています。
ところでこのマイコンボードはArmでフルのLinuxを動かすことができます。
さらにこんなコメントが。

!!!!

もちろんBBBは各種GPIOやLEDをLinuxファイルシステムとして提供してくれています。
つまりファイルの読み書きさえできて、Arm対応の言語なら何でもマイコン操作ができるはずです。
そこで今回はMltonによるマイコンボードプログラミングを紹介します。

環境

  • Beagle Bone Black (Rev C)
    • Ubuntu 14.10 utopicをインストール済み
    • apt-getでMltonのインストール済み

Beagle Bone BlackのGPIOの操作方法

  • 以下のサイトを参考にしました
    • shellからの操作がとても参考になる。
    • ピン番号についての一覧エクセル/PDFも便利。

http://www.si-linux.co.jp/techinfo/index.php?BeagleBoneBlack

# echo 60 > /sys/class/gpio/export             # 60番GPIOを使用
                                               # 新しいディレクトリgpio60ができる
# echo out > /sys/class/gpio/gpio60/direction  # outputに指定
# echo 0 > /sys/class/gpio/gpio60/value        # HIGH出力
# echo 1 > /sys/class/gpio/gpio60/value        # LOW出力

SMLによるGPIOモジュールの例(Arduino風)

上記シェルコマンドの動作をそのまま落とし込むだけです。
100行以下の小さなお試しプログラムです。

(* DIGITAL_GPIO.sig *)
signature DIGITAL_GPIO =
sig
  type pin = int
  datatype mode = OUTPUT | INPUT (* | INPUT_PULLUP *)
  datatype value = HIGH | LOW
  val pinMode : pin * mode -> unit
  val digitalWrite : pin * value -> unit
  (* 省略 val digitalRead : pin -> value *)
end
(* DigitalGPIO.sml *)
structure DigitalGPIO : DIGITAL_GPIO =
struct
  type pin = int

  datatype mode = OUTPUT | INPUT

  datatype value = HIGH | LOW

  val path = "/sys/class/gpio"

  fun startPin pin =
      let
        val path = path ^ "/export"
        val outs = TextIO.openOut path
        val () = TextIO.output (outs, Int.toString pin)
        val () = TextIO.closeOut outs
      in
        ()
      end

  fun setMode (pin, mode) =
      let
        val path = path ^ "/gpio" ^ Int.toString pin ^ "/direction"
        val modeString = case mode of
                             OUTPUT => "out"
                           | INPUT => "in"

        val outs = TextIO.openOut path
        val () = TextIO.output (outs, modeString)
        val () = TextIO.closeOut outs
      in
        ()
      end handle IO.Io error => ()

  fun pinMode (pin, mode) =
      let
        val () = startPin pin
        val () = setMode (pin, mode)
      in
        ()
      end

  fun digitalWrite (pin, value) =
      let
        val path = path ^ "/gpio" ^ Int.toString pin ^ "/value"
        val v = case value of
                    HIGH => "1"
                  | LOW => "0"

        val outs = TextIO.openOut path
        val () = TextIO.output (outs, v)
        val () = TextIO.closeOut outs
      in
        ()
      end
end
(* Main.sml *)
structure Main
          : sig
            val main : unit -> unit
          end
=
struct
  fun init () = DigitalGPIO.pinMode (60, DigitalGPIO.OUTPUT)

  fun loop () =
      let
        val () = DigitalGPIO.digitalWrite (60, DigitalGPIO.HIGH)
        val () = OS.Process.sleep (Time.fromReal 0.5)
        val () = DigitalGPIO.digitalWrite (60, DigitalGPIO.LOW)
        val () = OS.Process.sleep (Time.fromReal 0.5)
      in
        loop ()
      end

  fun main () = (init (); loop ())
end

val () = Main.main ()

できたプログラムをBBB上で実行すると、P9-12番ピン - GND間に繋いだLEDが1秒周期でチカチカします。
やったね!

setMode関数でIo例外を握りつぶしています。
実行初回だけdirectionファイルがビジー状態のエラーがでるためです。
もしかするとexport設定後のdirectionファイルへのアクセスが早過ぎる?
この辺はまだ調査中です。

まとめ

列挙型と代数的データ型

今日はなごやかJava第1回 - connpassに行って来ました。
そこで@bleisさんによるJavaC#(とF#)の比較の話の中で列挙型(と代数的データ型)について話題に上がりました。
SML好きな自分が最近C++を書いてて同じように2つの違いについて思ったことがあったので、ここに書いておきます。

列挙型

  • (おそらく)有限数状態を表すために作られた
    • int等でもプログラマが管理すれば同様の機能は実現できる
    • 状態の意味を名前付けしたり、状態数の制限を付加できる
  • C/C++Javaなどで使える*1
  • ラベルのみを持つ
  • 使用例
// C++

// 定義
enum Janken {
  Gu,
  Choki,
  Pa
};

// 使用
int walkLength(Janken hand)
{
  switch(hand) {
    Gu:    return 3 // グリコ
    Choki: return 6 // チョコレート
    Pa:    return 6 // パイナップル
  }
}

代数的データ型

  • 数学の直和が理論の元になっている
    • 集合A,Bに対して2つの直和A+Bは A+B = { a_label(x) | x∈A } ∪ { b_label(x) | x∈B }
    • つまり、どちらの集合から来たかラベルが付いた和集合
  • HaskellOCamlやSMLやScalaで使える
  • 型推論が効く
    • 強力なパターンマッチが使える
  • 列挙型と違い、ラベルだけでなくデータも持てる
    • そもそも列挙ではなく、複数の型を直和した別な型をつくる概念
    • Cでいう共用体(union)にラベルが付いている、ほうが正しく表していると思う
  • 暗黙の型変換は存在しない
  • 使用例
(* SML *)

(* 定義 *)
datatype janken =
    Gu
  | Choki
  | Pa
  | LocalRule of string * int

(* 使用 *)
fun walkLength hand = (* 型推論結果: fn: janken -> int *)
  case hand of
      Gu    => 3
    | Choki => 6
    | Pa    => 6
    | LocalRule (name, n) => n (* "グリコノオマケ"、など *)

まとめ

  • 2つの生まれ元は違えど、使いたい目的はたいてい同じ「ケース分け」
    • しかし、代数的データ型のほうが強い
  • 個人的には代数的データ型がサクッと使いたいんです!!
    • C++で代数的データ型を探して絶望したのよ…
    • もちろんクラスを駆使すればC++/Javaで同様のことはできる*2
    • もっと多くの言語に流行れ、でも原理的な問題で実装難しそう

*1:Cでは実体はただのint、C++では型や値を指定できるものの暗黙の変換とかがあってやっかいこの上ない

*2:そんなにがんばりたくない