素人のアプリ開発日記

Androidアプリ開発について紹介します

vimでアルファベット26文字を最小キーストロークで入力する方法

こんにちは、とりかつです。

みなさんはvimで以下のようにアルファベットを入力したくなったことがありませんでしょうか。ありますよね(圧)

abcdefghijklmnopqrstuvwxyz

ということで本記事ではvimでアルファベットを最小キーストロークで入力していく方法について深めていきます。

本記事ではノーマルモードから始まり、ノーマルモードに終わることを前提とします。

一番シンプルな方法

まずは、普通に打ってみましょう。

iabcdefghijklmnopqrstuvwxyz<Esc>

キーストロークは28です。 ですが、a~zまで間違えずに高速入力するのは至難の技です。 TypoScripterならなおさらです。

<C-a>でアルファベットをインクリメンタルする方法

vimでは以下のコマンドで、アルファベットを<C-a>でインクリメンタルできるようになります。

:set nf=alpha

(アルファベットをインクリメンタルする機会はあまりないうえに、数字をインクリメンタルできるほうがクソ便利なので、.vimrcに書くのはお勧めしないです。)

ということでやってみましょう。 キーストロークの合計は31です。愚直に打ち込むより少し長くなってしまいました。

:set nf=alpha<CR>ia<Esc><fd-61>qqylp<C-A>q24@q

ここで:h setをみてみましょう。

f:id:torikatsu923:20210214220858p:plain
:h set
なんということでしょう!settは省略可能ではありませんか! ということで、先程のキーストロークは以下の30文字になりました。

:se nf=alpha<CR>ia<Esc><fd-61>qqylp<C-A>q24@q

マクロ使わずに<C-a>

発想の転換です。 さっきはマクロを使っていましたが、今度はマクロを使わずに、アルファベットをインクリメンタルする方法をやってみます。

:se nf=alpha<CR>ia<Esc>Y25pVGg<C-A>k26gJ

キーストロークは27になりました! アルファベット直打ちに近づいてきました。

g??入力

今度は、g??を使うやり方をやってみます。 g??はRot13変換をしてくれるコマンドです。

詳しくは以下のヘルプを...

:h g??

rot13変換は以下のように、アルファベットを13個後ろのアルファベットに置き換える暗号化方式です。 https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/ROT13.png/640px-ROT13.png

a~mはn~zに変換されます。 これを利用すれば入力回数を減らせそうです。

iabcdefghijklm<Esc>y0g??P

キーストロークは21です。 ついに直打ちよりも少ないキーストロークで入力できるようになりました! さりげなく、rot13を使ってアルファベットを入力できたら、合コンでモテモテ間違いなしですね!

コピペしちゃう

最後の方法はa~zをコピペしちゃう方法ですw

手元でvimを開いている方は以下のヘルプを表示してみてください。

:h <_

...

...

...

f:id:torikatsu923:20210214222936p:plain
:h <_

なんということでしょう!カーソルの2行下にa~zの文字列が存在するではありませんか!

ということで、コピペ戦略を実践してみます。

:h<_<CR>jjYZZP

なんと!!わずか11回の入力でa~zの文字列を入力することに成功しました! タイポの心配もなく、安定してa~zを入力できる最高の方法ですねw

おわりに

今回の記事ではvimでa~zを入力する方法をいくつか紹介してみました。その中で最小キーストロークは11でした。

最後のコピペの方法を初めて知った時、「そんなのありかよwww」ってなりました。 目から鱗とはまさにこのことですね。

もしかしたら、もっと早い入力方法があるかもしれませんね。

それではよいvimライフを!

macでkindleで本読んでみた感想

こんにちは、とりかつです。 私は普段紙の本派だったのですが、たまたまkindleを使う機会がありました。

そこで、kindle使ってみて感じたこととか書いていこうと思います

mackindleアプリは...

 私はmackindleアプリを使って本を読んでいるのですが、この「kindle for mac」が激重です。 どれぐらい重いかというと、ページをめくる際にエンターキーを押してからページが捲られるまでに1秒以上かかります。 また、検索する時は入力が終わってから2~3秒遅れて検索が完了し、検索結果のスクロールは操作してから0.5~2秒ほど遅れます。 快適に本が読めるとは言えません。

