「Go言語でつくるインタプリタ」を読み終えた

概要

Go言語でつくるインタプリタを読み終えました。

Go言語でつくるインタプリタ

Go言語でつくるインタプリタ

写経しやすい本だったので、写経してみました。

github.com

コミットメッセージに該当ページのページ番号をできるだけ書いてあるので、参考にできるかもしれません。

これまでGo言語については簡単なプログラムを中心に勉強していましたが、あまり身についたという実感はできないままでいました。もう少し大きなプログラムを作ってみたいなと思ったときに本書に出会い、Go言語の勉強ついでに写経しながら書いてみました。

感想

テストプログラムがきっちり書かれていて、写経しやすい一冊。テストが失敗して本処理のTypoとか実装誤りとか勘違いとかを適宜見直すことができて素晴らしい感じです。

Go言語の文法については特に説明はないので、別の書籍などで勉強しておく必要があります。私は、「スターティグGo」を読んで勉強しました。

スターティングGo言語 (CodeZine BOOKS)

スターティングGo言語 (CodeZine BOOKS)

「スターティングGo」が対象としているGo言語のバージョンは若干古いのですが、今回写経するうえでは問題ありませんでした。

著者が読者に対して語りかける形で説明や実装が進むので、好き嫌いは分かれるかと思いますが私は好きでした。

インタプリタの実装についてもちょっと詳しくなりました。だからといってすぐさま「おれが考えた最強の言語。miyohide」ができるとは思いませんが。昔、「Rubyのしくみ」って本を読んだことがあるのですが、個人的には自分で言語が作れる分、「Go言語でつくるインタプリタ」のほうが読了後の達成感は強かったです。

Rubyのしくみ Ruby Under a Microscope

Rubyのしくみ Ruby Under a Microscope

すると、「Rubyで作る奇妙なプログラミング言語」はRuby大好きな人にはおすすめな一冊と思います。

また、「RubyでつくるRuby」はコンパクトで読みやすい一冊かと思います。

RubyでつくるRuby ゼロから学びなおすプログラミング言語入門(紙書籍+PDF版)www.lambdanote.com

2018年の振り返り

2019年になったけど、雑に2018年を振り返りたい。

骨折した

5月にランニング練習中、転倒して骨折した。はじめての手術も経験。いろいろな人に迷惑かけたけれども、色んな人の暖かさに触れた一年であった。

ラソン

骨折の影響がずっと響いて、横浜マラソン2018は28キロぐらいで足がつる。その後は歩いたり走ったり。めっちゃ情けなかった...。来シーズンにご期待ください。

f:id:miyohide:20181028131229j:plain

Yokohama.rb

治療のために1回Yokohama.rbをお休みしたら「運営できる人を増やそう」と @hamakn が呼びかけてくれて、色んな人が運営を手伝ってくれるようになった。おかげさまでまだ続けられています。次回は2019年1月19日(土)です。よろしくお願いします。

yokohamarb.doorkeeper.jp

Ruby Prize 2018 ファイナルノミネート

るびまのメンテを続けてきたことが評価されてRuby Prize 2018にファイナルノミネートされた。

f:id:miyohide:20181101234122j:plain

おかげさまで、RubyWorld Conferenceの場で「記事を書きますよ」というお話をいただき、次号に向けて作業中。2019年はもうちょっと発行ペースを上げたい。

Java(Spring Boot)

業務でJava(Spring Boot)を触ることが多くなって勉強し始める。アプリを実装するのはみんながやることなので、自分としてはテストをどうやって書くのかをいろいろと試してみたりした。表に出せる成果といえばWEB+DB PRESSの記事に載ってあったTodoアプリに対してテストを書いたりした(これも2019年だな)。

miyohide.hatenadiary.jp

普段Railsでアプリを書いているので、別のフレームワーク・言語でアプリを書くと色々と勉強になる。

Golang

これまでちょっとしか書いてなかったGo言語も、業務がきっかけでまじめに勉強するようになった。A Tour of Goをこなしたあと、『スターティングGo言語』を買って文法を学んだり、『みんなのGo言語』を読んだりして勘所を掴む感じ。

