fish移行した

以下雑な手順

  1. brew install fish
  2. cp ~/.zshrc ~/.config/fish/fish.config
  3. ひたすらfish化する
  4. このへんでfishにはいる
  5. fishermanをinstall
  6. 適当にfisher installする
  7. /etc/shells に追記
  8. chsh -s fish_path

ひたすらfish化でやったのででかめのトピックは以下。

export FOO=BAR -> set -x FOO BAR

anyenvがなんかダメだったのでがんばった。

  1. anyenv init - は実は後ろに引数としてshell名をとれる。なければ $SHELL を見る。そのためfish移行時にはfishと明記しておかないとエラーがでまくる。せっかくなのでzshrcにも書くことにした
  2. anyenv init - fish | source でいいはずなのだがなんかうまくいかなかったのでanyenv自体をupdate
  3. それでもダメだったので、anyenv init - fish の出力をなんとなく目で見る。ndenvのpath設定あたりで文字列内展開の書き方が間違ってたっぽい。いろいろめんどくさくなって anyenv uninstall ndenv しとく。dockerもあるし、ローカルのnodeのバージョンがちゃんと管理できなくて困ることはあるまい……

プロンプト変えた。fishなのでさかな。right_promptは最初gitブランチを設定してたんだけど、右端まで空白入るのがウザくて切った。手癖で git s(= git status) 打つようになってるから見えなくても特に問題ない

pecoは下に入力欄がくるようにした。そっちのほうが目線移動が少ない、というのを誰かの設定でみた。確かに。

hubのaliasは別にいらないかなって思って切ったままにしている。hub browseくらいしか使ってないしhub browseって打つようにしている。

移行した感想としては、特に変わらなかった。ターミナルでその場でシェルスクリプティングをすることがあまりなく、あってもfor文程度なので特に利点がない。逆にREADMEとかにあるスクリプトをコピペで動かすことができないのでいまのところ不満度のほうが高い。あっさりまた乗り換えるかもしれない。次にやるとしてもzshではなくbashにしようと思っている

懺悔

えー、最近の振り返りで使ってたツールですが集計ミスが発覚しました。

各レコードに対してminutesっていうカラムがあるんでそれで集計してたんですけど、minutesってのが実は「経過分数」じゃなくて「時刻表示の分」だったんですよね。

60 seconds -> 1 minute
3660seconds -> 1hour 1minute ( not 61 minutes )

2月末に発覚したデータロストとかじゃないからまだよかった……(よくはない)
1月の振り返りの時点で「コーディング時間おもったより少ないですね。もっと頑張らなきゃなあ」みたいな感想もってるのが笑える。ちゃんと気づけよw
3000分で少ないなって思ってましたが8000分になりました。はい。
2月は12000分弱なので実際1月は少ないみたいです。データ何日分かロストしてるけど

データの整合性については、えー、恥ずかしながらSQLで全件抜いたあとにgoogle spreadsheetに頼りました。エクセルで育ったもんで……。
実際値を見ながら仮説をたててなんかするってときにSQLはちょっとやりにくくて集計データがのこるスプレッドシートのほうが断然楽ですね。

データロストの対応については、昨日の分のレコードが0件だったらslackで教えてくれるスクリプトを書いてます。

f:id:hkdnet:20170315010110p:plain

というわけで過去記事を書き直しておきました。

yet another pomodoro

つくりました

github.com

いつもどおり英語は適当です。

モチベーション

  • ポモドーロテクニックがやりたかった
  • tmuxのバーに表示したかった
    • ターミナルを全画面で使ってる事が多いのでmacのステータスバーに表示するのは微妙
    • tmuxのバーが一番いいかな?っていう感じで決まった
  • 終わったら通知が欲しかった
    • macユーザーなので右上にピコンと出る系のやつがよかった

対抗馬は?

  • hughbien/thyme: Console Pomodoro timer
    • 使おうとしたんだけど依存関係がちゃんと定義されてなくて普通にやると動かなかった
    • たしかgem installしてレポジトリをとってきてbundle installしてその後bundle exec rakeしてテストを通すとようやく動くようになった
      • 最後の1ステップがマジで謎すぎる
  • ほかはしらない

作ったもの

1秒sleepして、ってやるとどんどんズレるよなー、どうやってんのかなーと悩んでた。悩みながら実装は見ないでthyme使ってた。
あるときgoでループ回しながら指定期間過ぎたら「過ぎたよ」っていうのをchannel経由で送ってくれるやつがいたらそれでよくね?と思いついたので作ってみた。
まだthymeの実装みてないのでどうやってるのかはしらない。

tmuxに出すのはthymeの設定ファイルから察したやり方で。$HOME配下にファイル出してtmuxのステータスバー側でcatで読んでる。

