Memento memo.

Today I Learned.

Effective Ruby 第三章 コレクション まとめ

Effective Ruby 第二章まとめ その2 - Memento memo. の続きです。

第三章はコレクションです。コレクションをうまく扱えるかどうかはコードの可読性・保守性にダイレクトに効いてくる気がするので、言語ごとのクセを把握しておきたいです。

Effective Ruby

Effective Ruby

コレクションを書き換える前に引数として渡すコレクションのコピーを作っておく

  • Rubyのメソッド引数は値渡しではなく参照渡し。例外あり。(Fixnumは値渡しされる)
  • cloneとdupメソッドでオブジェクトのコピー作成ができる。たいていdupを使ったほうがいい。ただしshallow copyになってしまうので注意。
  • dupと比較して、cloneは"レシーバのフリーズ状態"と"特異クラス"を含めてコピーする
  • Marshalでシリアライズ、デシシアライズすればdeep copyになるが、メモリ効率、パフォーマンスの観点が悪いので注意。

破壊的メソッドを使って要素を直接書き換えるようなコードを避ければ大半は回避できそうな気がします。

nil、スカラオブジェクトを配列に変換するにはArrayメソッドを使う

  • Array(foo)とすると、fooがnilでもスカラオブジェクトでも配列に変換できる。
  • Array(foo)のfooにHashを渡してはいけない
foo = nil
puts Array(foo).map(&:to_s)
#=> no error
puts foo.map(&:to_s)
#=> error!!!

ある程度柔軟に引数渡せるようになるのがありがたいです。

要素が含まれているかどうかの処理を効率よく行うために集合を使うことを検討する

  • include?メソッドで要素が含まれてどうかの判定を繰り返し行うような場合は、include?のレシーバをSetクラスのインスタンスにすると高速になる。
  • SetはArrayと同じInterfaceを持つ。
  • require('set') して使う。

Array, HashだけじゃなくてSet, Rangeの存在も忘れないようにしましょう。

reduceを使ってコレクション畳み込む

  • select, mapメソッドよりreduceを使った方がメモリ効率が良い。
  • accumulatorの初期値は必ず与えること(コレクションが空の時の挙動を制御するため)

selectやmapだと効率が悪い、みたいなことが結構書いてあったのですが、内部実装どうなってるんでしょう。確かにreduceはあまり無駄がなさそうですが、向き不向きがある気がするのでいろんなパタンでベンチマーク取ってみようかと思います。

畳み込み自体の概念や実際の使い方については、HaskellやElixirみたいな関数型言語系の解説書を読むと理解が格段に深まるのでElixir本を読みましょう。

Hashのdefault値を利用することを検討する

  • Hashのデフォルト値・デフォルトブロックを使うことを検討する(以下参照)
h = {} # デフォルト値なし
i = Hash.new(0) # デフォルト値あり
j = Hash.new{|hash, key| hash[key] = []} # デフォルトブロック(危険な挙動があるので注意)
  • Hashのキー存在チェックは has_key? メソッドを使う。デフォルト値がnilとは限らないため。
  • デフォルト値より Hash#fetch の方が安全な場合がある
h = {}
h.fetch(:a)
#=> KeyError
h.fetch(:a, "default_value")
#=> "default_value"

Hash#fetch が一番柔軟でよく使う気がします。

Collection classからの継承よりも委譲を使う

  • 継承より委譲を使うこと。
  • 委譲するには require('forwardable') して Forwardable をextendする
  • def_delegatorsクラスメソッドで委譲ターゲットと委譲メソッドを定義する。

"継承より委譲"はよく聞きますね。OOPへの深い理解がないと適切に継承を使うのは難しいです。

Phoenix環境構築(Install・Server起動・ページの追加まで)

ElixirのWebフレームワーク Phoenixの入門 環境構築についてです。

公式Docの

に載っているものを簡略化 & 日本語化したものです。

Elixir

Elixirについての詳しい概要はこちらの記事が参考になります。

qiita.com

入門書はこちらの書籍が非常に面白かったです。というか他の日本語書籍は現時点で存在しないと思います。

プログラミングElixir

プログラミングElixir

Install

