ちなみに

火曜日の空は僕を押しつぶした。

Fear Of Missing Out in Business

FOMO (Fear Of Missing Out) はビジネスのシーンにおいても問題になっているのではないだろうか。

たとえば Slack の画面をつねにディスプレイに表示したいという話があるが、リアルタイムでみないといけないメッセージなんてほとんどない。むしろリアルタイムでみないといけないメッセージが存在するということは、そこに非効率が潜んでいる。リアルタイムのコミュニケーションが必要なら別の手段を用いた方がいいだろう。

情報を見逃すということはそれほど問題だろうか。僕はそうは思わない。

本当に必要な情報というのはその場でみなくても、おそらくなんらかの手段で目に触れることになる。返信が必要なものはメンションされているだろうから、メンション一覧を見るだけでよい。全ての情報を見ようとすることで、本当に必要な情報を見逃していないだろうか?

突発的に発生した大喜利に参加できないという話はあると思うが、仕事しろ。僕だって乗り遅れたら悔しくはある。

諦めて Slack や Eメール の画面を非表示にしよう。意外と困ることはない。

パターン認識

最近、意識が高まって LeetCode を一日一問ずつやっています。 正直、Easy でもだいぶ苦戦していて、基礎の出来てなさに凹む毎日です。

ところで、現代では ChatGPT というSFチックなサービスが存在します。何かを学ぶときに補助してもらうことで、知の高速道路をより素早く進むことが出来るようになりました。 LeetCodeでの練習でいうと、うまく書けなかったなというときにコードをシンプルに書き直してもらうと学ぶところが多々あります。

今日は本当にクソみたいなコードを書いたので、ちょっとでもヒントを得ようと書き直してもらったのですが、あまりにシンプルなコードになってひっくり返りました。 最初みたときにハルシネーションだろって思ってしまったのですが、よく読むとすごく正しい。

自分は与えられた問題の情報を愚直にコードに落とし込んでしまっていて、今回の問題の本質 = 一定のパターンがあることに気付いていませんでした。 GPT-4o は自分の書いたクソコードをみただけで、そのパターンに気付いてコードに落とし込んでくれたのです。

問題解決の糸口として、なんらかのパターンがないかというのは普段は考えている気がするけど、こういう問題形式でプログラミングするときには頭が回ってなかったので、すごくハッとさせられたのでした。

(もちろん本当のところは同様のコードを大量に見せられていて、ベストな回答を知っていたということだとは思うのだけれど)

おまけ

問題は与えられたローマ数字の文字列を数値に直すというやつでした。

自分の書いたクソみたいにナイーブなコードがこれ。

func romanToInt(s string) int {
    num := 0
    rs := []rune(s)
    for i := 0; i < len(rs); i++ {
        r := rs[i]
        switch r {
        case 'I':
            if i+1 < len(rs) {
                n := rs[i+1]
                if n == 'V' {
                    num += 4
                    i += 1
                    continue
                } else if n == 'X' {
                    num += 9
                    i += 1
                    continue
                }
            }
            num += 1
            continue
        case 'V':
            num += 5
            continue
        case 'X':
            if i+1 < len(rs) {
                n := rs[i+1]
                if n == 'L' {
                    num += 40
                    i += 1
                    continue
                } else if n == 'C' {
                    num += 90
                    i += 1
                    continue
                }
            }
            num += 10
            continue
        case 'L':
            num += 50
            continue
        case 'C':
            if i+1 < len(rs) {
                n := rs[i+1]
                if n == 'D' {
                    num += 400
                    i += 1
                    continue
                } else if n == 'M' {
                    num += 900
                    i += 1
                    continue
                }
            }
            num += 100
            continue
        case 'D':
            num += 500
            continue
        case 'M':
            num += 1000
            continue
        default:
            panic("invalid rune")
        }
    }
    return num
}

ChatGPT が書き直してくれたのがこれ。