終わったら通知というのは設定ファイルにスクリプトのテキスト書いてそれをexecする感じにした。これもthymeの設定ファイルを参考にしている。スクリプトの中身はterminal-notifierというのを使っている。
julienXX/terminal-notifier: Send User Notifications on Mac OS X 10.8 from the command-line.

直したいところ

  • -dとかでdaemon化したい
    • goでdaemon化するのちょっとめんどくさそうで止まってる
      • 適当にやる分にはできそうだけどどういう問題があるのかよく把握してない
    • 実運用的には gomodoro & でバックグラウンドに飛ばしてる
  • SIGNAL対応
    • SIGINTくらいしか対応してない
    • まあ実用上困らんか……
  • tmux用のファイルは開きっぱなしのほうが効率がいい気がする?
  • 日別のpomodoroカウントとりたい気がする

実は作ったのは結構前で3commitしかないけど1commit目でmain.goは全部できてます。

2017年2月振り返り

記録

2017年2月 コーディング時間: 3378分 言語比率 1〜5位

Ruby 859
YAML    625
ERB 291
Docker  163
JavaScript  143
訂正版
total: 4517 minutes
Rank    Lang    Minutes
1   Ruby    1090
2   YAML    747
3   ERB 291
4   JavaScript  277
5   C++ 208

2017-03-13追記: 2/11と2/16のデータがないけど仕方ないのでこれで確定版

再訂正版
total: 11230 minutes
Rank    Name    Minutes
1   Ruby    4350
2   YAML    1418
3   JavaScript  702
4   Markdown    680
5   C++ 571

2017-03-15追記: 普通に計算ミスってました。 -> 懺悔 - Smoky God Express

ただしデータの信憑性があやうい

雑感

記録から

時間すくねーなって思ったんだけどこれはまた後で。

Rubyは主にCLIツール作ってた時間かな。いろいろ作った。使うかあやしいけど。

  • hakoのyamlを生成するやつ(諸事情あって2回つくった)
  • erbを自分たちのawsリソースの情報を埋め込みやすくしたラッパー
  • CircleCi内でやりたい処理を詰め込んだ便利gem

あとrubotyのプラグインとlambda(nodejs4.3)も書いてた。公開できないけど。流れとしてはこんな感じ
githubの通知 → lambda → ruboty → AWS CloudFormation

PRに対してChange SetのURL貼ったりマージしたらexecuteしたりexecuteしたらステータスが完了になるまでまって教えてくれたりって感じ。

Dockerfileは、うーん、なんでこんなに長いんだろう。そんなに書いてないと思うが。謎。herokuのdocker対応番作ろうとして挫折した記憶はある。

JavaScriptはwakatimeのviewerの構成を変えたからかなー。HTML直書きのVueだったのをcomponent分割してwebpackするようにした。
Go側はほぼいじってない。

wakatimeのviewerについて

viewerのバグ直した。これは結構大事なバグで、なにかっていうと0分だとそもそも折れ線グラフに点が打たれないからスキップされちゃうってバグ。初歩的すぎる……。もしかしてバカなんだろうか。真面目にデータみてないからわかってなかったけど……。
そして0分をいれて折れ線グラフを見ると1月にやる気ないどころかマジでなにもしてない1週間があってちゃんと値とれてるのか不安になってきた。っていうか2月のこの日おれ絶対コード書いてるんだけどってのが抜けてるのでたぶん取れてない。

2017-03-13追記: このあとすぐにサーバにログインしてその時点からでもとれるデータはとった

エラー通知なんもいれてないけどさすがにいれてretryさせる形がいいのかなー。エラー通知はslackに投げときゃいいかな

2017-03-13追記: エラー検知してリトライはめんどかったので昨日の分がとれてなかったらslackに投げるようにした

これからの振り返り

施策を打てるような分析をやりたいなーと思ってる

  • 曜日単位での集計
  • タブの分け方の変更
    • 年次、月次、週次の種別をかんたんにかえたい
  • 書いてる時間の集計
    • 集中してる時間とかわかるかも?

最近のコーディングネタ

Ruby

  • テスタビリティのために引数をとりたい
  • 普通にプロパティアクセスするような気楽さでアクセスしたい

この2つの気持ちがあわさってこういうことをよくしている

class Foo
  attr_reader :baz, :qux

  def bar
    @bar ||= build_bar(baz, qux)
  end

  def build_bar(baz, qux)
    # baz, quxは結局 @baz, @quxなのだがとっておくとテストがしやすい
    # なんか適当な処理
  end
end

# test

subject = Foo.new
assert(foo.build_bar(1, 2) == 3) # こういう感じで内部状態@baz, @quxを意識しなくてよくなる

#build_bar がもう少し重い処理ならFactoryを使うべきだとは思うけど全部につくるのはめんどくさくてこういう妥協をしている

JavaScript

webpack