スターティングGo言語 (CodeZine BOOKS)

スターティングGo言語 (CodeZine BOOKS)

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

@tatsuosakurai さんと『Goならわかるシステムプログラミング』のオンライン読書会も進めている。

Goならわかるシステムプログラミング

Goならわかるシステムプログラミング

また、『Go言語でつくるインタプリタ』も写経をしながら読み進めている。

Go言語でつくるインタプリタ

Go言語でつくるインタプリタ

断捨離

年明けすぐに引っ越しすることになって荷物の整理を始めたらいつの間にか断捨離っぽくなった。2年間開いていない本とかはもう読まないだろうということで古本屋に売ったり、ダラダラ続けていたウェブサービスも整理して解約した。こういうの、定期的にやりたい。

GitHub ActionsでGo言語のテストを動かしてみた

はじめに

GitHub Actionsのβテストに選ばれたので、正月休みを利用して試してみました。何をさせようかちょっと考えたのですが、ちょうど『Go言語でつくるインタプリタ』を読みすすめているので、そのテストコードを実行するようにしてみました。

Go言語でつくるインタプリタ

Go言語でつくるインタプリタ

はじめてのGitHub Actions

ドキュメントが公開されているので、それをもとに実行してみます。

developer.github.com

今回はGoコマンドのバージョンを出力するようにしてみます。

.github/main.workflowに以下の内容を記してGitHubリポジトリにpushします。

workflow "Test" {
  on = "push"
  resolves = ["test"]
}

action "test" {
  uses = "docker://golang:latest"
  runs = "go version"
}

すると、GitHubリポジトリにあるActionsタブに以下のような画面が表示されます。

f:id:miyohide:20190101193353p:plain

「Log」をクリックすると以下のようなログが出力されます。

### STARTED test 07:11:08Z

Pulling image: gcr.io/github-actions-images/action-runner:latest
latest: Pulling from github-actions-images/action-runner
4fe2ade4980c: Already exists
86eb2eb12b87: Pulling fs layer
3c0e0e9cbe16: Pulling fs layer
0dff81d7fe33: Pulling fs layer
3c0e0e9cbe16: Verifying Checksum
3c0e0e9cbe16: Download complete
0dff81d7fe33: Verifying Checksum
0dff81d7fe33: Download complete
86eb2eb12b87: Verifying Checksum
86eb2eb12b87: Download complete
86eb2eb12b87: Pull complete
3c0e0e9cbe16: Pull complete
0dff81d7fe33: Pull complete
Digest: sha256:2b563779b8eb5c34114dce5f547ef0e8506a5701123819159a3ae1b319f4f80e
Status: Downloaded newer image for gcr.io/github-actions-images/action-runner:latest
Unable to find image 'golang:latest' locally
latest: Pulling from library/golang
Digest: sha256:7866a3428b229f9bb8aeaa437ed5cc3a4e5bf0b7c2ac534598fb6e40b6c6088d
Status: Downloaded newer image for golang:latest
go version go1.11.4 linux/amd64

### COMPLETED test 07:11:13Z (5.365s)

見にくいですが、

go version go1.11.4 linux/amd64

が表示され、Goコマンドのバージョンが出力されていることがわかります。

テストを実行する

さて、当初の目的であるテストの実行をしてみます。DevelopersIOの以下の記事を参考にDockerfileなどを作って実行してみました。

dev.classmethod.jp

最終的な設定は以下の通り。

まずは.github/main.workflowusesの部分を自分が作成したDockerfileなどをおいているパスに変更しています。

workflow "Test" {
  on = "push"
  resolves = ["test"]
}

action "test" {
  uses = "./.github/actions/golang"
}

.github/actions/golang/Dockerfileは以下の通り。

FROM golang:latest
 
COPY entrypoint.sh /entrypoint.sh
 
ENTRYPOINT ["/entrypoint.sh"]

最後に.github/actions/golang/entrypoint.shリポジトリ名をmiyohide-monkeyにしていたのにソースの中のpackage名はmonkeyにしていたので当初うまく動かずに悩みましたが、APP_DIRを直接指定することで動かすことができました。

#!/bin/bash
 
