2017年を振り返ってみて

残り25分しかないんですが雑に書いてみます。

C++

相変わらず Twitter とかでてきとーに言ってる事が多かったです。
C++ 界隈のニュースで言えば、つい先日やっと C++17 がリリースされましたね。
これでやっと <variant><optional> が標準ライブラリに追加されたり、構造化束縛や constexpr lambda みたいな機能も実装されました。
いやー C++20 もたのしみですねー。
個人的な話でいえば、Ruby の Enumerable っぽいライブラリを夏頃に書きました。
コードはクソですが、実装手段としては結構気に入っているのでどこかでまとめ記事を書こうかなーと思っていたら年を越してしまいそうなのでぐぬぬ…。
そのうち書きます…。

Ruby

今年も C++ より Ruby ばっかり書いていたような気がします。
個人的なニュースでいえば Ruby に投げたパッチが取り込まれた奴ですかねー。
内容自体はしょぼいんですが、こういうのを投げて取り込まれるのははじめてなので素直によかった。
これを期に来年は Ruby 本体のほうにもちょっとずつ関心を向けていきたい。

あと今年つくった gem は以下のような感じ。


相変わらず役に立たない gem ばかりつくっているので来年ももっと役に立たない gem をつくっていきたい。

Vim

無です。
来年はなんかしたい。

Electron + Vue.js + JavaScript

