富山の寒ブリ食べる会をやりました


こちらです
なぎせさんが持ってきた日本海の天然寒ブリを東京で食べる会 - connpass


約1年弱程前の

と言うつぶやきに端を発しています。


半年以上会場探しとかをサボっていて、いざ準備し始めた頃に現実世界がいろいろバタバタしてあまり時間が取れず、計画不足感があり参加して頂いた皆様には申し訳ありませんでした。

振り返り

  • 会場は角筈地域センター
    • 18人であの規模で調理しようと思うと調理時30人を交渉するクッキングルームでもやや手狭
    • ボウル、バット、各種鍋(圧力鍋含む)、各種食器、箸、すり鉢、レンジ、ジャー等大体のものは揃ってる
    • ラップなどの消耗品、調味料などは無し
      • ただし近くにコンビニとスーパーがあるのである程度現地調達できる
    • 食器調理器具の片付けは洗って拭いて元の場所に戻すまで
      • キッチンペーパーだと足りないか不便なので清潔なふきんを何枚か用意したほうが良さそう
    • 手を消毒する消毒用アルコールはあるけど手洗い用石鹸はない
  • 時間
    • 作業がシェアードナッシングに分担する形が決まってくるまでは混乱気味になり時間がかかる
    • 何やかんやで片付けには1時間くらいかかる
      • 会場は終了時間で鍵返却を含む完全撤収なので早め早めに動いたほうが良い
    • 今回夜間1と夜間2の2枠の時間(約3時間)で会場を予約したけど時間的には結構厳しかった
      • 作りながらある程度出来上がった時点で流れで「いただきます」になり、食いながら流れで片付けに移行し終始バタバタしてしまった
  • 料理
    • 僕は料理わからないので基本的になぎせさんに丸投げだった
    • 料理は割と残った(食べる時間があまりなかったというのもある)
  • ごみ処理
    • 夜間に生ごみをスポットで引き取ってくれる業者はこの宇宙には存在しないと思ったほうが良い
    • ゴミの量はぎゅうぎゅう詰めて45Lのゴミ袋1つとペットボトルビン類が数本と言う感じ
    • 今回はタクシーで直接ゴミを家まで持ち帰ったがもちろん乗車拒否される可能性もあるのでごみ処理に課題があったと言う感じ
      • ただしタクシーで持って帰れるなら経費はタクシー代だけなので業者に頼むよりは割安になる感(距離による)
  • 費用
    • 最終的にかかった経費は約10万
      • 一人あたり約6000円
      • 比率として大きいのはやはりなぎせさん費用
        • 食材費、とくにブリ
        • 遠征費用(宿代、往復のガソリン代等)
      • 詳しい内訳忘れたけど東京分の費用は2万前後ぐらいだったと思う
        • 主には会場費(4400円)とゴミ持って帰るためのタクシー代(約1万)
        • 現地調達の野菜類やジップロック、薬味、調味料、買い足しのキッチンペーパー等は全体からすると誤差の範囲内という感じ(数千円くらい)
    • 当初30人計算だった所実質18人だったのでもっと参加費上がるかと思ったけどそうでもなかった
      • ひとえになぎせさんの買い付けスキルの賜物
  • ぶり
    • ぶり1匹を18人で食べると一人あたり450g程
      • 1ポンドぶり
    • 味に関しては美味しかった以上の感想がない

こんなところですかね。
参加して頂いた皆さん、協力して頂いた皆さん、色々至らなくて申し訳なかったですがありがとうございました!

Go言語の開発環境構築したメモ

メモです。

Goをインスコするためにgvmをインスコする

Ubuntu使ってるんですがaptにあったのなんかすごい古いっぽかったのでソースインストールかなぁと思ってたら、どうやらgvmと言うrbenvみたいなやつがあるらしくそれ使ったほうがいいとのことです。

gvmをインスコするためにgvmを削除する

gvmって聞いて、あれ?Groovyでもそんなんなかったっけ?と思ったらやっぱりありました。なんかそれでgvmはsdkmanに名前変わったらしいです。
gvm(groovyの方)は起動して指示に従えばさくっとsdkmanに更新され、互換性のために.gvmディレクトリが.sdkmanディレクトリへのシンボリックリンクに変わったり、gvmコマンドがsdkコマンドへのaliasに変えられたりします。
が、この状態でgvm(golangの方)をインスコするといろいろ競合してつらい思いをすることになるっぽいので、sdkmanへの更新が終了したらaliasと.gvmリンクを削除しておきます。

gvm(golangの方)をインスコする

ググれば出てきます。

pkgsetを作る

golangはGOPATH決めたらライブラリ含め全てのソースはその配下に収める流儀で好きな場所にアプリディレクトリ作れないらしく、例えばIDEがworkspaceとかprojectsディレクトリとかを持ってる場合、クッこれが世界の選択か…と言う気分になるらしいです。

gvm使うとpkgsetとかいうのが作れて、任意のGOPATHが作れていろいろ切り替えられるらしいです。