公式ページにいろいろ載ってますが、Mac + Homebrewの場合は

$ brew install elixir

でInstallできます。

上記コマンドでElixirをinstallすることで、 elixir コマンド、ElixirのREPL環境を実行する iex コマンド、ElixirのプロジェクトのCLIユーティリティの mix が使えるようになります。またErlangも一緒にinstallされます。

Phoenix

Install

Elixir & mix & Erlang がinstall済みであること

PhoenixのInstall

# package managerの hex を導入する
$ mix local.hex

# mixでPhoenixのinstall
mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez

その他必要なもの

Node.js (>= 5.0.0)

Homebrewやnvmで適当に

PostgreSQL

オプションでMySQLも可能。デフォルトはPostgreSQL

参考: Homebrewを使ったPostgreSQLのインストール(Mac OS El Capitan)

Projectの作成

create project

$ mix phoenix.new hello_phoenix
# Fetch and install dependencies? [Yn] 聞かれるのでとりあえず 'Y' を押下するとbrunchがinstallされる
$ cd hello_phoenix

ディレクトリ構造はこんな感じです。

❯ tree -L 2
.
├── README.md
├── brunch-config.js
├── config
│   ├── config.exs
│   ├── dev.exs
│   ├── prod.exs
│   ├── prod.secret.exs
│   └── test.exs
├── lib
│   ├── hello_phoenix
│   └── hello_phoenix.ex
├── mix.exs
├── package.json
├── priv
│   ├── gettext
│   └── repo
├── test
│   ├── channels
│   ├── controllers
│   ├── models
│   ├── support
│   ├── test_helper.exs
│   └── views
└── web
    ├── channels
    ├── controllers
    ├── gettext.ex
    ├── models
    ├── router.ex
    ├── static
    ├── templates
    ├── views
    └── web.ex

よく触るファイル系はだいたい web に入っています。

ectoのsetup

軽量ORMのectoはRailsでいうActiveRecord的なポジションです。

config/dev.exs の設定の設定をいじってpostgresに接続できるようにしてください。role/passwordが"postgres/postgres"でCREATEDB権限があればいけるはずです。

...
# Configure your database
config :hello_phoenix, HelloPhoenix.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  database: "hello_phoenix_dev",
  hostname: "localhost",
  pool_size: 10
$ mix ecto.create

上記コマンドでエラーがでなければ成功です。

Phoenix server 起動

$ mix phoenix.server

でserver起動できます。デフォルトでは http://localhost:4000 にアクセスすればページにアクセスすることができます。

f:id:shotat_jp:20160919221029p:plain

こんな感じの画面が出ます。

ページの追加

mix phoenix.gen.html といったmix task( Mix Tasks · Phoenix )で必要なファイル群の生成ができるみたいなのですが、今回はガイドに沿って確認しながら手でちまちま作っていきます。

routingの設定ファイル

routingの設定ファイルは web/router.ex です。 中身を見てみましょう。

defmodule HelloPhoenix.Router do
  use HelloPhoenix.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", HelloPhoenix do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
  end

  # Other scopes may use custom stacks.
  # scope "/api", HelloPhoenix do
  #   pipe_through :api
  # end
end

get "/", PageController, :index の行で ( web/controllers/page_controller.ex で定義された) HelloPhoenix.PageController moduleの index 関数を呼び出す、ということが容易に読み取れます。

routingの追加

http://localhost:4000/hello ページを作成します。

まず web/router.ex ファイルの20行目付近にroutingを定義します。

  scope "/", HelloPhoenix do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
    get "/hello", HelloController, :index
  end

controllerの作成

次に以下の内容の web/controllers/hello_controller.ex を作成します。

defmodule HelloPhoenix.HelloController do
  use HelloPhoenix.Web, :controller

  def index(conn, _params) do
    render conn, "index.html"
  end
end

conn はrequest情報が詰まったstructです。_paramsはrequest parametersですが、今回使わないので先頭に _ をつけています。

viewの作成

以下の内容の web/views/hello_view.ex を作成します。

defmodule HelloPhoenix.HelloView do
  use HelloPhoenix.Web, :view
end

