while (token = lexer.read) != EOFをEnumeratorをつかってどうにかしたい

あたらしく研究室に入って(2度目)スクリプト言語の作り方って本が課題なのでやっていまして、そのときlexer作るんですが

while (token = lexer.read) != EOF
  ...
end

的な書き方してて嫌な気持ちになったので他にまともな書き方がないか調べました.

どうしたいか

  • while とかの中で代入はすきじゃないのでしたくない
  • eachみたいにつかえる
  • けど,任意の位置でreadできるようにしたい
  • しかしメモリ使用量を抑えたいので一気に配列に突っ込むとかはしたくない

つまり下みたいにはしたくない

# ファイルひらいて一気に配列に突っ込む
file = open(file_name).map { |f| f.strip }
file.each do |f|
  ...
end

どうしたか

Enumerator classを使いました.

例として以下の様なこと Enumeratorを使ってやってみました.

ファイルから1行ずつ読んでくる->読んできた1行になにかする(行番号をつける). javaLineNumberReaderみたいなやつ

class LineNumberReader
  def initialize(filename)
    @filename = filename
  end

  # nextがなかったらStopIterationをraiseする
  def read_line
    file.next
  end

  def peek_line
    file.peek
  end

  def has_next_line?
    !!file.peek
  rescue StopIteration
    false
  end

  # loopはStopIterationをrescueする
  def each
    loop { yield(read_line) }
  end

  private

  # each_line, with_indexは enumeratorを返すのでnextとかで逐次に取ってくるはず
  def file
    @file ||= open(@filename).each_line.with_index
  end
end

LineNumberReader#fileEnumeratorを返すようにしているので[メモリ使用量を抑えたいので一気に配列に突っ込むとかはしたくない]は解決出来てるはず

またLineNumberReader#read_lineを外から呼ぶようにすることで[任意の位置でreadできるようにしたい]も解決できる

reader = LineNumberReader.new('file.rb')
p reader3.read_line
...
p reader3.read_line if reader3.has_next_line?

またLineNumberReader#eachを作ってることで[eachみたいにつかえる]も解決

reader = LineNumberReader.new('file.rb')
reader.each |f|
  ...
end

while使いたいときはloopを使うと(実際eachで解消されてるけど)[while とかの中で代入はすきじゃないのでしたくない]も解決

reader = LineNumberReader.new('file.rb')
loop
  p reader.read_line
end

まとめ

ただのiteratorっぽいなにかだし,こんなことしてないで早く課題終わらせたほうが良さそう もっと賢い方法があればだれか教えてくれ!!

2週間でできる! スクリプト言語の作り方 (Software Design plus)

2週間でできる! スクリプト言語の作り方 (Software Design plus)

ansibleっぽいitamaeっぽいプロビジョニングツールminarai作った

github.com

作りました. ansibleとitamaeの名前を出しましたがお手本にしたのは @r7kamuraさんが作ったr7kamura/serverkit · GitHub というgemです.

動機

これが欲しかったわけではないんですがgem作ったことなかったし作りたいものもなかったのでなんか真似しようとおもって色々探してたらserverkitが出てきてちょうどよかったので自分でも書いてみました.

使い方

一番シンプルな使い方はrecipe.ymlを以下の内容で作って

- name: clone codic-clojure
  type: git
  repository: https://github.com/ganmacs/codic-clojure.git
  destination: codic-clojure

- name: clone dot_emacs
  type: git
  repository: https://github.com/ganmacs/emacs.d.git
  destination: .emacs.d

以下のコマンドを実行するだけです.また、既に目的のファイルが存在する場合などはスキップされるようになってます.

$ minarai recipe.yml
INFO : Minarai starting...
INFO : [SKIP] clone codic-clojure
INFO : [DONE] clone dot_emacs
INFO : Minarai finish

以上でgit cloneしてきてくれます.

変数を使った場合

recipeに変数を使うこともできます.

まずvars.ymlに以下を記述します.

remote_dotfile_repo: git@github.com:ganmacs/dotfiles.git
tmp_dir: /Users/ganmacs/tmp
dotfile_path: /Users/ganmacs/tmp/dotfile
vim_config_in_dotfile: /Users/ganmacs/tmp/dotfile/vim/vimrc
dot_vim_path: /Users/ganmacs/tmp/.vim

そしてrecipe.ymlに以下を記述します

- name: install vim
  type: homebrew
  item: vim

- name: create tmp directory
  type: directory
  destination: <%= tmp_dir %>

- name: clone dotfile
  type: git
  repository: <%= remote_dotfile_repo %>
  destination: <%= dotfile_path %>