func romanToInt(s string) int {
    // ルーンとその値のマッピング
    romanValues := map[rune]int{
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000,
    }

    num := 0
    rs := []rune(s)
    for i := 0; i < len(rs); i++ {
        // 現在のルーンの値
        currentValue := romanValues[rs[i]]

        // 次のルーンが存在し、かつその値が現在のルーンの値より大きい場合
        if i+1 < len(rs) && romanValues[rs[i+1]] > currentValue {
            num -= currentValue
        } else {
            num += currentValue
        }
    }

    return num
}

Hyper Key べんり

最近、Hyper Key という概念を知った。

概要

masOS だと Control+Alt+Shift+CommandWindows だとControl+Alt+Shift+Win を同時に押すことを言うようです。 現代では失われた物理的な Hyper Key に代替しようということだと思ったけど経緯はあんまり分かっていない。

これの何が便利かというと、システムやアプリケーションのショートカットキーと被りにくいのである。 グローバルなショートカットキーを設定するときに、被らないように悩まなくて済むのが嬉しい。

もちろん本当に同時押しするのは馬鹿げているので、特定の1キーを押すことで済むようにする。 人気なのは Capslock を置き換える方法で、合理的だけれどちょっとかわいそう。

やりかた

macOS だと Karabiner-Elements を使うのが簡単でしょう。

karabiner-elements.pqrs.org

Hyper Key っていうずばりの名前のアプリもあるけど、Karabiner-Elements がすでに入っている場合はわざわざ単体のアプリを入れるまでもないでしょう。

Windowsはよく分かってません。

用途

自分の場合はよく使うアプリケーションを呼び出すショートカットキーとして Hyper Key を使っています。 元々はそれぞれ被らないように適当なキーを当てていたけど、全部置き換えてしまった。

アプリケーションの頭文字にすると覚えやすい。一例としては以下の感じで Hyper Key を で表現した。

アプリケーション キー
VSCode +V
Arc +A
Slack ✦+S
iTerm2 +T
Obsidian ✦+O

さらに自分の場合はキーボードのレイヤ3に配置することで指の動きを最低減にしている。

余談

アプリケーションを呼び出すショートカットは Raycast で設定している。 一度押すとそのアプリケーションがアクティブになって、もう一度押すと非アクティブになって画面から消えてくれる。 もちろん起動していない場合は起動してくれます。 現在の状態を把握してなくてもとにかく最悪2回押せば手前に来てくれるのでとてもべんりです。

設定の Advanced に Hyper Key の表示に関する設定があるのでこれを有効にしておくと見やすくなる。

www.raycast.com

AppleScriptでSlackの特定チャネルに定型文を投稿する

Slackの特定のチャネルを開いて定型文を入力したい。具体的にはAPIでは発火できないスラッシュコマンドを実行したい。

特定のチャネルを開く簡単な方法は、Slackアプリに用意されている Deep Link を使うことです。 この場合は slack://channel を使うと目的を達成できます。試すには open slack://channel?team=<チームID>&id=<チャネルID> みたいにすると良い。 IDはWeb版で目的にチャネルを開くとURLに含まれているので、2つ合わせてゲットするにはそこからが速いかも。

AppleScript でこれを開くにはいくつか方法がありますが、今回は System Events を使います。 (System Events についてのドキュメントを発見できなかったのだけれど誰か教えてください。)

tell application "System Events"
    open location "slack://channel?team=<チームID>&id=<チャネルID>"
end tell

System Events を使ったのは文字入力をするための布石で keystroke を使っていきます。 keystroke "Hello" のようにすると、キーボードから Hello と入力したのと同様の結果が得られます。

tell application "System Events"
    keystroke "Hello"
end tell

ただしここで問題が生じます。キーストロークなので日本語をそのまま与えてもおかしなことになります。 キーボード操作を考えても、IMEをオンにして、文字を入力、変換して、確定という操作をしているので当然です。

そんな面倒なことを再現しないといけないのかというとそうでもなくて、クリップボードを使うと実現できます。

set the clipboard to "日本語でこんにちは"

tell application "System Events"
    keystroke "v" using {command down}
end tell