APP_DIR="/go/src/github.com/miyohide/monkey/"
 
mkdir -p ${APP_DIR} && cp -r ./ ${APP_DIR} && cd ${APP_DIR}
 
echo "#######################"
echo "# Running Test"
go test ./...

実行ログは以下の通り。

### STARTED test 13:13:05Z

Already have image (with digest): gcr.io/cloud-builders/docker
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855: Pulling from gct-12-whr4wtzjyryvx9olfja8cwy/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/8cf18bd4dc69e0f0e1f4b7a018b1b229495786905f46383be02cfeda9cc0c33b
cd8eada9c7bb: Already exists
c2677faec825: Already exists
fcce419a96b1: Already exists
045b51e26e75: Already exists
70a7003e9fe9: Already exists
751b6f060321: Already exists
462a907acb44: Already exists
6592a1601888: Pulling fs layer
6592a1601888: Verifying Checksum
6592a1601888: Download complete
6592a1601888: Pull complete
Digest: sha256:ab4db72476723a12a47a5c13c618ed8284b1444840b54e74a156ab01ab2da208
Status: Downloaded newer image for gcr.io/gct-12-whr4wtzjyryvx9olfja8cwy/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/8cf18bd4dc69e0f0e1f4b7a018b1b229495786905f46383be02cfeda9cc0c33b:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Already have image (with digest): gcr.io/cloud-builders/docker
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM golang:latest
latest: Pulling from library/golang
Digest: sha256:7866a3428b229f9bb8aeaa437ed5cc3a4e5bf0b7c2ac534598fb6e40b6c6088d
Status: Downloaded newer image for golang:latest
 ---> 343df9d12b7b
Step 2/3 : COPY entrypoint.sh /entrypoint.sh
 ---> e8e67d9de9a7
Step 3/3 : ENTRYPOINT ["/entrypoint.sh"]
 ---> Running in f3333c74336c
Removing intermediate container f3333c74336c
 ---> e38fd33cb0bf
Successfully built e38fd33cb0bf
Successfully tagged gcr.io/gct-12-whr4wtzjyryvx9olfja8cwy/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/8cf18bd4dc69e0f0e1f4b7a018b1b229495786905f46383be02cfeda9cc0c33b:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Pulling image: gcr.io/github-actions-images/action-runner:latest
latest: Pulling from github-actions-images/action-runner
4fe2ade4980c: Already exists
86eb2eb12b87: Pulling fs layer
3c0e0e9cbe16: Pulling fs layer
0dff81d7fe33: Pulling fs layer
86eb2eb12b87: Verifying Checksum
86eb2eb12b87: Download complete
0dff81d7fe33: Verifying Checksum
0dff81d7fe33: Download complete
3c0e0e9cbe16: Verifying Checksum
3c0e0e9cbe16: Download complete
86eb2eb12b87: Pull complete
3c0e0e9cbe16: Pull complete
0dff81d7fe33: Pull complete
Digest: sha256:2b563779b8eb5c34114dce5f547ef0e8506a5701123819159a3ae1b319f4f80e
Status: Downloaded newer image for gcr.io/github-actions-images/action-runner:latest
#######################
# Running Test
?       github.com/miyohide/monkey  [no test files]
ok      github.com/miyohide/monkey/ast  0.002s
ok      github.com/miyohide/monkey/evaluator    0.003s
ok      github.com/miyohide/monkey/lexer    0.002s
ok      github.com/miyohide/monkey/object   0.002s
ok      github.com/miyohide/monkey/parser   0.002s
?       github.com/miyohide/monkey/repl [no test files]
?       github.com/miyohide/monkey/token    [no test files]

### COMPLETED test 13:13:26Z (21.068s)

Running Test以下にGo言語のテストが実行されていることがわかります。

まとめ

取り急ぎ動かしてみたっていう感じでブログエントリを書いてみました。

ここまではTravisやCircleCIとやっていることは一緒なので、もっとGitHub Actionsならではのことをやってみたいです。

iPhoneの機種変更をした

2年に一回の恒例行事、iPhoneを機種変更しました。

環境は

というもの。

第一印象はでかいなぁって感じ。その後、ケースまでつけると分厚さも感じるようになりました。