- name: link dotfile to hgoe
  type: link
  source: <%= vim_config_in_dotfile %>
  destination: <%= dot_vim_path %>

そして実行すれば終わりです

$ minarai recipe_erb.yml.erb --variables=vars.yml
INFO : Minarai starting...
INFO : [SKIP] install vim
INFO : [DONE] create tmp directory
INFO : [DONE] clone dotfile
INFO : [DONE] link dotfile to hgoe
INFO : Minarai finish

機能

とにかくシンプルにしたくて他の構成管理ツールみたいに高機能なものを作るのはやめました. 基本的にローカルのMacの構成管理のためにしか使う気はないのでsshもできないです. コマンドも実行するrecipeを渡すだけです.(変数は使えますが)

実行できるタスク(アクション)は以下のとおりです

  • git - git cloneしてきます
  • file - fileのコピーをします
  • link - symlinkをはります
  • directory - directoryを作ります
  • homebrew - homebrewでパッケージをインストールします
  • homebrew_cask - homebrew_caskでappをインストールします
  • url_get - 指定したurlからcurlしてきます

感想

ansibleとitamaeはすごいなーって感想とserverkitのコードが読みやすくて最高って感じでした.

今後

rbenvとかdefaultとかcommandのactionも増やして構成管理に使っていきたい

関連

Serverkitつくった - ✘╹◡╹✘

itamae-kitchen/itamae · GitHub

ansible/ansible · GitHub

リクルートのインターンで負けてきました

まとめ

負けた!

概要

http://recruit-jinji.jp/winter-internship2015/

リクルートホールディングスのApplication Engineerコースに行ってきました。 ぼくはApplication Engineerコースの中の「インフラ/DB/バックエンドエンジニア」コースに申し込みました。 日程は2月1日から2月23日までで、コードを書くだけで15万もらえて人のお金で美味しいごはん食べられて交通費、宿泊費まで出る最高な感じでした。 やったこととか選考方法とかは他の人が書いているのでそちらを見てください。

リクルートインターンの良かったところ

僕が思ったインターンの良かったところを書きます

ずっとコード書いていられる

最初の3日間を企画を考える+座学に使います。 あとは、基本的にずっとコード書いていてよかったので開発に集中できてとてもいい環境でした。 聞きたいことがあればメンターがチームに1人ついているので聞くこともできてこれもまたいい環境だなと思いました。 また、週に1回メンターとの時間も設けられていたりもしました。

とにかくうちのチームのメンター氏はいい人で非常に勉強になることが多かったです。

AWS使い放題

AWS上にアプリをおいて開発するのでAWSが使い放題でした。 これが本当によくて自分はAWS使ったことなかったんですが試して壊してを繰り返せたりして勉強になりました。

使い放題だったこともあり、てきとうにインスタンスを立ち上げてitamae走らせてすぐインスタンス壊すみたいな無駄なことができます。最高です。

インターン中に企画がある

インターン中に「天下一自動化大会」っていうの企画が1日あってそれが結構楽しかったです。 この企画は自分の身の回りで自動化できそうなことを自動化して一番良さそうなやつを決めるみたいなあれです。

僕はchef使って環境構築自動化したのとemacsからコマンド一つでgithubのコミットひらけるプラグイン作りました。

emacs-github-open

美味しいご飯が食べれる

ご飯の参考画像です 天国

最高ですね

ほかにもみんなが書いてくれるはず

実際やったこと

バックエンド1人、フロントエンド2人のチームで「デートコース共有アプリ」をつくりました。 フロントエンドの2人が頑張ってくれて気づいたらミュゼっぽいおしゃれランディングページとか出来てました。(本番だとフォントととかもちゃんとしてる)

f:id:ganmacs:20150228233411p:plain

僕はすこしRailsかいてあとはインフラやってました。 サーバの構築にitamaeを使ったり、サーバのテストとしてserverspec使ったり、capistranoとcircle ci使ってデプロイ自動化したりして最高に楽しかったです。

その辺で得た知見はまた別エントリで残したいと思います。

来年あるかしらないけど行くと良さそうな人

  • あたりまえだけどエンジニアになりたい人
  • エンジニアの友達が周りにいない人
  • 2月暇で死にそうな人
  • 寿司が食べたい人

感想

選考とかあるけど実際ちょろいしみんなインターン行って寿司と15万ゲットした方がいいと思いました!!!

どう考えても完全にうちのチームが一番最高だった!!!!

他のインターン生が書いた参加ブログ