using {command down}Cmd を押しながら別のキーを押すを実現できます。 これで Cmd+v をして貼り付けすることが出来ます。

これらを組み合わせると以下のように特定のチャネルに定型文を投稿することが可能です。

ここでは ジョブカン のスラッシュコマンドを実行しています。 メッセージも入力したいので引数を受け取れるようにしました。

on run argv
    set message to item 1 of argv
    set the clipboard to "/jobcan_touch " & message

    tell application "System Events"
        open location "slack://channel?team=<チームID>&id=<チャネルID>"
        delay 1

        keystroke "v" using {command down}
        delay 0.5

        keystroke return
    end tell
end run

これで人力でやっていたチャネルを開いて、入力して、投稿の3ステップの操作が1ステップで完了できるようになりました。

べんりですね。

能楽堂で音楽を聴く

argerich-mf.jp

別府アルゲリッチ音楽祭の催しの1つで、平和市民公園能楽堂 で行われたチェロとピアノの演奏会に行ってきた。

生でチェロを聴くのはもしかしたら初めてかもしれない。

能楽堂は別に音響に特化したわけではないと思うので、めちゃくちゃ良い音で聴けるわけではないけど、やはり生演奏というのは響くものがある。 席もめっちゃよくて二人の手元がよく見える位置で目でも楽しむことができた。

アンコールの朧月夜が特によくて、ピアノの編曲がすごく好きだった。

Keep In Touch

どうやら一般的には人との関係はメンテナンスしないと壊れてしまうらしい。

自分は友達や知り合いにたいしてこちらから連絡をほとんどしない。 友達だと思っている人達は連絡を取らなくてもつながっていて、何かあったときだけ連絡すればすぐに元の関係に戻れると思っていたからだ。 特にSNSのようなものが普及していつでも連絡が取れるようになってからは顕著で、SNSでつながってなかったとしてもなんらかで連絡取れるやろと思っている。 物理的に会うなんて考えもしていない。

しかし、どうやら幻想だったようで、友人達とはどんどん疎遠になってしまっている。 まあたぶん連絡したらなんかなるとは思いつつ、昔よりもやり取り自体がかなり減ってしまっている。

特に何かあった訳じゃないのだけれど別府市にやってきて、物理的に会う機会がほぼ無くなったことでふと不安に思ったのであった。

GitHub Copilot Chat 舐めていた

marketplace.visualstudio.com

GitHub Copilot と直接会話できる Copilot Chat 、皆さん使ってますか? 私は最近まともに使い始めました。

Copilot と言えば補完だけだと思っている人、以前ちょっとだけ触れて使えないと思った人(僕です)、いまのバージョンをもう一度触ってみてください、めっちゃ便利になっている。

www.youtube.com

この動画が出来ることを追いかけるのに良さそうなので見てください。

ベースモデルがGPT-4に変わったりとかいろいろ変化はありますが、便利なのは ParticipantContext の概念が入ったことだと思います。

Participantは @workspace みたいなやつで、Chat-GPTにおける GPTs みたいなやつ。例えば @workspace ならいま開いているプロジェクトについての情報をローカルで集めてくれて俯瞰的でかつトークン制限を超えた回答ができる。 さいきん発表された Copilot Extension などもこの仕組みにのっかっていそう。

Context は #file:REAME.md とか #selection みたいな感じで特にここを見てくれというのを明示的に伝えられる。これによって意図していない回答が得られる率を大幅に減らせている。

code.visualstudio.com

ドキュメントがちゃんと更新されているのでここを読むと一望できそう。

また、英語が苦手勢としては日本語でプロンプトを入力するのが面倒な時がある。そういうときには VS Code Speech を使うと音声入力できるので重宝している。 日本語だと精度がそこまででもないのと、日本語の中に英語を交ぜたりできないのが玉に瑕。3S 原則 を守っていたらそんなに長文にはならないのでギリ使えている。

marketplace.visualstudio.com

今後はどんどん人間の作業が減っていくのは間違いないので、コードの詳細よりもっと大きな視点で考えられるように意識を変えていこう。