アクティビティモニタから検索時のCPU使用率をみてみたところ90%超えでした

f:id:torikatsu923:20210209011724p:plain
Kindleで検索した時のCPU使用率

また、ページをめくった時のCPU使用率は60%を超えていました。

f:id:torikatsu923:20210209011921p:plain
ページをめくった時のCPU使用率

この原因としてmacのOSがあるかもしれません。 私はBigSureを使っているため、もしかしたらまだ未対応な可能性もあります。 (BigSure以外でKindleの動作を試していないので、憶測です。) 今後のアップデートによる改善を期待します。

もしかしたら、kindle for macが遅いのは、amazonさんの「kindle端末買えや」っていう圧力かもしれませんねw

レイアウトが変わる?

どうやら、本によってはページという概念がないものもあるようです。 上手い例えではありませんが、本全体が一つのマークダウンで記述されているイメージです。 それゆえ、ページのレイアウト(テキストが記述されている位置)がページを開きなおすたびに変わります。

私は、紙の本に慣れていて、本を読む時は「本の中盤あたりの右下ぐらいに書いてあったなー」といった感じで、テキストが記述されている位置を、記憶を引っ張り出してくるときのインデックスにするようにする癖があります。 それゆえ、テキストが記述された位置が変更されるという仕様は、紙の本を読む時と違う頭の使い方をしなければならないので少し負担になると感じました。

また、Kindleに限った話ではありませんが、電子書籍では指でページ感を掴むこともできないのでその辺の再適応みたいなステップも必要かなと感じました。

amazon primeの恩恵

ここまでの感想は、Kindleのネガティブな面によってしまいました。しかし、Kindleにもいいところはたくさんあります。 その一つにamazon primeによって読める本が存在することが挙げられます。

しばしば、本の選択は出会いのように語られることがあります。 「書店でぶらぶら歩いていて、たまたま目に止まった本を取り、購入し...」といった感じです。 従来の電子書籍は、目的の本があり、その本のタイトルで検索して購入するといったイメージで、目的の本以外に触れる機会がないように感じていました。 しかし、amazon primeに入っているとprimeによって読める本が常に入れ替わります。 そして、リコメンド欄に表示されます。

この仕組みのおかげで、電子書籍でありながら「本との出会い」という体験を得ることができます。 この点において、kindleは素晴らしいと感じました。

kindle unlimitedはprimeに比べて、より多くの本を読むことができるため、加入すればこの体験のクオリティはより上がると思われます。

おわりに

今回の記事ではKindleを使ってみて感じたこととかをつらつら書いてみました。 Kindleがいいとか紙がいいとかではなく、それぞれに良いところと悪いところがあって、うまく使い分けていくべきだと改めて感じました。

Haskellの門を叩いてみた

こんにちは、とりかつです。

最近、私の中で関数型パラダイムのブームが来ています。 その流れでHaskellを触りました。 そこで、今回の記事はHaskellを触る経緯と、学習していて感動したところについて話したいと思います。

Haskellを触る経緯

冒頭でもお伝えしたように、私の中では関数型パラダイムがブームです。 最近、普段JSとか触ってる自分の耳にも、ReactのFunctionalComopnent最高だぜとかテストしやすいぜとかいう声が聞こえるようになりました。

私は、一度気になったものは、気になって気になってしょうがない性なので、空いてる時間に細々と、関数型パラダイムに入門することにしました。

関数型の入門にあたって、初めはJSとかで関数型の雰囲気を掴もうとしてました。 でも関数型やるならゴリゴリの関数型言語やればいいやんってなって、Haskellの門を叩いてみることにしました。

普段、新しい言語とか触るときは、公式docとかでさらっとやって「完全に理解した」状態にしてました。 Haskellもそうしようと思っていましたが、あえて入門書を買うことにしました。