あんまりアウトプットしてなかったんですが、Electron + Vue.js + JavaScript で簡単なアプリとかつくってました。
今までフロントエンドはちょろちょろーっと触ったことはあるんですが、Vue.js や JavaScript をガッツリと触ったのはこれがはじめてかなー?(正確にいえば ES2015 を。
async/await なんかもはじめて触ったんですがめちゃくちゃ便利でした。
もう全部のプログラミング言語にほしいぐらい。
JavaScript は書いてて思ったよりもストレスがなかったので来年も書いてみたいですね。
フロントエンドって意味ならもうちょい開発環境(ビルドシステム)とかもどうにかしたい…。

Advent Calendar

一人 Advent Calendar やりました。


1人で2つも25日間記事を書き続けるとかあたまおかC。
でも来年もやりたい。

勉強会

今年は後半にちょいちょい勉強会に参加してみました。
来年も勉強会にちょいちょい参加して LT なんかをしていきたいですね。

来年の抱負

まあ今まで通りてきとーにプログラミング書いていきたいなーという感じ。
Ruby はそろそろ Rails やらなと人権がないので今年こそはやりたいですね…。
もしくは Hanami をやってみたい。
時代はうぇぶぷろぐらみんぐ。
あと Electron + Vue.js の技術を忘れないうちにまた何かつくりたいですね…。

それは良いお年をー。
そして書いている間に年が開けてしまったのであけおめー。

【一人 vimrc advent calendar 2017】vimrc を拡張するコツ【25日目】

一人 vimrc advent calendar 2017 25日目の記事になります。
今日で終わりっ!! と、言うことで vimrc を拡張するコツみたいなものを。

vimrc を設定する目的

vimrc を書こう!って言っても最初はどういう風に書けばいいのかわからないと思います。
Vim はかなり特殊なエディタなのでまずは

  • Vim らしい使い方


よりも

*自分の使い勝手のよいエディタ


を目指すとよいともいます。
Vim を使い始めた人がよく『カーソルキーを封印する』みたいな事を行っている人がいると思うんですが、そういう矯正をしてストレスを溜めるよりも『ストレスがない設定』を行っているほうがよいかなーと個人的には思います。
別に自分が使いやすければカーソルキーを使ってもええんやで…。

:help を読む

まずは基本中の基本ですが :help を読みましょう。
Vim:help がかなり充実しているので、わからないオプションやコマンドなんかが出てきたらすぐに調べる癖を付けておきましょう。

まず何から設定するべきか

vimrc ではまず、オプションを使って自分が使いやすいように挙動を制御していくとよいと思います。
どんなオプションがあるのかは :help option-list に簡単にまとまっているのでざっと眺めてみるとよいでしょう。
ちなみにオプション数は約300個ぐらいあります。
オプションの次は


みたいな順で設定を拡張していくとわかりやすいかなーと思います。

Vim script を知る

vimrc を書くということはつまり Vim script を書くことになります。
もちろん :set コマンドでオプションを設定するだけでも Vim はカスタマイズすることは出来るんですが、基本的な制御構文や組み込み関数、変数の扱いなんかを覚えるとより設定の幅が広がります。
Vim script については :help vim-script-intro なんかを読んでみるとよいでしょう。

キーマッピングを行う際の注意点

これは注意点というかわたしの持論なんですが『コマンドを呼び出すようなキーマッピングは極力しない』方がいいです。
例えば、以下のようにコマンドを呼び出すようなキーマッピングを行っていることは多いと思います。

nnoremap <Space>udm :Unite directory_mru<CR>
nnoremap <Space>urm :UniteResume<CR>
nnoremap <Space>uff :Unite file file/new -hide-source-names<CR>
nnoremap <Space>uol :Unite outline -no-quit -buffer-name=outline -winheight=10<CR>
nnoremap <Space>unb :Unite neobundle<CR>
nnoremap <Space>url :Unite reanimate:default_category -default-action=reanimate_switch<CR>
nnoremap <Space>urs :Unite reanimate:default_category -default-action=reanimate_save<CR>

一見すると便利そうなんですが、この手のキーマッピングは設定しても『まず覚えきれない』ので『無駄』です。
このようなコマンドを呼び出すキーマッピングは、


というのではなくて

  • 1日1000回ぐらい呼び出すようなコマンドはキーマッピングしておく


というぐらいのほうが無駄なキーマッピングを省くことができるので便利です。
また、長いコマンドはキーマッピングではなくてユーザ定義コマンド化しておくのもよいでしょう。

command! UniteFile Unite file file/new -hide-source-names

ただし、以下のように『デフォルトの操作を変更する』ようなキーマッピングは覚える必要がないのでどんどんしていくとよいと思います。

" https://sites.google.com/site/fudist/Home/vim-nihongo-ban/tips#TOC--3
" カーソルを表示行で移動する。物理行移動は<C-n>,<C-p>
nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk

nnoremap <Down> gj
nnoremap <Up>   gk

" カーソルキーで行末/行頭の移動可能に設定。  
set whichwrap=b,s,[,],<,>
nnoremap h <Left>
nnoremap l <Right>

頻繁に使うようなコマンドは予めユーザ定義しておく

先ほどのキーマッピングの話でもあったのですが、以下のようによく使うコマンドなどはユーザ定義しておくとよいです。

" ハードタブをソフトタブに
command! TabToSoft %s/\t/    /ge
" 行末の空白文字を削除
command! RemoveLastSpace %s/\s\+$//ge

こうすることで入力する手間を省くことが出来ます。
また、コマンド化しておけば autocmd なんかでも呼び出しやすくなりますね。

他人の vimrc を読む

他人の vimrc はパンツです。
そしてパンツは見たくなるものですよね。
vimrc を公開している人は結構いるので気になる人や憧れている人のパンツ vimrc をみてみると興奮して新しい発見があって面白いです。
とはいえ、そんなに他人の vimrc を読むことはあまりないと思うのでvimrc 読書会などに参加してみるとよいと思います。
他人の便利な設定はどんどんパクっていきましょう。

定期的に vimrc を見直す

これが一番重要です。
vimrc を設定していくとどんどん肥大化していきます。
肥大化していくと管理が難しくなったり Vim の起動時間などにも影響してきます。
vimrc はどうしても『その場』で『雑に』設定を追加してしまうことが多いので、定期的に整理していく必要があります。
特に利用していないキーマッピングプラグインがあればどんどん削除してしまいましょう。
逆にユーザ定義コマンドなどはそれほど副作用が大きくないのであまり使っていなくてもそのまま残しておいてもよいと思います。

変数のスコープに注意する

vimrc を書くと言うことは Vim script を書くことになります。
ただ、Vim script は結構癖が強い言語なので注意して書く必要があります。
例えば、変数のスコープが結構特殊で変数名に prefix を付けることでそのスコープを明示化します。

" g: をつけるとグローバル変数
" どこからでもアクセスできる
let g:value = 42

" s: をつけるとスクリプトローカル変数
" そのスクリプトファイル上でのみ参照できる
let s:value = 42

上記のようにスコープごとに別々に変数を定義します。
また、prefix を付けなかった場合は『グローバル変数』として定義されるので注意する必要があります。

" g:value と同等
let value = 42

" こういう i もグローバル変数として定義される
for i in [1, 2, 3]
   " ...
endfor

特に理由がなければ vimrc ではスクリプトローカル変数(s:)として定義することで意図しない副作用を抑えることが出来ます。

プラグインは入れたほうがいい?

これは宗教上の理由もあると思いますが、個人的には『プラグインはどんどん入れていっていい』と思います。
やっぱり世の中には便利なプラグインがたくさんあるのでどんどん使っていった方が得かなーと。
欲しいと思った機能がプラグインとしてすでにあったりするのも Vim の魅力の一つですしねー。
ただし、プラグインを使う上では以下のことに注意する必要はあります。

  • プラグインを入れることでパフォーマンスに影響することは覚えておく
  • 競合したり変な設定を行っているプラグインもあるので精査する必要がある
  • 設定が難しいプラグインもあるのでそれなりに Vim script の知識が必要
  • 定期的に使わないプラグインなどは削っていく


まあプラグインを削るのは後からでもできるので、最初は時に気にしないでどんどんプラグインをいれていっていいかなーと思います。

まとめ

  • Vim の機能は全て :help にかかれているのでわからないことがあればすぐにヘルプろう
  • まずはオプションの設定から始めるとわかりやすい
  • vimrc を書く上で Vim script の知識が必要になってくるので、慣れてきたら覚えよう
  • キーマッピングは過剰に設定してもどうせ使わないのでほどほどに
  • vimrc は定期的に見なおそう
  • プラグインはどんどん入れていこう


まー最初は慣れないので書くのが難しいと思うんですが、『習うより慣れろ』って言うことでどんどん設定を書いていくのがよいかなーと個人的には思います。
何度もいいますが、オプションやキーマッピングプラグインなどはあとからいくらでも変更する事ができますしね。
冒頭にも書きましたが『Vim らしい使い方』よりも『自分の使い勝手のよいエディタ』を目指しましょう!!

一人 Advent Calendar を終えて

vimrc は4000行とかあるからネタに困らないやろーと思って始めたんですが、意外とプラグインの設定やあまり汎用性がない設定などが多かったので思ったよりも厳しかったです。
そもそも汎用的な機能は全部プラグイン化しているんやった…。
まあでもそのおかげでネタを探すために vimrc を何回も見なおしたりしていたのでどんな設定をしているのかを見直すことが出来たのはよかったかな。

本当は最初と最後で vimrc がどうなったのか比較してみようかとも思ったのですがそんなに変わってないのでやめておきました。
さっきも書いたんですが設定の殆どがプラグインなので(ry。

そんなわけで来年は『一人 Vim plugin Advent Calendar』でも書こうかなーとは思っています。
思っているだけでやると言っていませんー。
それではまた来年ー。
と、いうか冷静に考えると 1ヶ月の間に 一人 Advent Calendar を2つやりつつ、通常の Advent Calendar の記事を3つ書いて、更に LT 用のスライドを4〜5個書くなんて頭おかC

【一人 Ruby Advent Calendar 2017】Ruby 2.5 がリリース!!【25日目】

一人 Ruby Advent Calendar 2017 25日目の記事になります。
今日で最後!!

Ruby 2.5 がリリース!!

直前にいろいろとあったようですが、無事リリースされました。
コミッタの皆さんお疲れ様でした。

Bundler の標準入りは延期

Ruby 2.5 で標準入りする予定だった Bundler ですが、リリース直前に問題が見つかった為、今回は延期されることに。
うーん、まあ Bundler 自体が結構不安定で反対している人もいたぽいんですが、残念といえば残念かなー。

個人的に気になる変更点や追加点

  • require "pp" が暗黙的に読み込まれるようになった
  • バックトレース順の変更
  • ブロック引数を定義した場合のパフォーマンスの改善
  • Set#===Method#=== の追加
  • レシーバをブロックの引数で受け取りブロックの戻り値を返す #yield_self が追加
  • define_methodattr_accessor などが public 化
  • 式展開時の #to_s が Refiements 時で定義されている場合にも呼ばれるように


などなど、他にも変更された機能や追加された機能はあるので気になる方は以下のサイトなどを参照してみるとよいと思います。
個人的には #=== がちょっと注目されてるのかなーという感じですかね。
#===case-when 以外でもいろいろと応用が効く機能なので今後もいろいろと利用していきたいと思います。

あと今回の式展開の #to_s のように Refinements まわりも年々制限が緩和されている流れですね。
Refinements に関してはまだまだ使う上でちょっとつらい部分があるので、そのあたりを今後 Ruby 本体に提案できればなーと思っていたりします。

参照

一人 Advent Calendar を終えて

と、言うわけでやっと終わりましたーやふー。
途中で少し遅れることはありましたが、なんとか完走する事が出来ました。
やる前からわかってたんですが最初にちょっと書き溜めておいたネタだけじゃ全然足りなかったですね、これ。
やーやっぱり勢いでやるものじゃないわー。

まあしかし、そのおかげでネタを絞りだす為に普段はあまり気にしないような部分も調べて書いたのでそういう意味ではよかったかなーとは思います。
トップレベルの扱いやキーワード引数まわりは結構てきとーに使っていたので、そのあたりをちゃんと調べて理解出来たのでそういう意味ではやってよかったかなーと思います。

次は1年ぐらい書き溜めて溜まってたら書くぞ〜。
書いた記事の一覧は以下から参照してくださいー。

さて、これからもう1つの方も書かないと…。

【Vue.js #1 Advent Calendar 2017】Vue.js + Element でフォームダイアログをいい感じに呼び出す【24日目】

Vue.js #1 Advent Calendar 2017 24日目の記事になります。
少し前に Electron + Vue.js + Element でネイティブアプリの開発を行っていたのですが、その時に利用したコードなどを簡単に紹介してみようかと思います。

Element とは

Element(element-ui) とは Vue 2.0 ベースのコンポーネントライブラリになります。
例えば、以下のようにモーダルダイアログからフォーム入力などを行うことが出来ます。

index.html

<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<div id="app">

  <!-- 登録ダイアログ -->
  <el-button @click="registry_visible = true">登録</el-button>
  <pre>{{ registry_data }}</pre>

  <el-dialog :visible.sync="registry_visible" title="保存">
    <el-form :model="registry_form" label-width="120px">
      <el-form-item label="first name">
        <el-input v-model="registry_form.first_name"></el-input>
      </el-form-item>
      <el-form-item label="last name">
        <el-input v-model="registry_form.last_name"></el-input>
      </el-form-item>
      <el-form-item label="age">
        <el-input v-model="registry_form.age"></el-input>
      </el-form-item>
    </el-form>

    <span slot="footer" class="dialog-footer">
      <el-button @click="registry_visible = false">Cancel</el-button>
      <el-button type="primary" @click="registry_submit">保存</el-button>
    </span>
  </el-dialog>
  
</div>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="./script.js"></script>

script.js

new Vue({
  el: '#app',
  data: function() {
    return {
      registry_visible: false,
      registry_form: {},
      registry_data: [],
    }
  },

  methods: {
    registry_submit(){
      this.registry_data.push(this.registry_form);
      this.registry_form = {};
      this.registry_visible = false;
    },
  },
});

on jsbin.com

こんな感じのコードをもうちょっと使いやすくしてみたので今回はそれについて書いてみようかと思います。

問題点

問題点ってほどでもないと思うんですが、例えばフォーム入力にデフォルト値とかを設定したい場合にちょっと複雑になってきます。

<!-- 登録ダイアログ -->
<!-- 開く時に関数を呼び出す -->
<el-button @click="open_registry">登録</el-button>
<pre>{{ registry_data }}</pre>

<el-dialog :visible.sync="registry_visible" title="保存">
  <el-form :model="registry_form" label-width="120px">
    <el-form-item label="first name">
      <el-input v-model="registry_form.first_name"></el-input>
    </el-form-item>
    <el-form-item label="last name">
      <el-input v-model="registry_form.last_name"></el-input>
    </el-form-item>
    <el-form-item label="age">
      <el-input v-model="registry_form.age"></el-input>
    </el-form-item>
  </el-form>

  <span slot="footer" class="dialog-footer">
    <el-button @click="registry_visible = false">Cancel</el-button>
    <el-button type="primary" @click="registry_submit">保存</el-button>
  </span>
</el-dialog>
new Vue({
  el: '#app',
  data: function() {
    return {
      registry_visible: false,
      registry_form: {},
      registry_data: [],
    }
  },

  methods: {
    // ダイアログを開く関数
    open_registry(){
      this.registry_visible = true;
      form = this.registry_data[this.registry_data.length - 1] || {
        first_name: "yamada",
        last_name:  "tarou",
        age: 20
      };
      Object.assign(this.registry_form, form);
    },

    // フォームを登録する時に呼ばれる関数
    registry_submit(){
      this.registry_data.push(this.registry_form);
      this.registry_form = {};
      this.registry_visible = false;
    },

  },
});

JS Bin on jsbin.com

こんな感じで複数の関数を言ったり来たりするのがちょっともにょったのでなんとかしてみました。

async/await を利用する

まず、async/await を利用して上記open_registry()registry_submit() を1つの関数にまとめてみました。

index.html

<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<div id="app">
    <!-- 登録ダイアログ -->
    <el-button @click="registry">登録</el-button>
    <pre>{{ registry_data }}</pre>

    <el-dialog :visible.sync="registry_visible" title="保存" :before-close="close">
      <el-form :model="registry_form" label-width="120px">
        <el-form-item label="first name">
          <el-input v-model="registry_form.first_name"></el-input>
        </el-form-item>
        <el-form-item label="last name">
          <el-input v-model="registry_form.last_name"></el-input>
        </el-form-item>
        <el-form-item label="age">
          <el-input v-model="registry_form.age"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="registry_visible = false">Cancel</el-button>
        <el-button type="primary" @click="submit">保存</el-button>
      </span>
    </el-dialog>
</div>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="./script.js"></script>

script.js

new Vue({
  el: '#app',
  data: function() {
    return {
      registry_visible: false,
      registry_form: {},
      registry_data: [],
    }
  },

  methods: {
    open(name, form){
      this[`${name}_form`] = form;
      this[`${name}_visible`] = true;
      return new Promise((resolve, reject) => {
        var submitted = false;
        this.submit = () => {
          this[`${name}_visible`] = false;
          submitted = true;
          resolve(this[`${name}_form`]);
        };

        this.close = () => {
          this[`${name}_visible`] = false;
          if( !submitted ){
            reject("Dialog is closead.");
          }
        };
      });
    },
    // ダミー
    submit(){},
    close(){},

    async registry(){
      this.registry_visible = true;
      form = this.registry_data[this.registry_data.length - 1] || {
        first_name: "yamada",
        last_name:  "tarou",
        age: 20
      };
      result = await this.open("registry", {...form});
      this.registry_data.push(result);
    },
  },
});

JS Bin on jsbin.com

こんな感じで async/await を使うことで

result = await this.open("registry", {...form});

のように直接フォームを呼び出して、その値を取得することが出来ます。

コンポーネント化する

さてさて、先ほどのコードだとちょっと汎用性にかけるので簡単にコンポーネント化してみたいと思います。

Vue.component("form-dialog-wrapper", {
  template: `
    <div>
      <slot :submit="submit" :form="form" :close="close" :visible.sync="visible"></slot>
    </div>
  `,
  data(){
    return {
      visible: false,
      form: {},
    }
  },

  methods: {
    open(form){
      this.form = form;
      this.visible = true;
      return new Promise((resolve, reject) => {
        var submitted = false;
        this.submit = () => {
          this.visible = false;
          submitted = true;
          resolve(this.form);
        };

        this.close = () => {
          this.visible = false;
          if( !submitted ){
            reject("Dialog is closead.");
          }
        };
      });
    },

    // ダミー
    close(){},
    submit(){}
  }
});

コンポーネントはこんな感じです。
Vue.js のポイントとしては slot を使って form のデータのやり取りを行うところでしょうか。
HTML 側では以下のように使用します。

index.html

<!-- 登録ダイアログ -->
<el-button @click="registry">登録</el-button>
<pre>{{ registry_data }}</pre>

<!-- JavaScript 側から参照できるように ref で名前付けしておく -->
<form-dialog-wrapper ref="dialog_registry">
  <!-- form データへの参照は slo-scope 経由で行う -->
  <el-dialog title="保存" slot-scope="props" :visible.sync='props.visible' :before-close="props.close">
    <!-- slot-scope 経由でデータを参照することでコンポーネントのデータのみ bind 出来る -->
    <el-form :model="props.form" label-width="120px">
      <el-form-item label="first name">
      <el-input v-model="props.form.first_name"></el-input>
      </el-form-item>
      <el-form-item label="last name">
      <el-input v-model="props.form.last_name"></el-input>
      </el-form-item>
      <el-form-item label="age">
      <el-input v-model="props.form.age"></el-input>
      </el-form-item>
    </el-form>

    <span slot="footer" class="dialog-footer">
      <el-button @click="props.close">Cancel</el-button>
      <el-button type="primary" @click="props.submit">保存</el-button>
    </span>
  </el-dialog>
</form-dialog-wrapper>

こんな感じで slot-scope="props" を利用してコンポーネントのデータを参照します。
このようにすることでメインの Vue ではフォームの入力データなどを用意する必要がなくなります。
実際にメインの Vue は以下のようになります。

new Vue({
    el: '#app',
    data: function() {
        return {
            registry_data: [],
        }
    },

    methods: {
        async registry(){
            form = this.registry_data[this.registry_data.length - 1] || {
                first_name: "yamada",
                last_name:  "tarou",
                age: 20
            };

            // ref 経由でコンポーネントを参照する
            result = await this.$refs["dialog_registry"].open({...form});
            this.registry_data.push(result);
        },
    },
});

このようにかなりコードがすっきりしている事がわかると思います。

JS Bin on jsbin.com

まとめ

と、言う感じでフォームダイアログをいい感じにしてみました。
元々はフォームダイアログが複数あってどんどんデータが肥大化していったのでなんとかしたいと思いこんな感じのロジックを思いつきました。
Vue.js もそうですが async/await めちゃ便利ですね…。
Vue.js 自体はまだ全然やれてないんですが、こういうのを回避する手段って他にもあったりするんですかね…(ちなみに Vuex はまだやってない。

そんな感じで簡単に書いてみましたー。
もっとこうしたらいいよーみたいなのがあればコメントや Twitter までおねがいしますー。

【一人 Ruby Advent Calendar 2017】キーワード引数や Hash の渡し方や受け取り方いろいろ【24日目】

一人 Ruby Advent Calendar 2017 24日目の記事になります。
Ruby 3.0 でキーワード引数をぶっ壊すらしいのですが、現状の仕様をよく理解していないので簡単にまとめてみようかと。

Hash を渡す時に {} を省略

引数の最後が Hash 値の場合、{} を省略して書くことが出来ます。

def func a, b
    return a, b
end

# Hash 値を渡す
p func 42, { name: "homu", age: 14 }
# =>[42, {:name=>"homu", :age=>14}]

# 最後の引数が Hash 値の場合、{} を省略出来る
p func 42, name: "homu", age: 14
# =>[42, {:name=>"homu", :age=>14}]

# Hash でなくても渡せる
p func 42, 32
# =>[42, 32]

# 最後でなければエラー
# Error:syntax error, unexpected ')', expecting =>
# p func name: "homu", age: 14, 42

** で受け取る

メソッドの引数に ** を付けることで『Hash として受け取る』事を明示化することが出来ます。

def func a, **hash
    return a, hash
end

# Hash 値を渡す
p func 42, { name: "homu", age: 14 }
# =>[42, {:name=>"homu", :age=>14}]

# 最後の引数が Hash 値の場合、{} を省略出来る
p func 42, name: "homu", age: 14
# =>[42, {:name=>"homu", :age=>14}]

# Hash でなければエラー
# Error: wrong number of arguments (given 2, expected 1) (ArgumentError)
p func 42, 32

キーワード引数

以下のように引数を定義する時に『引数名: デフォルト値』と記述することでキーワード引数として定義できる。
キーワード引数はメソッドを呼び出す時に『引数名: 値』のようにして『任意の引数名に対して』引数を渡すことが出来る。

def func id, name: :homu, age: 14
    { id: id, name: name, age: age }
end

p func 1, name: :homu, age: 14
# =>{:id=>1, :name=>:homu, :age=>14}
p func 1, age: 15, name: :mami
# =>{:id=>1, :name=>:mami, :age=>15}

よくあるのが複数の引数があった場合に『一部の引数だけ渡す』みたいな時に使うことが多いですかねー。

def setting a: 1, b: 2, c: 3
    
end

# 一部の引数だけ渡す
setting a: 10
setting b: 20
setting c: 30

まとめ

  • Hash をいい感じに渡す手段はいくつかある
  • メソッドの受け取り側と渡し側でどのようにして引数を渡すのか意識する必要がある


今まで雰囲気で使っていたんですが、思ったよりも役割によって使う機能が違っている感じですねー。
もっとなんか複雑だと思っていたんですが、言われてみれば『そうかーそうやって使い分けるのかー』という印象。
Ruby 3.0 だとこのあたりをもっとよくするらしいんですが、どうなるんでしょうねえ…。

参照

【一人 vimrc advent calendar 2017】キーマッピングの注意点とか【24日目】

一人 vimrc advent calendar 2017 24日目の記事になります。
今日はクリスマスイヴですね。
ケーキを買いに行ったら売り切れていましたかなしい。

モードごとのキーマッピング

さて、気を取り直して…。
Vim はモードごとに操作が分けられているのはご存知だと思いますが、キーマッピングもモードごとに設定することが出来ます。
代表的なのは以下のようなものになります。

登録コマンド 削除コマンド モード
:map :noremap :unmap ノーマル、ビジュアル、選択、オペレータ待機
:nmap :nnoremap :nunmap ノーマル
:vmap :vnoremap :vunmap ビジュアル、選択
:smap :snoremap :sunmap 選択
:xmap :xnoremap :xunmap ビジュアル
:omap :onoremap :ounmap オペレータ待機
:map! :noremap! :unmap! 挿入、コマンドライン
:imap :inoremap :iunmap 挿入
:lmap :lnoremap :lunmap 挿入、コマンドライン、Lang-Arg
:cmap :cnoremap :cunmap コマンドライン

いろいろとありますが、基本的には

  • :nmap :nnoremap
  • :vmap :vnoremap
  • :imap :inoremap
  • :cmap :cnoremap

の4つを覚えておけばよいです(あとは textobj 系プラグインを使うなら omap も。
キーマッピング自体の仕方はまあわかってると思うので省略。

mapnoremap の違い

Vim でキーマッピングをする上で重要なのが mapnoremap の違いになります。
と、言っても特に難しくはなくて map は『再マップされ』、noremap は『再マップされません』。
どういうことかというと例えば、

imap a aa

とした場合、a を入力した時に aa を更に展開しようとするので無限ループします。
一方、

inoremap a aa

の場合は aa は再展開されないので aa だけが入力されます。
なのでキーマッピングを行う際に『他に設定したキーマッピングの影響を受けない場合は :noremap』、『他に設定したキーマッピングの影響を受ける場合は :map』みたいにして使い分ける必要があります。
と、言っても意図的に展開してほしい場合以外は noremap を使っておくほうが混乱がないと思います。

ただし、プラグインを使用していると例えば、

nmap hoge <Plug>(hoge-plugin-mapping)

みたいに <Plug>(hoge-plugin-mapping) をキーマッピングすることがあります。
この <Plug>(hoge-plugin-mapping) というのは『プラグイン側でマッピングされている設定』になります。

" プラグイン内ではこんな感じでキーマッピングされている
nnoremap <silent> <Plug>(hoge-plugin-mapping) :<C-u>Hoge<CR>

なので、このような場合は mapマッピングする必要があります。

まとめ

  • Vim ではモードごとにキーマッピングを行うことが出来る
  • mapnoremap は再展開されるかされないかの違い
  • 基本的には noremap を使っておくほうが副作用がなくて安全


キーマッピングについてはいろいろと書きたいことはあるんですが、まー基本的には変な縛りを設けないで自分が使いやすいようなキーマッピングをしておくとストレスなく Vim を使うことが出来るのでよいと思います。
Vim に慣れるのではなくて、自分が使いやすい Vim を目指しましょう。

【一人 Ruby Advent Calendar 2017】Ruby で外部ファイルを読み込むメソッドいろいろ【23日目】

一人 Ruby Advent Calendar 2017 23日目の記事になります。
今回は require などの外部ファイルを読み込むメソッドを簡単にまとめてみます。

Kernel.#require

引数の Ruby のライブラリを読み込みます。
ここでいう Ruby のライブラリとは、

などのファイルを指します。

# Ruby のスクリプロファイルを読み込む
require "hoge.rb"

# 動的ライブラリを読み込む
require "foo.o"

また、拡張子を省略して記述することも出来ます(その場合は *.rb を優先して両方のファイルを検索します。

# hoge.rb を優先しつつ hoge.o などを読み込む
require "hoge"

同じファイルは複数回読み込みません。
ファイルが絶対パスの場合はそのファイルを、相対パスの場合は組み込み変数 $: から検索し、最初に見つかったファイルを読み込みます。
また、『require してるファイルのカレントディレクトリ』は検索の対象にならないので『require しているファイルからの相対パス』で読み込みたい場合は注意してください。

# こんな感じで require しているファイルからの相対パスでファイルは読み込めない
require "../hoge/foo"

Kernel.#require_relative

『現在のファイルからの相対パス』で require します。
以下のような挙動とほぼ同じです。

require File.expand_path({ファイル名}, File.dirname(__FILE__))

require しているファイルからの相対パス』のファイルを読み込みたい場合は require ではなくて require_relative を使用してください。

Kernel.#load

require と違い再ロード可能です。
相対パスの場合は『カレントディレクトリ』も含めて検索します。
また、require は拡張子を省略した場合は自動的に *.rb などを補完しますが、load は『拡張子を補完しない』ので拡張子を記述する必要が有ります。

Kernel.#autoload

指定した定数の名前を最初に参照した時に自動で require を行います。

# この時点ではまだ "hoge" は読み込まれない
autoload(:Hoge, "hoge")

# 最初に Hoge を参照した時に require("hoge") が実行される
p Hoge

まとめ

メソッド名 検索対象 拡張子 再ロード
require $: のパス 省略化 されない
require_relative 現在のファイルからの相対パス 省略化 されない
require $: とカレントディレクト 省略不可 される


基本的に『ライブラリを読み込む際は require』を使い、『相対パスで読み込みたい場合は `require_relative』を使う、みたいな感じで使い分けるとよいと思います。