mnrtks's blog | gvmを用いてRevelの開発環境を作成

に従って、

cd ~/IdeaProjects
mkdir hogehoge
cd hogehoge
gvm pkgset create --local
gvm pkgset use --local

とすると、アプリごとにローカルなpkgsetを作れていろいろ分離できるとのこと。

IntelliJ IDEAにgolangプラグイン入れる

IDE厨なので何をするにもIDEが無いと何も出来ないのでプラグイン入れます。

http://stormcat.hatenablog.com/entry/2015/04/13/123000

見れば大体大丈夫だと思います。
ただ、ローカルのpkgsetの様子まではIDEAさん分からないのでGOPATH分からんぞみたいなことを警告してきます。
その場合は、上記の例で言うとhogehogeディレクトリを指定すれば大丈夫っぽいです。

Hello World 実行する。

src/{yourdomain}/{name}/{app} でHello World書きます。
コード右クリックして実行選ぶとビルドされて実行され、golang完全にマスターできます。

バージョン管理

hogehoge/src/{yourdomain}/{name}/{app} でgit initするとのことです。

まとめ

なんか世界観がいろいろ違って大変でした(こなみかん)

僕(2015-10-09現在)

やってきた事

やったことある事

やっていきたい事

やって行きたくない事

  • 遅延証明受け取ってくれない会社で働くこと*2
  • スーツ着ること
  • 長時間労働、柔軟性のない勤務形態での労働
    • 子供作るかもフェーズになっているのでその辺りで憔悴したくない

興味あること

  • 自動化
  • 強い静的型付きの言語
  • FP

*1:本当にいろいろやってる

*2:埼京線は6割遅延するらしい

Clojure完全にマスターした話

TL;DR

  • LeiningenインスコしてIntelliJ IDEAにCursiveプラグイン入れるとLeiningenで生成したプロジェクト普通に読み込めるし括弧辺りの問題もだいぶ快適になるよ。
  • テスト環境何もしなくてもとりあえず整ってるっぽい
  • 完全にマスターとはHelloWorldやったり普通のFizzBuzzやったり出来た、を指す隠語

経緯

最初の一歩

Clojureのサイトからzip落としてきて展開、中に clojure-1.7.0.jar が入ってるので

java -cp clojure-1.7.0.jar clojure.main

するとREPLが起動していろいろ試せる

REPLがしょぼい

矢印キーが効かなかったり履歴機能が無かったりとにかく何を書くにもだるいなって思ってたらrlwrapというのがあるよと教えてもらいました。
よく分かんないですけどうまいことラップしていい感じにしてくれるとのこと。

rlwrap java -cp clojure-1.7.0.jar clojure.main

と言う感じでREPL起動すると履歴がついたり矢印キー使えたりしていい感じになりました。
rlwrapのインスコ方法は調べてください。だいたいパッケージマネージャで入ると思います。

Leiningenのインスコ

Javaで言う所のMavenScalaで言う所のactivator(sbt)みたいなものらしいです。ライブラリの依存関係やってくれたり、プロジェクトの雛形作ってくれたりコンパイルしたりしてくれる、Clojure界ではみんな当然使っている奴という感じっぽいです。
インスコは適当なディレクトリで

wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein

して、DLしたファイルにパス通せば終わりです

Cursiveインスコ

IntelliJ IDEAのClojureプラグインです。
勝手に括弧の対応取ってくれたり対応する括弧に色んな色付けてくれたり補完出してくれたりLeiningenと連携してくれたりしてClojureコーディングライフを強力にサポートしてくれるとのこと。

インスコCursive: Getting Started にある通り、自分のIntelliJ IDEAのバージョンに合ったplugin.xmlプラグインリポジトリとして登録し、いつもの様にプラグイン検索してインストーすればOKです。

で、こちらが様子です。

https://i.gyazo.com/467d36e14326c7179f1b2aeb6cf3193f.png

テスト

なんか最初からテストやる環境も整ってるらしいです。いろいろ言うより見たほうが早いのでこちらどうぞ。

動画みたいな感じでテストが書けます。Clojure REPL(ローカルサーバ)を起動しておいて、カーソル位置にあるコード(テスト)をREPLサーバに送ってちくいち実行しています。

REPLへのコードの送るのは、コードの適当な位置を右クリックしてREPL→Run 'hoge' in REPLを選ぶか、「Enter action or option name」のダイアログだして「run repl」とかで検索すると出てくる「Run test under caret in REPL」を実行するかすると出来ます。

関数書く→テスト書く→カーソル位置のテストをREPLに送る→失敗する→関数実装する→カーソル位置のテストをREPLに送る→イカ繰り返し

なんかかっこいいですね(括弧だけに)。

FizzBuzz

さっきの画像でチラ見えしてますが、出来たコードがこちらです。

(ns cljtest.core)

(defn peek' [x]
  (do (println x) x))

(defn gen [n]
  (range 1 (+ n 1)))