あえて入門書を買うことにした理由として、関数型パラダイムを基礎から固めたいという思いがあります。 私が今まで触ってきた言語は、java, kotlin, dart,jsあたりで、どれもオブジェクト指向の考え方を持ち越すことができました。 しかし、Haskellは純粋な関数型言語ということでパラダイムが異なります。 思想を基礎から固めるには、しっかりと構造化された情報でインプットを行う必要があると考えられます。 それゆえ、入門書を買うという選択をしました。

幸い、オブジェクト指向とかを触ってきた人向けの「すごい Haskell 楽しく学ぼう!」という本があったのでこの本にしました。

www.amazon.co.jp

まだ全部読み切ってはいないですが、解説がとても丁寧な点と、オブジェクト指向の思想と混乱しそうな箇所がしっかりとフォローされていた点がとても最高な本です。

Haskellで感動したこと

Haskellの感動したところは、数学っぽいことが自然な形でコードに落とし込めるところです。

例えば、10以下の偶数の集合を表現したいときは、以下のようになるかと思います。

{0, 2, 4, 6, 8, 10}

さらに、次のようにも書くことができます。

{ x | x≤10, xは偶数 }

ここで、10以下の偶数のリストをHaskellで作ると、次のようになります。

[ x | x <-[0..11], x `mod` 2 == 0 ]

実際に実行してみると、確かに[0, 2, 4, 6, 8, 10]が出力されます。

f:id:torikatsu923:20210127223508p:plain

集合とリストは異なりますが、集合の表記とコードが非常に似ています。

このように非常に自然な表現でコードに落とし込むことができるところがHaskellのいいところだなと思います。

おわりに

まだ学習し始めたばかりで、Haskellのいいところを全て吸収できたわけではありません。 ですが、これは見方を変えると、入門したてにもかかわらず、いい!って思えるところが見つかるプログラミング言語だといえます。

まだHaskell触ったことないって人は、ぜひHaskellを触ってみてはいかがでしょうか。

Logicool mx ergoを導入してみて

お久しぶりです。 とりかつです。

先日、Logicool mx ergoというトラックボールを導入ました。 今回の記事は、その使用感とデスク環境のアップデート状況について話をしたいと思います。

f:id:torikatsu923:20210124231934j:plain

また、以前、以下の記事で私のデスク環境を紹介させていただきました。 もしよければご覧になってください。 torikatsu923.hatenablog.com

目次

  • logicool mx ergo導入の経緯
  • 実際に使ってみて
  • 置いてみて(見た目)
  • おわりに

logicool mx ergo導入の経緯

私は、ITエンジニアとして働いており、その職の性質上机に向かい続ける時間が長くなる傾向があります。 そこで、少しでもQOLを向上させるために、デスクまわりの環境が快適になるよう様々なアイテムを導入してきました。

私のデスク環境を整えていく方針として、自身の生産性に対して投資をするというものがありました。 また、別の軸として、PC操作をキーボードで完結させるというものもありました。

それゆえ、chromeにvimiumという拡張機能を導入し、マウスレスブラウジングを実現したり、 vimを導入して黒い画面からなんでも操作できるようにするみたいな工夫をしてきました。 chrome.google.com

f:id:torikatsu923:20210124232305p:plain
黒い画面の見た目もいろいろいじりました

それゆえ、トラックボールの導入はPC操作をキーボードで完結させるというポリシー登坂するため、導入について非常に悩みました。 これについて、会社の先輩の先輩に相談したところ、「マウスとキーボードのいいとこ取りして共存するのもいいかも」という話をいただきました。 たしかに、真に求めるべきものは効率であり、先入観や自身の価値観で便利なものを導入しないのことは、かえって作業の効率を落としかねないです。