webpack入門した。自分で調べながらかいたらこの程度で済んでいる。

https://github.com/hkdnet/wakatime-viewer/blob/master/webpack.config.js

  • cssはもともと書いてないからsassとかの設定がない
  • 画像サーブもしてないからそのへんもない
  • htmlサーブはやるけどまだ書いてない

このへんが短くなってる理由だろうか。どんどん育てていきたい

underscore

標準JavaScriptのArrayで微妙にたりなくて使ってるがunderscoreに渡す関数内で普通にArray.prototype.reduceとか呼んでてどうなんだろうという感じがある。

fetch

fetch APIをつかってHTTPリクエストを送ろうとしている。自分のAPIエンドポイントのためにClientクラスも作っている。

そうするとテストのためにはfetchをDIで使えるようにしておくとよい、気がする。

class Client {
  constructor(opts) {
    this.fetch = opts.fetch || fetch;
  }
  getFoo() {
    return this.fetch('/foo');
  }
}

一方でfetchは呼び出しコンテキスト(っていう言い方であってますか?Rubyでいうレシーバみたいな)がwindowであることを期待しているので、結局bindして渡す必要がある。

const client = new Cleint(fetch.bind(window));

いやー、微妙にダサい。どうしたもんか。

C++

先日書いたけど競プロっぽいのにC++使ってる。

そして関数内で int[n] を確保したらセグフォって「は???」という気持ちだったのだけどそういうこともあるらしかった。
そのあとぼでさんにunique_ptrとか使うといいんですよーと聞いたのでつかってみている

ツイートのリンク先を見ればわかるが、モダンさを感じて結構よさげ。

一方で困っていることもある。
いままで適当に配列つくって渡してーとやっていたがスタック領域以外のところにメモリを確保するようになったのでそのメモリを使うオブジェクトの生存区間とかを意識することになった。
というか意識しなきゃいけないなってことに気づいて結局グローバルにint配列確保するようにしてごまかしている。せっかく教えてもらってるのにすみません……。

相対的鉈

久々に競プロをやったら「あーこれとりあえずこうすれば動くけどたぶんでかいケースで落ちそうだなー」と思う問題に多数当たってめちゃくちゃ悔しい思いをしたのでまたアルゴリズム系の勉強をしようと思った。

家にあるアルゴリズム系の本はAOJ*1の本だけ。ちゃんと(?)購入当時に挫折済み。
なのでAOJ本をやり直すことにしたのが3日前くらい。

当時はたしか水たまりを計算する問題が解けなくて挫折したのだけど*2今解いてみたらあっさり終わって「いつの間にこんなに……」という気持ちになった。解説の内容をうろ覚えながら頭にいれてたのでソレが残ってただけだと思うけど。特に地力があがったわけでもないだろう。いや上がってないわけではないと思うけど別に競プロっぽいことやってないしな……。

普段はRuby使いだしRubyで書くかと思ってたのだけど、どうも便利メソッドが揃いすぎてて卑怯な気がしてきた。卑怯というか学習目的なら不適切というか。なのでC#でEnumerableとか封印して書くか、と思ったらAOJのランタイムがmonoでめんどいことになるのもなーと思ってうじうじ。そこでC++書けばいいじゃんって気持ちになってきたので最近書いてる。

「Goがなんとなく好き。Rubyは魔法で切れたか切れてないかよくわかんないけどスパスパパシパシ切れる感じでそれはそれでステキなんだけど、Goは鉈でオラァっていって切り回していく感じがあって好き。書いた分だけ動くっていうプログラミングの原点に立ち戻れる気がする」みたいなことを前にいった記憶があるのだけど、C++を前にするとGoは日本刀くらいの切れ味がありますね。ほんものの鉈の無骨さを目の当たりにしている。
たぶん僕の書いてるC++がマクロもtemplateもautoも使ってないのでだいぶ無骨だっていうのはあるのですが。というかたぶんほぼCで書いてる気がする。便利にC++書けたら嬉しいよなって気持ちもあるけどたぶんそこへの道のりがかなり長そうなので尻込みしちゃう。あくまでも競プロ用、みたいなね。適当なバッチかいてたときにpowershellの文法があやしいのと同じ。複雑なのはC#書くけど書き捨てはpowershellで。仕事でならRubyだけど勉強なら(無骨な)C++で。

元鉈現日本刀のGoは書いた分だけ動くといってもfor rangeとか配列とSliceとかが言語機能として備わっててやっぱモダンなんだよなーという感じ。C++を書いてGoへの想いを強くしている。
AOJでは選べないけどyukicoderはGoとかRustが選べた気がするので、yukicoderでこの問題を問いていけばアルゴリズムの勉強になるよという記事(あるいは本)の登場が待たれますね。

*1:サイト 具体的にはALDSコース