こういう機種変更のログを残しておくとまた2年後に役に立つかなと思い、ログとして残してみることにしました。

事前準備

事前にやっておくのは、

  • Suica情報を削除
  • LINEの移行手続き
  • Apple Watchとのペアリング解除

ぐらい。各社案内を出しているので事前に目を通しておくとよいかと思います。

www.jreast.co.jp

official-blog.line.me

移行

あとは、iPhone XRに電源を入れてiPhone 7の近くに置くとすぐ「新しいiPhoneを設定」というメッセージが出てくるのであとは画面の指示に従うだけ。

support.apple.com

iTunesに繋げなくてもさくっと移行できたのでめっちゃ楽でした。大体1時間ぐらい。

ハマりポイント

最後にSIMをiPhone XRに入れて、IIJ mioのプロファイルを入れたらおしまい。IIJ mioのプロファイルを入れないと、無線LANがない場所ではデータ通信ができません。アンテナは普通に捕まえるので、めっちゃハマりポイント。実際ハマりました。

www.iijmio.jp

RubyWorld Conference 2018に行ってきた&Ruby Prize最終ノミネート者として表彰された

毎年恒例のRubyWorld Conference 2018に行ってきた。

今年も発表者募集に応募したのですが、採択されず。そのことについて若干いじられたりもして正直悔しい。来年はなにか発表できるように頑張りたい。

発表について

今年も多岐にわたる発表。Ruby = Railsっていう考えが多い中、本当に色々な所で使われているんだなあと。mrubyについては昨年までいろいろと取り組んでいたんだけれども、今年になって中断しているのでなんとかしたいなぁ。特にngx_mrubyについてはどこかで実戦投入したい。

ショートプレゼン

協賛企業の特典であるショートプレゼンも実施した。自社のRubyに対するこれまでの取り組みとこれからの取組みについて。発表後、NaClの井上社長から「迫力があってよかった」というお言葉をいただき、ちょっと嬉しかった。

Ruby Prize

Ruby Prizeの最終ノミネート者としてRubyWorld Conference 2018で表彰された。Rubyist Magazineに対する取り組みを評価していただいたとのことで、嬉しい。

f:id:miyohide:20181101234122j:plain

色んな人から「おめでとう」と声をかけていただき、やってきてよかったなと。RubyWorld Conferenceの場でも「記事書きますよ」と言っていただき、効果は抜群であった。

まだまだRubyist Magazineに対してはやりたいことがたくさんあるので、まだまだ続けていきたい。

Ruby Prize 2018にノミネートされた

るびま」ことRubyist Magazineの運営・編集・リリース管理などを数年やっていたら、Ruby Prize 2018にノミネートされました。ありがとうございます。

RubyPrize2018|候補者決定

発行ペースが落ちているのですが、これからも色々と記事を集めてるびまを続けていきたいと考えています。

Rails 5からbelongs_to associationを書くと親はデフォルト必須になった

はじめに

Rails 5(Rails 5.1?)からbelongs_to associationを書くと親が必須になっていました。これに今日はドハマリした...

具体的には、

class Post < ApplicationRecord
  belongs_to :article
end

というmodelがあったとして、rails consoleなどでPostインスタンスsaveしようとするとvalidationエラーが出ます。

> Post.new.save!
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
Traceback (most recent call last):
        1: from (irb):3
ActiveRecord::RecordInvalid (Validation failed: Article must exist)
>

経緯

Rails 5.0から5.1にアプリをあげてテストを流していたときに大量にテストが落ちたことがきっかけです。解決に至ったのは、次のブログ。

48n.jp

回避

上記のブログにあるように、belongs_tooptional: trueをつければOKです。ソース全体を書くと

class Post < ApplicationRecord
  belongs_to :article, optional: true
end

と言った感じになります。

実際にrails consoleで確かめてみます。

> Post.new.save!
   (0.1ms)  begin transaction
  Post Create (0.5ms)  INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2018-09-25 11:29:33.968321"], ["updated_at", "2018-09-25 11:29:33.968321"]]
   (1.3ms)  commit transaction
=> true
>

無事、生成できました。