例えばvimでインサートモードの時に、カーソル以降の文字を全て消したい時は、esc→$→xなんてせずに、インサートモードのままctrl+kした方が効率が...(ry おっと、だれかがきたようだ...

こんな経緯で、トラックボールの導入を決意しました。

一口にトラックボールには様々な種類があります。 その種類の多さゆえに、アイテム選びには非常に迷いました。

そこで、以下の条件で絞り込みをしました。 - 所持しているデスク周りのアイテムと親和性の高いデザイン - Bluetoothで接続先を複数設定できる - 机に対するグリップ力

この条件でいろいろ見ていった結果Logicool mx ergoに辿り着きました。 www.logicool.co.jp お値段は1.4万円ほどで非常にリーズナブルな価格帯です(?)

私にとっての決め手は以下の4つです。

  • 色が黒色で、所持しているHHKBと相性がよかったこと
  • 角度調整が可能なこと
  • Bluetoothで充電回数が極端に少ないこと
  • Logicoolというブランドの信頼性

実際につかってみて

最初は、トラックボール自体、使うのが初めてだったので、新しい操作にかなり戸惑いました。 しかし、2、3日触っていたらかなり手に馴染みました。

トラックボールの設定で、スクロール速度を最高にしました。 さらに、Mac本体の設定でポインタの移動速度を最速にしました。

f:id:torikatsu923:20210124234604p:plain
スクロール速度の設定

その結果爆速ポインタ移動が実現しました! ディスプレイの移動も親指で少し回すだけで端から端まで移動できちゃいます! 最初は早すぎて「使えるか!」とか思ってましたが、今ではMacトラックパッドのポインタ移動がとても遅く感じてしまう体になってしまいました。 また、トラックボールの滑り具合やボタンのクリックした時のフィードバックはとても快適です。

mx ergoを購入する前の懸念点として、机に対するグリップ力がありました。 折角性能のいいトラックボールでも、固定しずらければ、デスクのフォームが崩れたりかえって疲れてしまったりする原因になります。 ですが、この心配は取り越し苦労でした。 mx ergoの底面にはゴムがついており、このグリップ力が高いおかげで、ズレとは無関係の、快適な操作を提供してくれました!

mx ergoのすごいところは他にもあります。 それは角度調整が可能だというところです。 mx ergoは本体の角度を、0度と20度の2種類に調整できます。

f:id:torikatsu923:20210124235656p:plain
https://www.logicool.co.jp/ja-jp/products/mice/mx-ergo-wireless-trackball-mouse.910-005183.html?crid=7より
f:id:torikatsu923:20210124235704p:plain
https://www.logicool.co.jp/ja-jp/products/mice/mx-ergo-wireless-trackball-mouse.910-005183.html?crid=7より

この20度という角度がとても絶妙な角度なのです。 絶妙であると考えられる理由として、鉛筆の持ち方との共通点が考えられます。

トンボ鉛筆によると正しい鉛筆の持ち方の定義について以下のようにあります。

「5本の指の関節(15箇所)と、手首の関節を自由に屈伸、屈折することができ、手と腕に余計な力が動くことなく、筆記具を自在に動かしてあらゆる基本線を思うように書ける持ち方」と定義されています。 tombow-ippo.jp https://tombow-ippo.jp/assets/img/howto/point03.png

つまり、私たちの手が最もリラックスした状態が20度という角度なのです。 これよりmx ergoは、手が疲れないよう、非常に考えられた設計がされたトラックボールであるといえます。

実際に使ってみて、ペンを握るような感覚で非常にリラックスして作業をすることができました。

デスクにおいてみて(見た目)

このmx ergoですが、Bluetoothのおかげで机の上がとてもシンプルになりました。

f:id:torikatsu923:20210124231934j:plain

HHKBのコンパクトさと相俟って、デスク上の雑念が存在しない空間作りに貢献してくれているのがわかると思います。 落ち着いたマットな黒色も、高級感を演出していて気分がいいです。

おわりに

今回の記事では、logicool mx ergoというトラックボールを導入した経緯とその使用感についてお話をさせていただきました。 それでは快適なデスクライフを!

JSの+について考える

こんにちは、とりかつです。 最近JSのコードを読むことが多いです。 とあるリポジトリのJSのコードを読んでいたら以下のような文がありました。

var a = +new Date();

+new Date()...??? なんじゃこりゃ...

と言うことで今回の記事ではjsの+について軽く調べてわかったことをまとめていきます。

+の種類

+ 記号を使用する演算子はいくつかの種類があります。

演算子 名前
+ 単項正値演算子
++ インクリメント
+ 加算
+= 加算代入

それぞれ見ていきます。

単項正値演算子

構文は以下のようになります。

+ ○

この記事の冒頭で出てきた+ は単項正値演算子です。 オペランドが数値以外の場合、数値に変換する役割を持っています。

+ 10 // -> 10

new Date()は数値変換するとミリ秒を取得できます。

f:id:torikatsu923:20201204005839p:plain

なので、冒頭のコードはミリ秒を取得するコードになります。

f:id:torikatsu923:20201204010021p:plain

インクリメント

インクリメントはオペランドに1を加算して返します。 インクリメントはオペランドの前後どちらにもつけることができます。 ですが、動きは異なります。

前置した場合は、インクリメントしてから値を返していることがわかります。

f:id:torikatsu923:20201204010511p:plain

後置した場合は、値を返してからインクリメントしていることがわかります。 f:id:torikatsu923:20201204010657p:plain

加算

オペランドを足し合わせた値または文字列連結した結果を返却します。

f:id:torikatsu923:20201204011213p:plain

オペランドの型が違う時、JSによって暗黙の型変換が行われます。

f:id:torikatsu923:20201204011317p:plain

暗黙の型変換には優先順位?みたいなものがあります。

f:id:torikatsu923:20201204011608p:plain
対応表

引用:https://jsprimer.net/basic/implicit-coercion/

また、加算演算子は左から右に評価されます。 なので、式の項の順序(これは正確な言い回しではないかもしれないです。)によって結果が変わります。 これ覚えとくと、いつか何かに使える気がします。

f:id:torikatsu923:20201204011838p:plain

加算代入

右辺のオペランドを変数の値と加算し、結果を変数に代入します。

f:id:torikatsu923:20201204012142p:plain

加算代入は代入系の演算子で優先度が3です。 対して、加算、減算の優先度は14、剰余、乗算、除算の優先度は15です。

なので+= ( 10 - 3 ) みたいにかかなくても良さそうです。

f:id:torikatsu923:20201204015351p:plain

おわりに

ここまでJSの+についてまとめてきました。 +に限らずJSの演算子による表現は幅が広いです。

f:id:torikatsu923:20201204012856p:plain

(どこでこれ使うかわかりませんがこんなこともできちゃいます)

また、新しい発見があったらまとめてみたいなと思います。

Vueで直接DOM生成してクラス割り当てようとしたらできなかった話

こんにちは、とりかつです。 今回は、VueでDOMを生成してクラスを割り当てようとしたら、スタイルが適用されなくてハマりました。 そこで、ハマリから得られた知見を共有したいと思います。

やろうとしていたこと

SFCで以下のようなことをしようとしていました。 付与するクラスinner_elementのスタイルは、SFC内の<css scoped>で定義してあります。

  1. mounted()のタイミングで動的に<span></span>を生成 1 生成した要素にnewElementというクラスを付与
  2. $refsの子要素として追加

コードにすると以下のようになります。

mounted() {
  const el = this.$refs.hoge as HTMLElement
  const newElement = document.createElement('span')
  newElement.className = "inner_element"
  el.append(newElement)
}

いざ実行してみると<span>はしっかり追加されており、class="inner_elementも確認することができました。 しかし、スタイルは適用される気配がありません。 うまくいかない原因はなんでしょうか。

なんでVueでVanilaJS使ってDOMを追加しようとしとるねんってことはあえて考えないようにしましょう。

VueのCSSが読み込まれるタイミング

スタイルが適用されなくて悩んでる時にscoped cssの仕様についてふと思い出しました。

scoped 属性をもつ <style> タグを利用するとき、その CSS は現在のコンポーネントの要素にのみ適用されます。これは Shadow DOM のスタイルのカプセル化に似ています。いくつか注意点がありますが、polyfill は必要ありません。PostCSS を使用して以下を変換することによって実現しています[^1]

同ページには以下のようなスニペットも掲載されていました。(一部抜粋)

example[data-v-f3f3eg9] {
  color: red;
}

要約すると、SFCのスコープ付きCSSのクラス名はコンパイルされて、.inner_element.inner_element[data-v-jfoieh]のようになるといった感じです。

では、CSSコンパイルされるタイミングはいつでしょうか。 以下はVue.js公式ドキュメントに掲載されていたライフサイクルの図です。[^2]

f:id:torikatsu923:20201127210526p:plain
Vueライフサイクル

この図からはSFCテンプレートがコンパイルされるタイミングがcreated()beforeMount()の間であることが読み取れます。 ですが、CSSコンパイルされるタイミングは読み取ることができませんでした。 推測ではありますが、この間でCSSコンパイルされている可能性がありそうです。

ここで気づいたのですが、CSSコンパイルされるのと同時にコンパイルによって付与されたID的なものがVueによって生成されるテンプレート内の要素にも付与されるようです。 以下のようなSFCを考えます。

<templete>
  <button class="button">
</templete>
<style scoped>
  .button {
    /* some style */
  }
</style>

Vueによってマウントされたとき、.button.button[data-v-horekjkd]となるとします。 このとき、Vueによって生成されるbuttonは次にようになります。

<...>
  <button data-v-horekjkd class="button"></button>
</...>

このようにVueによって生成されたIDはHTMLのタグに反映?されるようです。

実際にインスペクタを見てみるとv-data-.....buttonに付与されていることがわかります。

f:id:torikatsu923:20201127203001p:plain
buttonタグ内にdata-v-24921c38が存在していることが確認できます。


少し冗長になってしまいました。 ここまでわかったことをまとめます。

  • スコープ付きCSSはVueによってコンパイルされ、一意なIDが付与される
  • IDはテンプレート内のタグにも付与される
  • CSSコンパイルされるタイミングははっきりとわからない
  • テンプレートはcreated()beforeMounted()の間でコンパイルされ、このタイミングでIDが付与される

CSSコンパイルされるタイミングをはっきりと掴むことができませんでした。 しかし、CSSコンパイルで付与されるIDがテンプレート内のタグに付与されることと、テンプレートがコンパイルされるタイミングは明らかになりました。 これによりmounted()で生成した要素にスタイルが付与されなかったことの説明がつきそうです。

CSSコンパイルされるタイミングは追々調べようと思います。

まとめ

当初、私はmounted()<span class="inner_element"></span>を生成していました。 しかし、この時点でSFCCSSクラス名はコンパイルされ.inner_element[v-data-hgoejdklgha]のように変化していました。 また、テンプレートのコンパイルも終了していました。 スタイルを適用するには、クラスに付与されたIDをテンプレートの要素にも付与する必要がありましたが、私の生成したspanはIDが付与されていませんでした。 これによってスタイルが適用されなかったと考えられます。

おわりに

ここまで、Vueのmounted()でVanilaJSによって生成した要素にスタイルが適用されない原因について考えてきました。

思い返してみると... Vueでクラス名をバインドする際は、

:class="{classA: true, classB: false}"

みたいに書く必要がありました。 いままで、以下のように書けたらいいのにな。なんだか気持ち悪いなとか思ってました。

$refs.class = "classC"

ですが、テンプレートがコンパイルされるタイミングでIDが付与されることを考慮すると、 あらかじめクラス名をバインドしておいて、vueのdata等の状態の切り替えで、クラスの付与のアクティブ/パッシブを切り替えに納得が行きました。


[^1] https://vue-loader-v14.vuejs.org/ja/features/scoped-css.html [^2] https://jp.vuejs.org/v2/guide/instance.html

JavascriptのIIFEについて考える

こんにちは、とりかつです。 最近、Javascriptで以下のようなコードを見かけました。

(function() {
  console.log("hogehoge");
})();

調べていくとこれはどうやら即時実行関数式(IIFE: Immediately Invoked Function Expression)[^1]というものだそうです。 私はぱっと見でIIFEの書き方が理解できませんでした。 なので、今回の記事ではこのIIFEを完全に理解したいと思います。

原点回帰

最初に関数の定義について振り返ります。 JSで関数式は以下のように定義, 実行できます。

// 関数の定義
var a = function() {
  return "done";
}

// 関数の実行
a();

aの後ろの()は関数呼び出し演算子です。 関数呼びだし演算子の構文は...(/* 引数 */)です。[^2]

関数の実行の流れは以下のような感じかと考えました。

  1. aが関数の実態と置き換わる
  2. 関数が実行される
  3. 関数の返り値の"done"に置き換わる

関数実行のイメージ
関数実行のイメージ
(もしかしたらこの説明は少し語弊があるかもしれません。あくまでイメージ程度で捉えていただければと思います。)

関数の実行時に変数が関数の実態と置き換わるイメージから、関数の定義と同時に関数の呼び出しをおこなうことができそうな感じがします。 やってみます。

関数を即時事項してみる
関数を即時実行してみる

... だめでした。 エラーにはUncaught SyntaxError: Function statements require a function nameとありました。 どうやら現在の書き方では関数式ではなく関数定義文として認識されていて、関数名が必要だと怒られているようです。

関数の定義を関数式として認識させる

ではどうしたら関数式として認識してもらえるようになるのでしょうか。 私は関数式という名前から関数を式として認識させればいいと考えました。 具体的には+, -, !のような演算子を関数の定義の前につければいいといった感じです。

プログラミング言語において式はオペレータとオペランドから成り立っています。 たとえば以下のような式を考えます。

1 + 6

この式では16オペランドで、+がオペレータです。 JSで関数定義を式として認識させるためには、JSエンジンに関数の定義がオペランドだよと教えてあげられれば良さそうです。

なのでオペレータを使って関数定義をオペランドとして認識できるようにします。

// 例
+ function() {
  return "done";
}

実行してみると...

関数をオペランドとして認識させる
関数をオペランドとして認識させる

うまくいきました。 現時点では関数呼び出しはしていないのでNaNが返ってきていることがわかります。 次に関数呼び出し演算子を使って関数を呼び出してみます。

関数の即時実行
関数の即時実行
うまくいきました! これで関数を定義して即時実行することができるようになりました。

グループ化演算子を使用する

関数の定義を式として認識させるためには、関数の定義がオペランドであることを明示すればよさそうでした。 JSのグループ化演算子(...)は「式での評価の優先順位を制御」[^3]する役割をもっています。

グループ化演算子は中に式が入ることが想定されています。 これよりグループ化演算子の中で関数を定義すれば、その関数は関数式として扱われると考えられます。 実際にやってみます。

グループ化演算子を使って関数を定義する
グループ化演算子を使って関数を定義する
グループ化演算子を使って関数を式として定義することができました。

もちろん、即時実行も可能です。

グループ化演算子を用いて関数を即時実行する

グループ化演算子を使う理由

ここまで、演算子を用いた関数式の定義と関数の即時実行について考えてきました。 私がIIFEを理解できなかったポイントは、なぜグループ化演算子を用いるのかという点です。 なので最後になぜグループ化演算子を用いるのか考えていきます。

グループ化演算子は静的なスコープをもっているようです。 そのため、以下のケースではエラーを吐かれます。

グループ化演算子ありの場合

このようにグループ化演算子内で宣言する前の変数にはアクセスできないようです。 これは名前空間を切り分けることに役立ちそうです。

実際の開発では複数人で開発を進めていきます。さらにさまざまなパッケージを使用することが考えられます。 なので、名前空間は非常に重要となってきます。

以上より、JSファイルが読み込まれた際に名前空間を切り分ける目的でグループ化演算子が用いられていると考えられます。 逆に名前空間を切り分ける必要がないばあいに関数を即時実行したければ使用する演算子はなんでもいいかもしれません。

おわりに

今回はJSのIIFEを切り口にJSの関数について考えました。

個人的に、演算子を用いることで関数を式として認識させるという部分は大きな再発見でした。

参考