「Recruit Holdings Winter Internship 参加」って書けばいいと思ってる他のインターン生のブログです

surround.vimのEmacsバージョン作りました

surround.vimemacsバージョンみたいな感じです. emacsバージョンを探したんですがなかったので悔しくて作りました.

リポジトリ

ganmacs/emacs-surround · GitHub

設定

1.どうにかして入れます

caskの場合はCaskファイルに以下を追加

(depends-on "emacs-surround" :git "https://github.com/ganmacs/emacs-surround.git")

cloneしてくるのは

$ git clone https://github.com/ganmacs/emacs-surround.git

こんなかんじでロードパスが通ってるところにおいてください.

2.設定ファイル

init.elに以下を追加.

(require 'emacs-surround)
(global-set-key (kbd "C-q") 'emacs-surround)

使い方

変更

囲まれた文字列を変更したいときC-q '"と打つと

'He|llo World'

ダブルクォートをシングルクォートに変更します.

"Hello World"

削除

囲まれた文字列を削除したい場合はC-q d "と打ちます

"He|llo World"

そうすると以下のようになります

Hello World

挿入

文字列を囲みたいときはC-q i (C-q ( <return>とうつと

He|llo World

文字列で囲みます

(Hello) World

または,込みたい範囲をリージョンで囲むと以下のように囲むこともできます

(Hello World)

カスタマイズ

emacs-surround-alistに囲むペアのリストを渡すと任意の文字列で囲むことができます.

例えば以下のコードをinit.elに書くと{で囲むときにスペースを入れることができます.

(add-to-list 'emacs-surround-alist '("b" . ("{ " . " }")))

つまり,以下のrubyのブロック内にいる状態でC-q {bとすると

[1, 2, 3].each {p |1+i}

前後にスペースが入った{になります.

[1, 2, 3].each { p 1+i }

終わりに

問題があれば教えてください

参考

vim-surround

Vim のプラグイン紹介 〜 surround.vim でカッコつける 〜

emacs-dayone作った

なぜ

Macにはdayoneというmarkdownで日記をかけるおしゃれUIのアプリがある. 文章はemacsで書いて,読むときだけdayoneを使いたい. emacs-dayone

入れ方

  • Day One Toolsを入れます.
  • cask使って自分の環境に入れる
  • あとは適当にキー割り当ててつかう
  • (READMEにかいてある)

使い方

  • 範囲指定していない時は現在のバッファがすべてdayoneに保存されます
  • 範囲指定してる時は指定範囲のみdayoneに保存されます

emacs-git-grep作ってました

emacsにパッケージ管理をel-getからcaksに変更した際に自分で作ったemacs-git-grepにゴニョゴニョした時に思い出した

発端

デモ

github.com

f:id:ganmacs:20141031115516g:plain

実際

  • 初めて作ったのでたしかemacs-helm-agのコードとか参考に書いてあるコードをかなり真似て作った気がします
  • helm使ってるのに名前に入ってないのはどうなんだろうってずっと思ってる

感想

めっっっっっっっちゃ便利でした

参考

with-eval-after-loadとrequireとautoloadとadd-hookと

発端

違いは何だ!!

まとめ

違ったら教えてください

  • 起動してずっと使ってる -> require
  • 起動時には必要ないけどmodeごとでは使う -> autoload
  • ライブラリでのsetqとかの設定 -> add-hook
  • ライブラリでのdefine-keyとかの設定 -> with-eval-after-load

調べた感じ

  • autoloadrequireは使うタイミングは似てる?
  • autoladは必要なときに読んでくるので起動時に必要ではないものを設定するといい
  • requireはこれが呼ばれたタイミングでライブラリ読むので起動時必要なものだけにしたほうが良さそう

起動時にjs2-modeが呼び出される

(require 'js2-mode)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

初めてjsファイルを開いた時にjs2-modeが読み出される

(autoload 'js2-mode "js2-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

eval-after-loadwith-eval-after-loadadd-hookの違い

  • eval-after-loadwith-eval-after-loadの違いはwith-eval-after-loadはemacs24.4から新しく入ったマクロでprogn使わなくて良くなった
  • add-hookはバッファを呼び出すたびに呼ばれる
  • eval-after-loadは最初に設定しているライブラリがloadされるたびに呼ばれるが2回目以降は早いらしい

This macro arranges to evaluate body at the end of loading the file library, each time library is loaded. If library is already loaded, it evaluates body right away. 15.10 Hooks for Loading

  • setqとかはadd-hookがよくてdefine-keyとかはwith-eval-after-loadかな?

参考