xxx_controllerxxx_view の xxx部を一致させる必要があるので注意です。 viewの役割はtemplateのレンダリング & データの取得, 加工のヘルパー関数の提供です。

templateの作成

Elixirの標準テンプレートエンジンは Embedded Elixir(eex)です。

web/templates/hello/index.html.eex に以下の内容のファイルを作成します。

<div class="jumbotron">
  <h2>Hello World, from Phoenix!</h2>
</div>

helloページの表示

再びサーバを立ち上げ、 http://localhost:4000/hello にアクセスするとHelloページが表示されます。 サーバを再起動しなくとも変更は反映されます。

また、レイアウトファイルは web/templates/layout/app.html.eex に存在しています。

動的ページの追加

Pathパラメータを使ってページをレンダリングします。

routing設定

web/router.ex にroutingを追加しましょう。

  scope "/", HelloPhoenix do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
    get "/hello", HelloController, :index
    get "/hello/:messenger", HelloController, :show
  end

controller設定

/web/controllers/hello_controller.ex に showアクションを追加します。

  def show(conn, %{"messenger" => messenger}) do
    render conn, "show.html", messenger: messenger
  end

template設定

web/templates/hello/show.html.eex を作成し、以下の内容を記述します。

<div class="jumbotron">
  <h2>Hello World, from <%= @messenger %>!</h2>
</div>

これで http://localhost:4000/hello/phoenix にアクセスすると "Hello World, from phoenix!" と表示されるかと思います。

まとめ

PhoenixRailsライクなMVCで非常にわかりやすいですね。 今後は公式ガイド読みつついろいろ試してみるつもりです。

Programming Phoenix: Productive |> Reliable |> Fast

Programming Phoenix: Productive |> Reliable |> Fast

Effective Ruby 第二章 クラス、オブジェクト、モジュール まとめ その2

Effective Ruby 第二章まとめ その1 - Memento memo. の続きです。

Effective Ruby

Effective Ruby

構造化データにはHashではなくStructを使う

  • 新しいクラスを作るほどでもない構造化データを扱う場合はStructを使う
  • Struct::newを定数に代入し、定数をクラスのように扱う
  • ブロックでメソッドも定義できる
Person = Struct::new(:height, :weight, :age) do
  def bmi
    weight / (height * height)
  end
end

hoge = Person.new(1.58, 45, 20)

# getterでアクセスできる
puts hoge.height
# メソッド呼び出し
puts hoge.bmi

Hashで存在しないキーを指定するとnilになってしまってデバッグが辛くなるのでError吐いてくれるStructの方が良さ気です。

