表参道.rb #27 での発表に一部誤りがあったので訂正と補足
発表から一週間以上経ってしまっているんですが、発表中の発言に一部誤りがあったので訂正と補足。
pattern-match を使っているコードを説明する時に
「pattern-match は using PatternMatch
をすることで match
と with
が使えるようになり〜」
と発言していたんですが、正しくは
「pattern-match は using PatternMatch
をすることで match
が使える」
でした。
pattern-match で使用している refinements では match
のみが影響して with
は関係ありませんでした。
では、なぜ with
を使うことが出来るのかというと with
を呼び出しているブロックは内部で #instance_eval
されているためです。
#instance_eval
を経由してブロックを呼び出すことで、評価するコンテキストが別になりブロック内で with
を呼び出せるようになります。
class Env def with puts "with" end end def match &block # instance_eval で block を評価することで # block 内で Env のインスタンスメソッドを呼び出すことが出来る Env.new.instance_eval &block end match { with with with } # output: # with # with # with
この辺りの内部実装はもう少し解説すべきでしたね…申し訳ありませんでした。
ちなみに個人的には #match
メソッドだけなら『Object#match
で refinements する』のではなくて『module_function
と定義して PatternMatch.match
みたいな呼び出し』でもいいかなーとは思います。
PatternMatch.
の部分が煩わしければ include PatternMatch
とでもしておけばいいですしね。
まあここら辺はどちらがよいのかを考えるのがむずかしいところ…作りての好みもありますし。
C++17 の構造化束縛を range-based for で使う
C++17 では構造化束縛という言語機能が追加されました。
これは std::tie
のように std::tuple
などを個別に変数で受け取る事が出来る機能です。
auto homu = std::make_tuple(1, "homu", 14); // std::tuple の要素を個別に受け取る auto [id, name, age] = homu;
std::tie
とは違い変数定義で使用する事が出来ます。
range-based for で使う
これだけでも便利なのですが、range-based for と組み合わせることで更に便利になります。
#include <tuple> #include <vector> #include <string> #include <iostream> int main(){ std::vector<std::tuple<int, std::string, int>> vc = { { 1, "homu", 14 }, { 2, "mami", 15 }, { 3, "mado", 14 } }; for(auto&& [id, name, age] : vc){ std::cout << "id:" << id << ", name:" << name << ", age:" << age << std::endl; } return 0; } /* output: id:1, name:homu, age:14 id:2, name:mami, age:15 id:3, name:mado, age:14 */
https://wandbox.org/permlink/HwbLhRyBDCdQDsT8
こんな感じに range-based for の変数定義でも構造化束縛を使うことが出来ます。
ますます std::tuple
が便利になりますね。
npm install で github のリポジトリからインストールする
Vim でシンタックスハイライトが突然オフになる現象の対処方法
覚書っていうか情報共有というか。
Vim の syntax が突然オフになる現象にお困りの方へ
— mattn (@mattn_jp) 2017年9月26日
* パッチ 8.0.0647~8.0.1132 の方 → 8.0.1133 以降にアップデート
* 8.0.1133 以降の方 → redrawtime の値をデフォルト値に戻してみて下さい
結構前からこの現象に悩まされていたんですが、わたしの場合は 'redrawtime'
が原因だったのでその設定を見直すことで対処出来ました。
他にもこの現象に悩まされている人がいれば上記の手段を試してみてください。
追記
unite.vim を使っている方は内部で 'redrawtime'
が書き換えられる可能性があるので、unite.vim を更新すると対処出来るかもしれません(最新版の unite.vim では 'redrawtime'
自体の変更が削除されました。
追記2 : 'redrawtime'
について
'redrawtime'
は、
- Vim が再描画を行う際に『
'redrawtime'
に設定された以上の時間がかかる場合』にハイライトを無効にする
というような機能になります。
なので 'redrawtime'
で低い値(ミリ秒)が設定されていたり、描画に時間がかかるような場合にハイライトが無効化されます。
また、『Vim が再描画を行う際』というのも様々で、
hlsearch
がオンの場合のパターン検索:match
時syntax on
時matchadd()
を行った時
などなど、いろいろなタイミングがあります。
もし、突然ハイライトが消えてしまった場合は 'redrawtime'
の値が低くなっていないか(既定値は 2000
)、描画が遅くなかったか、などを確認してみるとよいと思います。
element-ui の tree コンポーネントでノードのレンダリングをカスタマイズする
かなりマイナーなネタですが、element-ui の tree コンポーネントで表示されるノードをカスタマイズしてみたいと思います。
環境
- Vue.js : v2.4.4
- element-ui : v1.4.6
コード
HTML
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- import CSS --> <link rel="stylesheet" href="https://unpkg.com/element-ui@1.4.6/lib/theme-default/index.css"> </head> <body> <div id="app"> <el-tree node-key="id" default-expand-all :data="table" :render-content="renderContent" :props="defaultProps"> </el-tree> </div> </body> <!-- import Vue before Element --> <script src="https://unpkg.com/vue@2.4.4/dist/vue.js"></script> <!-- import JavaScript --> <script src="https://unpkg.com/element-ui@1.4.6/lib/index.js"></script> <script src="./script.js"></script> <script> </script> </html>
JavaScript
new Vue({ el: '#app', data: function() { return { table : [ { id: 1, label: "Level one 1", children: [ { id: 2, label: "Level two 1" }, { id: 3, label: "Level two 2", children: [ { id: 5, label: "Level three 1" }, { id: 6, label: "Level three 2" }, { id: 7, label: "Level three 3" }, ] }, { id: 4, label: "Level two 3" }, ] }, ], defaultProps: { children: "children", label: "label" }, renderContent(h, { node, data, store }){ console.log(h); return h("span", [ h("span", node.label), h("span", { attrs: { style: "float: right; margin-right: 20px;" } }, [ h("el-button", { attrs: { type: "primary", size: "mini" } }, "button") ]) ]); } } } })
https://jsfiddle.net/jxc0m2n6/1/
el-tree
の :render-content
で各ノードのレンダリングを行う関数(renderContent
)を指定することが出来ます。
element-ui のサンプルコードでは renderContent
内で JSX っぽい記述を行っていたのですが、上記のコードでは生JSで記述しています。
書き方とかはまあこんな感じになりますよ、と(生 JS だと hyperscript っぽい記述?よくわかってない…
参照
ES2015(ES6)以降 の JavaScript でオブジェクトのキーに変数を使う
次のように JavaScript でオブジェクトのキーに変数を使おうとしても当然ですが変数は展開はされません。
const key = "age"; const value = 14; const obj = { key : value }; console.log(obj); // => { key: 14 }
通常このような場合は obj[key] = value
みたいにする必要がありました。
const key = "age"; const value = 14; const obj = {}; obj[key] = value; console.log(obj); // => { age: 14 }
ES2015(ES6)以降
ES2015(ES6)以降ではオブジェクトのキーを定義する時に [key]
とすることで変数が展開されるようになります。
const key = "age"; const value = 14; const obj = { [key] : value }; console.log(obj); // => { age: 14 }
これは便利そう。
最近の JavaScript はよく知らないので便利な文法は覚えていきたい。
Ruby の #class_eval と #module_eval の違い
Ruby の #class_eval
はクラスオブジェクト専用、#module_eval
はモジュールオブジェクト専用のメソッドだと思っていたのですが、実は名前が違うだけで同等のメソッドだったみたい。
検証コード
class C end C.class_eval { def homu end } # クラスオブジェクトに対しても #module_eval が使える C.module_eval { def mami end } p C.instance_methods false # => [:homu, :mami] module M end # モジュールオブジェクトに対しても #class_eval が使える M.class_eval { def homu end } M.module_eval { def mami end } p M.instance_methods false # => [:homu, :mami]
結論
#class_eval
と #module_eval
の違いは名前だけなのでケースによってよしなに使い分けましょう。