(defn fizzbuzz [x]
  (if (= (mod x 15) 0)
    "FizzBuzz"
    (if (= (mod x 3) 0)
      "Fizz"
      (if (= (mod x 5) 0)
        "Buzz"
        x))))

(defn doFizzBuzz [n]
  (map (comp peek' fizzbuzz) (gen n)))

との事です。

追記

コメント欄であやぴーさんに指摘もらいましたので修正(もらった指摘はコメント欄見てください)。

(ns cljtest.core)

(defn peek' [x]
  (do (println x) x))

(defn gen [n]
  (range 1 (inc n)))

(defn fizzbuzz [x]
  (if (zero? (mod x 15))
    "FizzBuzz"
    (if (zero? (mod x 3))
      "Fizz"
      (if (zero? (mod x 5))
        "Buzz"
        x))))

(defn do-fizzBuzz [n]
  (doseq [x (gen n)]
    (peek' (fizzbuzz x))))

doseq、よく分からないんですけどリスト内包表記みたいなのとなんかしらの関数を引数にとって、関数を繰り返し実行するマクロ?っぽいです。副作用のある関数使う時に使うやつとのこと。

更に追記
(ns cljtest.core)

(defn gen [n]
  (range 1 (inc n)))

(defn fizzbuzz [x]
  (if (zero? (mod x 15))
    "FizzBuzz"
    (if (zero? (mod x 3))
      "Fizz"
      (if (zero? (mod x 5))
        "Buzz"
        x))))

(defn do-fizzbuzz [n]
  (doseq [x (gen n)]
    (println (fizzbuzz x))))

peek'関数いらないとのことです

まとめ

Clojure完全にマスターした

FP in Scala勉強メモ(2)

高階関数、多相関数。

ここで言う多相は継承等による多相*1ではなく、型変数を利用した(総称)多相関数*2
この辺りは特に目新しいことは無かった。

データ型(List)

List[+A]として変位を共変にしてNil extends List[Nothing]とすることでval l: List[Int] = Nilみたいにできる。

演習問題

// Exercise 2.2
def isSorted[A](array: Array[A], p: (A, A) => Boolean): Boolean = {
  
  @annotation.tailrec
  def loop(n: Int): Boolean = {
    val next = n + 1
    if(array.length <= next){
      true
    }else if( p(array(n), array(next)) == false ){
      false
    }else{
      loop(n+1)
    }
  }
  
  loop(0)
}

// Exercise 2.3
def curry[A, B, C](f: (A, B) => C): A => (B => C) = a => b => f(a, b)

// Exercise 2.4
def uncurry[A, B, C](f: A => B => C): (A, B) => C = (a, b) => f(a)(b)

// Exercise 2.5
def compose[A, B, C](f: B => C, g: A => B): A => C = a => f(g(a))

FP in Scala勉強メモ

p.26 EXERCISE 2.1 n番目のフィボナッチ数を求める関数fib(n: Int): Intを末尾再帰で書く


脳内イメッジ

def fib(n: Int): Int = {
  def f(n: Int, a: Int, b: Int): Int = {
    if (n == 1) a
    else if(n == 2) b
    else f(n-1, b, a+b)
  }
  f(n, 0, 1)
}
  • 最初からnまで少しずつ道を伸ばしていくイメージ。
  • 次のフィボナッチ数を計算するために、fは現在の右端とそのひとつ左の2つの引数を受け取れるようにする
  • で、windowがスライドしていくイメージで一個ずつ右へずらしてく
  • a1とa2は決まっている(0と1)ので、nが2以上の時はfを初期呼び出しを除いてn-2回繰り返せば答えに到達する(右端がnになる)
  • nが1以下の時は必ず0

JenkinsとかでDockerコンテナを使ってテスト等を実行する時にdocker buildのキャッシュが効かない件

Dockerfileを使ってdockerイメージをビルドする時、COPYとかでリソースを追加する際、追加するリソースが変更されていなければキャッシュが使われてズババッとビルドされる。
が、リソースを変更していないにもかかわらず何故かキャッシュが使われず、結果として本来ならスキップできるはずの命令が実行されてしまいイメージのビルドにむっちゃ時間かかるみたいな現象があった。
Jenkinsとかでって書いたけど別にJenkinsに限らない。

原因

キャッシュ利用判断はリソース内容の変更を見ているんだけど、多分内容を見る前にファイルのmtimeを見ていて、それが変わっていれば内容を見ずに「変更されている」とみなしている。
gitはファイルのmtimeを保持しないので、ビルド対象リソースをcloneしてくると常に今作られたファイルみたいになってしまってキャッシュが使われない

対策

git-set-mtimeを使う(git-set-mtime を Docker のためにリリースした - 鳩舎)
これを使うとファイルのmtimeをgitのコミット日時に設定してくれるので幸せになれる。

まとめ

そもそもこのエントリに書いてある内容自体が Docker のキャッシュは mtime ベースっぽい - 鳩舎 以上の事を含んでないのであまり意味のないエントリだった。
git-set-mtimeのおかげで生きるのが楽しくなりました、id:rosylilly さんありがとうございます!