モジュールにコードをネストして名前空間を作る

  • 特にライブラリ等を作成する場合は、名前の衝突を避けるためにモジュール内に定義をネストして名前空間を切る。
  • 名前空間の構造はディレクトリに合わせる
  • トップレベル定数( Array とか)を使う場合に曖昧さが残る場合は"::"を使ってフル修飾する( ::Array

ライブラリ使う際は気を付けましょう。普通に開発する場合はあまり気にならないかも?

様々な等値の違いを理解する

  • "==", "===", "equal?", "eql?"の4種類の比較方法がある
  • "equal?"メソッドは厳格にオブジェクト(object_id)を比較する。オーバーライド禁止。
  • "eql?"メソッドはHashキーとして使われているオブジェクトの比較に使われる。たいていの場合は"=="の別名として定義した方が良い。
  • "=="メソッドは2つのオブジェクトが同じ値かどうかを緩やかにテストする。
  • "==="メソッドはcase式のwhen節をテストする。左被演算子がwhenに与えられる引数、右被演算子がcaseに与えられる引数であることに注意。

"<=>"とComparableモジュールで比較を定義する

  • "<=>"演算子を実装し、Comparableモジュールをincludeする
  • "<=>"演算子は、比較できない場合はnilを返す

Version.rb

サンプルはこんな感じでした。

protectedメソッドを使ってprivateな状態を共有する

  • privateな状態はprotectedメソッドで共有する
  • レシーバを明示してprotectedメソッドを呼び出せるのは、同じクラスのオブジェクトか共通のスーパークラスからprotectedメソッドを継承してるオブジェクトだけ

public interfaceは必要最低限にしたいので、関連クラスのオブジェクト間同士の処理はprotectedでの記述を検討しましょう。

クラス変数よりもクラスインスタンス変数を使うようにする

  • クラス変数はグローバル変数と同様の問題(並行処理など)があるため、クラスインスタンス変数を使う。
  • クラスはオブジェクトのため、専用のprivate instance変数セットを持っている。
  • Singletonを作成したい場合は include(Singleton) する

Effective Ruby 第二章 クラス、オブジェクト、モジュール まとめ その1

いつぞやの続きです。

shotat.hateblo.jp

Effective Ruby

Effective Ruby

一記事一章にまとめようとしたところ二章目から量が多くて詰んだので適当なところで切ることにしました。

Effective Ruby 第二章のテーマは"クラス、オブジェクト、モジュール"です。

Rubyは純粋オブジェクト指向言語とも呼ばれていて、全てがオブジェクトです。クラス、数値リテラルを含め全てオブジェクトです。クラス自体がオブジェクトなのです。

用語

  • オブジェクト: 変数の入れ物(※)
  • インスタンス変数: オブジェクトに状態を表現する変数
  • インスタンス: 特定のクラスの実例
  • クラス: メソッドと定数の入れ物
  • インスタンスメソッド: クラスのインスタンス(オブジェクト)のふるまいを表現する
  • クラス変数: クラスに格納された変数
  • クラスオブジェクト: (クラス自体がオブジェクト)
  • クラスメソッド: クラスオブジェクトのメソッド
  • スーパークラス: クラス階層内の親クラスの別名
  • モジュール: 制限付きクラス(newとかがない)
  • 特異クラス(singleton class): クラス階層に現れる不可視クラス。全てのオブジェクトが一つ持つ。
  • 特異メソッド(singleton methods: 特異クラスに格納される、クラスメソッドや特定オブジェクト専用メソッド
  • レシーバ: メソッドが呼び出されるオブジェクト

(※)オブジェクトが変数の入れ物っていうのはちょっと違うような気が。 少なくとも変数と振る舞いを両方カプセル化しています。

Rubyの継承階層について

  • オブジェクトは継承階層を使ってメソッドを探す
  • 階層ルートまで辿ってもメソッドが見つからなければ method_missing メソッドを探す
  • includeメソッドでmoduleをmixinした場合、特異クラス(不可視)がクラス階層に挿入される
  • singleton_classメソッドはレシーバのための特異クラスを返す
  • singleton_methodsメソッドは特異クラスに格納された特異メソッドを返すメソッド

コード書いて実験するのがわかりやすいですね。

class Hoge
  def foo
    puts 'bar'
  end
end

hoge0 = Hoge.new
hoge1 = Hoge.new
hoge2 = Hoge.new
def hoge2.foo
  puts 'piyo'
end

hoge1.foo
#=> bar
hoge2.foo
#=> piyo

# 特異クラス
p hoge0.singleton_class
#=> #<Class:#<Hoge:0x007fa93d81c480>>
p hoge1.singleton_class
#=> #<Class:#<Hoge:0x007fa93d81c458>>
p hoge2.singleton_class
#=> #<Class:#<Hoge:0x007fa93d81c430>>
### 全部違う(それはそう)

# 特異メソッド
p hoge1.singleton_methods
#=> []
p hoge2.singleton_methods
#=> [:foo]

superのふるまいが複数あることに注意する

  • 継承階層の上位メソッドをオーバーライドする際はsuperキーワードで上位メソッドを呼び出せる
  • 引数・括弧なしでsuperを呼ぶと呼び出し元のメソッドに渡された全ての引数を渡してオーバーライドされるメソッドの呼び出しをするのと同じ。暗黙的な挙動のため注意。
  • 引数を渡したくない場合は super() のように括弧をつける

基本的に括弧つけた方がよさげです。

サブクラスの初期化にはsuperを呼び出す

  • Rubyのサブクラスのinitializeメソッドは自動的にスーパークラスのinitializeのメソッドを呼び出さない。
  • initializeメソッドも通常のメソッドルックアップ規則が当てはまる(継承階層をたどる)
  • 明示的にinitializeメソッドを定義するときはinitializeメソッド内でsuperを呼ぶ。initialize_copyとかでも同様。

紛らわしい構文に注意

  • Rubyはメソッド名の末尾に "?", "!", "=" 等が使えるが、 "=" は構文的に別なので注意(セッターメソッド)
  • 代入と異なり、セッターメソッドは明示的なレシーバが必要
hoge = 1 # 代入
foo.bar = 2 # セッターメソッド呼び出し
self.a = 3 # セッターメソッド呼び出し
  • セッターメソッド以外は明示的にレシーバ指定しなくてOKなので、不要なselfを連発してはいけない。

続きます。

OSSへContributionする際のPull Request出す手順とか

最近PhoenixとかElixir面白そうだなーと思って勉強しているんですが、 PhoenixのCONTRIBUTING.md の説明がOSS Contribution guideとして分かりやすかったのでメモ。

github.com

詳細は、上記リンク読むとわかります。コマンドとかも載ってます。

要点をまとめると以下です。

  • Repositoryをforkする
  • fork元を "upstream" 、(fork先を"origin")にする
  • fork先のRepositoryのmasterに変更をcommitしない。feature branchを切ってmasterはupstreamに追従させる。
  • PR送る前にローカルでtestを走らせる
  • upstream/masterをmergeしちゃだめ絶対。rebaseする。

あとはプロジェクトごとに CONTRIBUTING.md とか CODE_OF_CONDUCT.md があるので必ず目を通しましょう。

Elixirはコード読んでる途中でtypo見つけて直したので晴れてContributorになりました。EilxirのContributorです、どうも。

github.com

結構いろんなOSSのコード読みつつFix typo系のPR送って生活してるんですが、Phoenixtypoは見つけられませんでした。Contribution guideもしっかりしてるのでコードレビューきっちりやってる印象です。

zsh promptをpureに設定した

zshの見た目とか補完とかhighlightの設定とかもろもろ変えようと思ってたら pure がめっちゃしっくりきました。

github.com

Most prompts are cluttered, ugly and slow. I wanted something visually pleasing that stayed out of my way.

らしいです。

zshのカスタマイズは prezto でやってるので、その前提でいくと、以下の設定でprompt切り替えができます。

  • .zpreztorcの設定
zstyle ':prezto:module:prompt' theme 'pure'
PURE_PROMPT_SYMBOL='🤔 '

見た目はこんな感じです。
2行に分かれてるのですっきりしててかっこいいです。

f:id:shotat_jp:20160914235825p:plain

Effective Ruby 第一章まとめ

最近仕事でJava、趣味でElixirを書いてるのですが、来週くらいから仕事でRuby書くっぽいのでRubyの復習を始めつつブログのネタにします。というわけでEffective Rubyを読み始めました。初見です。

Effective Ruby

Effective Ruby

備忘録がてら第一章で扱われている内容について簡単に。

Rubyの真偽値

  • false, nil以外の値は全て真(0も真)
  • falseを判定したい場合 false == 比較対象
  • nil判定は nil? メソッド

比較時にfalseを右辺に書くと左辺のObjectの挙動に引っ張られるので危険らしいです。

Rubynilの扱い

  • 基本的にnil チェック必要
  • nilはオブジェクト
  • nilは型変換すれば落ちない
nil.to_i * 2
#=> 0
nil.to_s.length
#=> 0
nil.length
#=> error!

ただ、nilとかemptyのチェックは実際Active Supportのメソッド使うことが多そうな印象です。

www.techscore.com

Perlっぽい機能を避ける

ruby-doc.org

"特殊なグローバル変数"、正しい日本語名が分からない。 ちょっと自信ないですが英語だとSpecial variablesでヒットします。

定数がImmutableでない

  • 普通に定数書き換え可能
  • Object#freezeしよう
  • コレクションのfreezeは要素までfreezeする
AAA = ["foo", "bar"].freeze # NG
BBB = ["foo", "bar"].map(&:freeze).freeze #OK
  • 定数はモジュールにまとめてfreezeする
module Hoge
  CCC = 1
end
Hoge.freeze

Objectの参照考えるのちょっとめんどくさいですよね。 ところでElixirのコレクションは完璧にImmutableなので分かりやすいですよ!

Warningを出す

RUBYOPT='-w'
export RUBYOPT
  • 実行時のWarningは$VERBOSE変数にtrue|false|nilのいずれかを指定する

基本Rubocop使いながら開発するはずなのでコンパイル時警告はあまり気にならないかも

Vimのtabは使わなくて良いかも

Vimにはbuffer, window, tabという概念があります。
このへんの詳細は以下のエントリ等にまとまっていました。

cohama.hateblo.jp

:tabnewコマンドでtabを生成することができます。が、僕は全く使いません。 複数ファイル編集時はWindow分割してbufferを適当に切り替えて生活しています。tabは一切使いません。 単純にtabとbufferとwindowを自分の脳味噌で管理し切れないからです。

ただ、素のVimで大量のbuffer(とwindow)を扱うのも若干の苦しさがあるので、pluginの力を借ります。

github.com

"vim-airline"というVimの見た目を超かっこよくしてくれるpluginを使います。 こいつは見た目を超かっこよくしてくれるにとどまらず、結構いろいろな機能を提供してくれます。

vim-airlineの機能の一つ、"Smarter tab line"を使うと、bufferをtabっぽく扱えるようになります。画像参照。

f:id:shotat_jp:20160913013218p:plain

設定はこんな感じで使ってます。

" カーソルキーでbuffer移動
nnoremap <Left> :bp<CR>
nnoremap <Right> :bn<CR>
" Smarter tab line有効化
let g:airline#extensions#tabline#enabled = 1
" powerline font入れないと若干ダサい
let g:airline_powerline_fonts = 1
" vim-airline-themesが必要
let g:airline_theme='behelit'

ところでVim8系がリリースされたそうで、おめでたいですね。

実践Vim 思考のスピードで編集しよう!

実践Vim 思考のスピードで編集しよう!

Vim再入門 Operator, Motion, TextObjectの理解とドットコマンド

Vimを使う上で "."コマンドが重要です。
"."コマンドは直前の操作の繰り返しを行うコマンドです。

例えばdawコマンドはカーソル下の単語を削除する操作ですが、ここで"."キーを押下すると再び他の単語を削除することができます。

1単語を削除する、等の定形操作は2,3回続けて行うケースが非常に多いので、ドットコマンドを癖にしておくと効率よくtext editすることができて大変気分が良いです。

"."コマンドは超強力ですが、使いこなすためには少なくとも次の3つの概念を理解することが必要不可欠です。

  • Operator
  • Motion
  • TextObject

上記3つが必要な理由としては、Vimにおける1つの操作単位が、基本的には以下の組み合わせで考えられるためです。(Visualモード等は今回考えないものとします。)

  • Operator + TextObject
  • Operator + Motion

Operator + TextObjectの例

いわゆる有名なdawciw等がこれにあたります。

それぞれdcがOperatorで、awiwがTextObjectに対応します。

Operatorで削除や変更といった操作を指定し、TextObjectで操作範囲を指定しています。

Operator + Motionの例

gU$=G等がこれにあたります。

それぞれgU=がOperatorで、$GがMotionに対応します。

Operatorで大文字化やインデント整形といった操作を指定し、Motionで操作範囲を指定しています。

基本的にはOperator + TextObjectのパターンと似ています。

"."コマンド

上記のOperator + TextObject、Operator + Motionが一つの操作の単位になります。 すなわち、上記コマンド実行後、"."コマンドを実行することで3~4キーストローク必要な操作を1キーストロークで繰り返すことができます。最初の方の繰り返しになりますが、同じ操作を数回繰り返す、ということはtext editにおいてはよくあるケースなので、"."コマンドは多用するように心がけていくのが良いです。

今回深くは踏み込みませんが、insertモードに入ってからnormalモードに戻るまで、というのも一つの操作の単位となり、"."コマンドで繰り返すことができます。

Operator

Operatorはtextを操作するものです。MotionやTextObjectと組み合わせて使います。 操作とは以下のようなものがあります。

  • 削除
  • 変更
  • 大文字小文字の入れ替え
  • テキストフォーマット
  • インデントの変更

上記の操作に対応するOperatorはd(削除) 、c(変更)等です。 Operatorの一覧を見るのが手っ取り早いと思うので、一覧を表示してみましょう。Vimを立ち上げて徐ろに以下のコマンドを打つと具体的なOperatorのリストが表示されます。

:h operator

困ったらヘルプ(:h or :help)を使いましょう。

:help operator

1. Motions and operators             *operator*

The motion commands can be used after an operator command, to have the command
operate on the text that was moved over.  That is the text between the cursor
position before and after the motion.  Operators are generally used to delete
or change text.  The following operators are available:

c   change
d   delete
y   yank into register (does not change the text)
~   swap case (only if 'tildeop' is set)
g~  swap case
gu  make lowercase
gU  make uppercase
!   filter through an external program
=   filter through 'equalprg' or C-indenting if empty
gq  text formatting
g?  ROT13 encoding
>    shift right
<    shift left
zf  define a fold
g@  call function set with the 'operatorfunc' option

g~で大文字小文字変換、zfで折りたたみの定義ができることがわかりますね。

TextObject

TextObjectとは意味のあるtextの固まりです。 通常、単語やカッコの中身を操作対象にすることが多いと思います。TextObjectはそれらをうまく表現するための仕組みです。 具体的には以下のようなものがあります。

  • 単語
  • 段落
  • カッコ内のtext
  • 引用符内のtext

例の如く、以下のコマンドで一覧を確認することができます。

:h objects

:h objects

2.1 Text objects                     *objects*

These can be used after an operator or in Visual mode to select an object.

command        action in op-pending and Visual mode ~
------------------------------------------------------------------------------
a"         double quoted string
a'         single quoted string
a(         same as ab
a)         same as ab
a<          "a <>" from '<' to the matching '>'
a>          same as a<
aB         "a Block" from "[{" to "]}" (with brackets)
aW         "a WORD" (with white space)
a[         "a []" from '[' to the matching ']'
a]         same as a[
a`         string in backticks
ab         "a block" from "[(" to "])" (with braces)
ap         "a paragraph" (with white space)
as         "a sentence" (with white space)
at         "a tag block" (with white space)
aw         "a word" (with white space)
a{         same as aB
a}         same as aB
i"         double quoted string without the quotes
i'         single quoted string without the quotes
i(         same as ib
i)         same as ib
i<          "inner <>" from '<' to the matching '>'
i>          same as i<
iB         "inner Block" from "[{" and "]}"
iW         "inner WORD"
i[         "inner []" from '[' to the matching ']'
i]         same as i[
i`         string in backticks without the backticks
ib         "inner block" from "[(" to "])"
ip         "inner paragraph"
is         "inner sentence"
it         "inner tag block"
iw         "inner word"
i{         same as iB
i}         same as iB

よく使うのはawiwibi"等でしょうか。

Motion

いわゆるh, j, k, lでカーソル移動、0, $で文頭文末移動gg, G`で行頭行末移動、等です。Vim始めて最初に覚えるやつですね。

こちらも以下のコマンドで確認できますが、量が膨大なのでこのページ上では割愛します。

:h motion.txt

まとめ

Vimの機能を深く知るためには:helpを使いこなしましょう。

実践Vim 思考のスピードで編集しよう!

実践Vim 思考のスピードで編集しよう!

実践Vimは1000回くらい読みましょう。

BEAM(Erlang VM)とは何の略語なのか

JavaVMと言えばJVM、すなわち"Java Virtual Machine"です。 Erlang VMの主流なものにBEAMというものがあるのですが、何かのアクロニムなのでしょうか。

Wikipediaや日本語記事は見つかりませんでしたが、StackOverFlowで回答されてました。

stackoverflow.com

It stands for "Bogdan/Björn's Erlang Abstract Machine" - it is just the name of the VM, much like JVM (Java Virtual Machine).

信憑性は不明ですがそれっぽいです。

Elixir楽しいです。

プログラミングElixir

プログラミングElixir