*2:見直したら超序盤で笑う。もうちょい頑張れ

mrubyだと32個以上の必須引数をとれない

www.amazon.co.jp

別に普段mruby使ってるわけでもないんですが『言語のしくみ』を読んでたら気になったので検証。

本の記載

タイプ3 Ax(25ビット) op(7ビット)

命令タイプ3はオペランド雨を全部1つにして25ビットのオペランド(Ax)として取り扱います。タイプ3の命令は、OP_ENTERの一つだけです。
(中略)
OP_ENTERはAxに指定されたビットパターンを見て、メソッドの引数チェックをします。OP_ENTERは25ビットのうち23ビットを5/5/1/5/5/1/1に分割して引数指定と解釈します。各ビットの意味を表2に示します。

ビット | 内容  
 5  | 必須引数の数
(以下略)
表2 OP_ENTERの引数指定 より一部抜粋

全体は1-3 バーチャルマシン、mrubyの命令を見てみる より。

思ったこと

必須引数の数が5ビットで管理されてるってことは 25 = 32 で 0〜31 までしかないはず。
32個の引数をとったら困るんじゃね?

検証

環境はこんな感じ。

$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
$ bin/mruby --version
mruby 1.2.0 (2015-11-17)

さて、引数32個も書くの嫌なのでさくっと生成します*1

n = 32
args = (1..n).map { |e| "a#{e}" }
str = <<-EOS
def foo(#{args.join(', ')})
  puts true
end
foo(*Array.new(#{n}))
EOS

File.write('main.rb', str)

じゃあ検証してみましょう。rubyとmruby両方で実行します。

$ ruby generate.rb
$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32)
  puts true
end
foo(*Array.new(32))
$ ruby main.rb
true
$ bin/mruby main.rb
trace:
        [1] main.rb:1:in Object.foo
        [0] main.rb:4
ArgumentError: 'foo': wrong number of arguments (32 for 0)

たしかに引数チェックは5ビットで行われてるみたい。 32 for 0 だから0個の引数を期待してることがわかります。

31個だと両方共trueを出力します。 33個だと wrong number of arguments(33 for 1) になってることも確認。

じゃあ0個を期待してるらしいので実際0個にしたらどうなるの?というのが以下。

$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32)
  p a1 # 中身みたかったので変更
end
foo # 引数ゼロ個
$ ruby main.rb
main.rb:1:in `foo': wrong number of arguments (given 0, expected 32) (ArgumentError)
        from main.rb:4:in `<main>'
$ bin/mruby main.rb
nil

当然rubyでは引数の数が違ってエラー。mrubyだと通りました。やったね
ただし引数は全部nilなので特に意味はありません。

じゃあ引数の最大値は31個なのかというと違います。
表2を全部写すのがめんどかったので書いていませんが、オプション引数の数とかキーワード引数の数も管理されています。
キーワード引数はmruby 1.2.0では未対応なので使えません*2。しかしオプション引数ならば5ビットまで使えるのでもう少し頑張れそうです。

n = 31 # これで31 * 2 の62個まで
args = (1..n).map { |e| "a#{e}" }
args += (1..n).map { |e| "b#{e} = #{e}" }
str = <<-EOS
def foo(#{args.join(', ')})
  puts true
end
foo(*Array.new(#{n}))
EOS

File.write('main.rb', str)

これで実行するとちゃんと通るのでたぶん62個ですかね。

$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, b1 = 1, b2 = 2, b3 = 3, b4 = 4, b5 = 5, b6 = 6, b7 = 7, b8 = 8, b9 = 9, b10 = 10, b11 = 11, b12 = 12, b13 = 13, b14 = 14, b15 = 15, b16 = 16, b17 = 17, b18 = 18, b19 = 19, b20 = 20, b21 = 21, b22 = 22, b23 = 23, b24 = 24, b25 = 25, b26 = 26, b27 = 27, b28 = 28, b29 = 29, b30 = 30, b31 = 31)
  puts true
end
foo(*Array.new(31))
$ ruby main.rb
true
$ bin/mruby main.rb
true

ビット的には必須引数の数とオプション引数の数が隣あってるからオーバーフローしたりしないかなって思ったんですがしなかったです。まあそりゃそうだ

# generate.rbは上記のをn = 32に変更
$ bin/mruby main.rb
trace:
        [1] main.rb:1:in Object.foo
        [0] main.rb:4
ArgumentError: 'foo': wrong number of arguments (32 for 0)

rubyだと引数の最大値いくつなんだろ?というのも気になりますが、n = 2_000_000_000_000 でも大丈夫だったのでまあいいかと思って最大値は見てません ( ˘ω˘)

*1:時間的には変わんないというか遅い気もするけど気持ちの問題ですよ

*2:たぶん。表2中に未対応とあり、mirbでやってもSyntax Errorになったので