トラックボールのチャタリングを直した

ずっと使っているトラックボールLogicool の M570 が例のごとくチャタリングするようになった。

接点復活剤(コンタクトスプレー)をスイッチに差すことで直るという記事を読んだので試してみた。

上記記事のとおり、分解してシュッと一吹きしてカチカチしたら直ったみたい。こんなに簡単ならもっと早くにやればよかったわ!

f:id:ryskosn:20200903171040j:plain

会社で使っていた分を自宅に持って帰ってきたので自分用のが 2 つあり、妻も 2 つ持っているので我が家には合計 4 つのトラックボールがある。今回直し方がわかったので、もうチャタリングが発生しても何も心配はいらない。

ただ、接点復活剤の効果はどれくらい持続するのかな〜。

最近の食卓

毎日ご飯がおいしい。

豚肩ロースの角煮的なやつ。

f:id:ryskosn:20200903191120j:plain

焼きそば。

f:id:ryskosn:20200801122808j:plain

買ってよかったもの

何となく紹介。他にも何か思い出したら書いてみようと思う。

Lite Grip グローブ

SHOWA の軽作業用ゴム引きグローブ。これはとても良いものなのでおすすめです。

ライトグリップ | SHOWA

2 年前くらいに引越しのときにホームセンターで購入した。確か 300 円くらいだったかな。スーパーマーケットでも販売されているのを見たことがあるのでエントリーラインというか、お安めの商品なのだと思う。

軽くてゴム引き系の中では薄めのつくりなので指先を使う作業でもまぁまぁ大丈夫。グリップは強力に利く。重いものを持つときやカッターを使う作業をするとき、ダンボールを解体して畳んで縛るときなどに使っている。あと、瓶のフタを開けるときにも活躍しているかな。手先が「滑らない」だけでこんなにも力強く感じるのかと驚くと思う。

大げさかもしれないけれど、個人的にはまるでパワードスーツを着たかのような感覚である。着たことないけれど。

f:id:ryskosn:20200828235829j:plain

ダンボールを折りたたんで縛るとき、分厚いものだとただ折りたたんだだけでは元に戻ろうとする力が強くてうまく縛れないから、柱の角に押し当てて既存の折り目と垂直方向に新たな折り目をつけて言うことを聞かせる(?)のだけれど、そのときにこのグローブを着用しているととても楽に進められる。何なら柱の角を使わずに両手で掴んで自力で折り曲げることすら可能。

あと、そうやって畳んで縛ったダンボールを捨てるとき、縛った状態のサイズが大きいと抱えるのが大変な場合もあるけれど、これがあれば一時的には端を片手で掴んで運ぶこともできる。ゴミ捨て場までのルートでドアを開けたりエレベーターの乗り降りなどが発生する場合はとてもやりやすくなる。もちろん両手で持つことだけを考えても「滑る心配が皆無だとこんなに楽なのか」と思うこと間違いなし。

手のひら側は通気性がない(ゴムだから)ので、ずっと着用していると蒸れるのでその点は要注意です。

サバイバルガイド本

書店で見かけて買ってみた。

こういうライフハック紹介本の類はもうすっかりご無沙汰だったけれど、こちらはなかなか良かった。著者と同様の属性を持っている人はもちろん、そうでない人にとっても参考になる部分がたくさんあるのではないかと思う。

序文に

この本には「いかに生き延びるか」、すなわち何度転んでも、何度落とし穴に落ちても、どうにか立ち直るための再起の方法以外、何ひとつ記載されていないのです。

とあるとおり、うまくできないことが多い状況であってもどうにかしてうまく(そして快適に)やっていくにはどうしたらよいか、ということが 47 項目にわたって書かれている。

11. 「1 日 1 箱」で習慣を固定しよう という項目で紹介されていた「エブリデイボックス」は Yodobashi.com で買えたので、早速取り入れてみた。

ヨドバシ.com - トラスコ中山 TRUSCO TSK-910TM [スケルトンカラーコンテナ スケルコン 9L 透明] 通販【全品無料配達】

ほどよい大きさでなかなか使い勝手が良いよ。

f:id:ryskosn:20200906202940j:plain

ようやく梅雨明け

気づけば前回の更新から 1 年が経っていた。 こちらは何とか元気にやっています。

最近「水を 2L 飲む」という取り組みを始めた。

別に何も難しいことはなく、ただ飲むだけなのだけれど、なかなか完遂することができない。

スクワットや腕立て伏せなどの簡単な筋トレも毎日やるようにしていて、こっちは習慣として定着したかな。

今日の夕食はシンガポールのローカルフード、バクテー。豚のスペアリブをにんにくと各種スパイスで煮込んだもの。シンプルだけれどおいしい。

元はマレーシアの料理で、マレーシアの方はもっと薬膳っぽい感じでスープの色も違うらしい。

f:id:ryskosn:20200802195249j:plain
バクテー(肉骨茶)

シンガポールに行ってきた 2

続き。

今回は木曜の夜に羽田空港を出て、金曜の早朝にチャンギ空港に着く便を利用した。 荷物を預け入れるのも初めてで少しドキドキした。

機内で入国カードが配られるので記入する。

上記のような記入例がガイドブックにも載っているので、それを見ながら書くつもりでいたのだけれど、この入国カードを提出するイミグレーションでのやり取りを思い出すと「実際はそこまで厳密な記述は求められていないのではないか」と思えてきたので、今回は記入例を参照せずに自分の解釈に基づいて書いてみることにした。何ごともチャレンジである。

英語圏の人なら迷わないのだろうけれど純ドメスティックな日本人からすると、まず最初の自分の名前を書くところで「どう書くのが正解なのか?」が気になってしまう。

  • 名 -> 姓の順でいいの? 姓 -> 名でもいいんだっけ?
  • 記入欄が複数行あるということは姓と名で改行した方がいいの?

とか。

今回は名 -> 姓の順で、改行せずに空白を挟んで続けて書いてみた(記入例だと改行してる)。

あと滞在先の名称と郵便番号。

ホテル名称のスペルはうろ覚えだし、住所や郵便番号は全く覚えていないので、これまでであればメモ帳やプリントアウトしたバウチャーなどをバッグから取り出して、一文字も間違えないように確認しながら記入したと思う。

でも、イミグレーションの担当者がホテル名のスペル間違いに気づいたとして訂正を求められるか、というと恐らくそんなことはない。

この入国カードを出すときに実際にそのホテルを予約していることを証明するものの提示を求められることもないので、どのホテルの名前を書いたとしても問題にはならないだろう。(明らかにシンガポール国内にはないと思われる名称を書いたら止められるのかもしれない)

だから、うろ覚えのまま微妙に間違ったスペルでホテル名を記入し、郵便番号は確か空欄のまま提出した。結局それで何の問題もなかった。 きっと、名前のスペルやパスポート番号を間違えていたらまずいのではないかと想像した。

そんなこんなで、あとは機内で寝たり起きたりしつつ過ごしていたらシンガポールに到着した。

イミグレーションを通過して預け入れ荷物を受け取り、空港の到着ロビーに出たところでベンチに腰掛けて小休止。

両替

現金の両替については、市内のおすすめ両替所を教わっていたので空港では必要最小限の額だけ替えることにした。

3,000 円と伝えるとカウンターの兄ちゃんに「three thousand...(ププッ)」と笑われたけれど気にしない。こちらはもっといい選択肢があるのだ。

ちなみに、羽田空港で両替するのはおすすめできない。空港に着いてすぐのところにある Travelex の両替所が最も不利なレートを提示している。同じフロアにある SMBC 信託銀行の両替所と比べても 2 円くらい違ったので驚いた。同じ羽田空港の中でも出国エリアにあるみずほ銀行の両替所の方がよいレートだった。

以下、6 月 6 日時点で提示されていたレートから計算した。

  • Travelex: 1 SGD あたり 87.82 円、10,000 円を替えると 113.87 SGD になる
  • SMBC 信託銀行: 1 SGDあたり 85.03 円、10,000 円を替えると 117.61 SGD になる
  • みずほ銀行: 1 SGD あたり 84.15 円、10,000 円を替えると 118.84 SGD になる

現地で英語でやり取りすることを考えると羽田空港で両替を済ませたほうが安心だという人の気持ちもわかるけれども、実際は一言も喋らなくても現金をずいっと差し出すだけでもちゃんと両替してもらえるから、シンガポールについてからチャンギ空港で替えた方がいいのではないかなと思う。

羽田空港の Travelex と比べると約 10 % 違う!

証拠

適当なことを書き散らかしているわけではないですよ、ということで一応。

Travelex

SMBC 信託銀行

みずほ銀行

UOB

為替レートの変動では?

6/6 から 6/7 にかけて、そもそもの為替レートが円高SGD 安)になったのでは?

確かにその可能性も考えられる。せっかくここまで書いたので確認してみたよ。

Image from Gyazo

0.1 円(10 銭)ほど 円安(SGD 高) になっていたみたい。つまり日本円からシンガポールドルへの両替は若干不利になっていたということ。

  • 1 SGD あたり 79.189 円、10,000 円を替えると 126.28 SGD
  • 1 SGD あたり 79.293 円、10,000 円を替えると 126.11 SGD

これまでも「国内の空港で両替するのはレートが良くないよ」という話は聞いていたけれど、大した違いではないだろうと考えてあまり気にしていなかった。確か 2012 年にフィリピンに行ったときは成田空港で替えた気がする。

今回少し気持ちに余裕があったので各両替所のレートを比較してみようと思って記録してみたら、思っていた以上に差があったのでびっくりした次第。

※今回シンガポールで利用したところの中には、レートを表示しているディスプレイの撮影(写真、動画ともに)を禁止している両替所もあったのでそのあたりは要注意。

空港から市内へ

空港から市内に向かうにはタクシー、バス、地下鉄(MRT)などがあり、今回は MRT にした。

日本の Suica のようにシンガポールでは EZ-Link カードという非接触型 IC カードがある。MRT もバスもこれ一枚で乗れる。利便性が大きく変わってくるので短期滞在だとしても買った方がいいと思う。

今回は前回訪問時に購入したカードがあり、残高も 7 ドルくらい入っていたのでそのまま改札を通って乗車できた。

もし残高が不足している場合は券売機でチャージできる。確か現金だけでなくクレジットカードからもできたはず。あと日本でいう「チャージ」は英語では「top up」という。

ちなみに Suica (FeliCa) と比べると改札での処理は少し遅いので、日本で改札を通るときよりも気持ち長めにタッチする必要がある。台湾でも同じような感じだったかな。詳しいことは知らないのだけれど FeliCa が抜きん出て速いんだっけ。

SIM カードを調達

チャンギ空港から MRT に乗って、滞在先ホテルがある Dhoby Ghaut 駅まで移動した。平日の朝ということで周りには通勤通学の皆さん。カジュアルな服装の方が多かった印象。新聞を読む人、スマートフォンでゲームをする人、音楽を聴いている人、寝ている人、この辺は日本と変わらない。

駅ビルが Plaza Shingapura という大きなショッピングセンターになっていて、1 階に携帯キャリア StarHub の大きな店舗が入っている。到着した時点ではまだ開店前だったのですぐそばにあるスターバックスで待つことに。

スターバックスの店員さんはこちらの英語がたどたどしかったからか日本語を交えて対応してくれて、内心「自分の英語はまだまだですな」と感じた部分もあったけれど、でも嬉しかった。

しばらく待っていると開店時間になったので StarHub へ。


店員さん: Hello, may I help you?

私: Hello, can I get a tourist SIM?

店員さん:(あっちのカウンターで受け付けますので、あちらへどうぞ)

私: OK, thank you.

カウンターに行って再び

私: Hello, can I get a tourist SIM?

店員さん: (7 日間で 12 ドルのものと、12 日間で 32 ドルのものがあります)

私: 7 days is enough. (指さしつつ)This one please.

店員さん: (パスポートを見せてください)

私: Here you are.


という感じのやり取りを経て、無事 SIM カードを購入できた。

データ通信が 100 GB も付いているので安心である。5 日間くらいの滞在でたぶん 10 GB も使っていないと思う。

また、SIM カードのトレイを出すピンや外した SIM を入れる簡易ケースなども付いていて至れり尽くせりであった。

入れ替えて少し待つと通信できるようになったので、スマートフォン側の設定などは必要ないみたい。

(続く)

シンガポールに行ってきた

先日、4 泊 5 日でシンガポールに行ってきたので記録を残しておこう。

当初はベトナムの首都ハノイに行こうと思っていた。ハノイは物価が安く、食事も美味しいらしく、のんびり過ごせてよさそうだったが、ふと「目線引き上げ効果」的なものを評価軸においた場合はどうだろうか、と考えた。

きっと今のハノイでしか見られないもの、感じられないものもあるのだろうけれど、これまで行ったことがないし、英語もあまり通じないようだし、現在の自分がもつ受容体とマッチしていないのではないか、と思ったりして。

その点、シンガポールは過去 2 回行ったことがあるし、シングリッシュが強いとはいえ英語が公用語だし、物価はベトナムよりずっと高いとしても滞在することでよい刺激を得られるのではないかと思えてきたのであった。

そもそも、前回 2016 年に行ったときの体験もよかったのでシンガポールに対して好意的な印象を持っているというのもあるのだけれど。

参考リンク

手配

今回は羽田空港発着の ANA 便にした。航空券は下記サイトを両方見て探した。

シンガポール航空のよりよい条件の便があったのだけれど、検索サイトでは表示されていても実際に予約を取ろうと航空会社のサイトに遷移してみると not available で取れない、という状態だった。そういことはままあるらしい。bot が古いキャッシュを持ったままになっていたのかな?

宿泊先は彼女の方で手配してくれるとのことでお任せ。いつも agoda を使っているそう。

航空券はうかうかしているとすぐ値段が変わってしまうので、早めに条件の優先順位(日程、価格)をはっきりさせて、ある程度よさそうであれば取ってしまった方がよさそう。

準備

ガイドブックは 2015 年に買った『地球の歩き方』は持っていたけれど、最新のものを購入。書店に置いてあった 5 冊くらいを見比べた結果、以下のものにした。

10 地球の歩き方 Plat シンガポール (地球の歩き方Plat)

10 地球の歩き方 Plat シンガポール (地球の歩き方Plat)

出発

地下鉄から京急直通で羽田空港へ。

キャリーケースを預けて、出国ゾーン(っていうの?航空券持っている人しか入れないゾーン)に移動。

出入国審査(パスポート確認等、通称イミグレ)が日本人は有人カウンターではなく、顔認識 + パスポートスキャンの自動認証機械を利用できるようになっていた。全然待たされないので快適であった。

自動販売機は Suica が使えず、ペットボトルの水を買いたい場合はその辺のカフェ、もしくはドラッグストア的なお店をあたるとよい。

この時点で周りはほとんどが外国の人で、みんな身体も大きいし、違う言語を話しているしで少し圧倒される。

その辺のベンチに USB の口がついているので携帯を充電しつつ搭乗時間を待つ。

(少しずつ書き足していく予定)

Elm でランダムにテキストを表示させる(その 2)

先日から作っていた web アプリが一応できた。

こういうスプレッドシートに文章を入力して、こういうサイトでランダムに表示させる、というもの。(何に使うものなのかは雰囲気で察してもらえればと)

Google スプレッドシートからは JSON でデータを吐くことができる(GET でのリクエストに対応するための関数が用意されている)ので、そちらは特筆すべきことなし。

下記記事のサンプルを参考にして、サクッと書いた。

変更したのはシート C 列 enabled のチェックがオフになっている行は除外する点と、選択したシートではなく全シートを対象とした点かな。

/**
 * Sheet から object にする
 * @param {Object} sheet
 * @param {Object}
 */
function convertFromSheet(sheet) {
    var rows = sheet.getDataRange().getValues();
    var keys = rows.splice(0, 1)[0];

    // filetering
    rows = rows.filter(function (row) {
        // enabled == true
        return row[2] === true;
    });

    var result = {};
    result["sheetName"] = sheet.getName();
    result["rows"] = rows.map(function (row) {
        var obj = {};
        row.map(function (item, index) {
            obj[String(keys[index])] = String(item);
        });
        return obj;
    });
    return result;
}

/**
 * 各シートのデータを filter した上で object にする
 * @returns {Object}
 */
function getObjectFromSheets() {
    const sheets = SpreadsheetApp.getActive().getSheets();
  return { sheets : sheets.map(convertFromSheet) };
}


/**
 * web app として公開する
 */
function doGet(e) {
    const data = getObjectFromSheets();
    return ContentService.createTextOutput(JSON.stringify(data, null, 2))
        .setMimeType(ContentService.MimeType.JSON);
}

で、Elm ですよ。

汎用的なプログラミング言語ではなく、Web のフロントエンドを作ることに特化した言語。Dart とかもそういう感じなのかな?知らないけれど。 コンパイルして html を出力したり、JS を出力したりできる。

# html
$ elm make src/Main.elm --output=index.html

# js
$ elm make src/Main.elm --output=elm.js

静的型付けで型の不一致をすぐ教えてくれるのがよい、ということを少し Twitter で書いたけれど、それに加えて、言語とフレームワークが一体となっていてプログラムの構成などで迷う必要がないのもいいところ。

細かいところについては各種ノウハウなどあるだろうけれど、大枠では Elm way に乗っかっていけばよくて、他の人も同じ構成でやっているからブログ記事なども参考にしやすかった。

OCamlHaskell に興味を持っていて少しだけかじったこともあった(歯型がついたかどうかくらいのレベルだけれど)ので、文法などはそんなに苦労せず理解できた。あと最近出たばかりの書籍があって丁寧に解説されていてわかりやすかったな。公式のガイド An Introduction to Elm も何回も読んだっけ。

基礎からわかる Elm

基礎からわかる Elm

あと、こうやってパイプライン演算子 |> を使ってすっきり書けると気分が良い。

addLineBreak : String -> List (Html Msg)
addLineBreak note =
    String.lines note
        |> List.map text
        |> List.intersperse (br [] [])

もう少し何か書こうと思っていたのだけれど、ひとまずこの辺で。

Elm でランダムにテキストを表示させる

所用で(?)シンプルな web アプリを作ることになり、Elm で書いてみることにした。

要件としてはルーレットのような感じで文章をシャッフルしてランダムに表示するもの。もう少し作り込む予定だけれどひとまず載せておこう。

とりあえずの感想

  • 見よう見まねで書いていると値は immutable ということを忘れがちだった。
  • エラーメッセージが親切なのでギリギリやっていけるという感じ。
  • バージョンが上がるごとに結構いろいろ API が変わっているようで、ブログ等の情報が参考にならない場合も多い印象。
  • update の処理を連鎖させるのはどうしたらいいのか、よくわからなかった。
    • 結局 Task.perform で繋ぐ感じでやっているが正しいのか不明。
  • 公式のフォーマッター elm-format があるので助かる。
    • でもインデントがずれていると動かなかったりするので Go の gofmt と比べると少々頼りない気がする。

もし、JavaScript で書いたとしたら、オンラインで公開されている参考にできるサンプルの数が多いので、おそらく半分くらいの時間でできたのではないかと思う。

まぁこうやって新しい概念に触れて、チャレンジしてみるのも大事だからね。

コード

Elm はシンタックスハイライトに対応していないか、そうか。

(190404 追記)
言語指定を Haskell にすることでそれっぽい感じでハイライトされるようになった。

module Main exposing (Model, Msg(..), init, main, subscriptions, update, view)

import Array
import Browser
import Html exposing (..)
import Html.Events exposing (..)
import Random
import Task
import Time



-- MAIN


main =
    Browser.element
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }



-- MODEL


type alias Model =
    { sentences : List String
    , index : Int
    , sentence : String
    , shuffling : Bool
    , count : Int
    }


init : () -> ( Model, Cmd Msg )
init _ =
    ( { sentences = sampleSentences
      , index = 0
      , sentence = ""
      , shuffling = False
      , count = 0
      }
    , Cmd.none
    )



-- https://www.thetoptens.com/random-sentences/


sampleSentences : List String
sampleSentences =
    [ "I am so blue I'm greener than purple."
    , "I stepped on a Corn Flake, now I'm a Cereal Killer."
    , "Everyday a grape licks a friendly cow."
    , "Llamas eat sexy paper clips."
    , "Banana error."
    , "Don't touch my crayons, they can smell glue."
    , "There's a purple mushroom in my backyard, screaming Taco's!"
    ]


maxCount : Int
maxCount =
    20



-- UPDATE


type Msg
    = Pick
    | GetIndex Int
    | Tick Time.Posix
    | CheckCount Time.Posix
    | Shuffle Time.Posix


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Pick ->
            ( { model | shuffling = True }
            , Random.generate GetIndex (randomIndex model.sentences)
            )

        GetIndex i ->
            let
                s =
                    pickByIndex model.sentences i
            in
            ( { model | index = i, sentence = s }
            , Cmd.none
            )

        Tick newTime ->
            let
                c =
                    if model.shuffling then
                        model.count + 1

                    else
                        model.count
            in
            ( { model | count = c }
            , Task.perform CheckCount Time.now
            )

        CheckCount newTime ->
            ( resetStatus model
            , Task.perform Shuffle Time.now
            )

        Shuffle newTime ->
            ( shuffleSentence model
            , Cmd.none
            )


randomIndex : List String -> Random.Generator Int
randomIndex sentences =
    Random.int 0 <| List.length sentences - 1


pickByIndex : List String -> Int -> String
pickByIndex sentences index =
    let
        default =
            "this is default sentence."

        arr =
            Array.fromList sentences
    in
    Maybe.withDefault default (Array.get index arr)


resetStatus : Model -> Model
resetStatus model =
    if model.count == maxCount then
        let
            s =
                pickByIndex model.sentences model.index
        in
        { model | shuffling = False, count = 0, sentence = s }

    else
        model


shuffleSentence : Model -> Model
shuffleSentence model =
    let
        randomId =
            modBy (List.length model.sentences) model.count
    in
    let
        randomSentence =
            pickByIndex model.sentences randomId
    in
    if model.shuffling then
        { model | sentence = randomSentence }

    else
        model



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Time.every 40 Tick



-- VIEW


showBool : Bool -> String
showBool bool =
    if bool then
        "True"

    else
        "False"


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text model.sentence ]
        , h2 [] [ text (String.fromInt model.count) ]
        , h2 [] [ text (showBool model.shuffling) ]
        , button [ onClick Pick ] [ text "Pick" ]
        ]

Ellie というオンライン開発環境(いわゆる playground 的なやつ)にも保存してみたけれど、表示されないかもしれない。

Elm の記事からヤギ画像を取り除く User Script を書いた

Elm とヤギ画像

Elm というプログラミング言語があって面白そうだなと思っているのだけれど、まぁ何というか、個人的にはアレだなーと思うところもあって。

ということで、User Script 書いてみた。

User Script

最近あまり聞かなくなった気がするけれど以前、Greasemonkey というものがあって、それの Chrome 版として Tampermonkey という拡張があった。

で、以下のスクリプトを登録することで目的を達成できた。

Qiita

// ==UserScript==
// @name         removeGoatQiita
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to remove images of goat
// @author       ryskosn
// @match        https://qiita.com/arowM/items/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const imgs = document.getElementsByClassName('it-MdContent')[0].getElementsByTagName('img');
    for (const img of Array.from(imgs)) {
        img.parentNode.removeChild(img);
    }
})();

ちょっと雑かもしれないけれど、他のやり方が思いつかなかった。

elm-lang.jp

// ==UserScript==
// @name         removeGoatElmLangJp
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to remove images of goat
// @author       ryskosn
// @match        https://elm-lang.jp
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const eyeCatch = document.getElementsByClassName('eyeCatch')[0];
    const moment = document.getElementsByClassName('moment')[0];
    eyeCatch.parentNode.removeChild(eyeCatch);
    moment.parentNode.removeChild(moment);
})();

それぞれのスクリプトを Tampermonkey のダッシュボードから設定する。

Image from Gyazo

190323 リカバリー中

2 月は自分のやるべきことに注力できていて、 結構いい感じで過ごせたのだけれど、3月に入ってから 低空飛行が続いている。

その要因として思い当たるものとしては、

  • 生活のリズムが少し変わった
  • イレギュラーなイベントも多々あった
  • 花粉症

といったところだろうか。

3/14 までは外部要因の影響が大きく、まぁこんなもんでしょうという 認識もあったが、その後の 1 週間もなかなか 2 月のようにはいかず、 現在リカバリーの真っ最中である。

どう考えても花粉症のせいだよね。まったくもう。

リカバリ

まぁ杉花粉に文句を言っても解決しないので、リカバリーについて考える。

何が問題かというと、2月と同じように行動できていないこと。 2月は守れていたルーティン、習慣がすっかりどこかに行ってしまった。

ここで悲観したり自己嫌悪に陥ったりするのはただの素人であり、 我々のようなもの(?)は、「あー、なるほどなるほど」と自身の状況 (続けていた習慣が途切れ、規律が乱れてしまっている現状)と、 それについてこれから対処しようとする自分を俯瞰して捉えるのだ。多分。

規律

まぁとにかく、復帰するためのアプローチとしては 「規律を取り戻すこと」を意識するのがいいのではないかと思う。

それも小さなところから少しずつでよくて、例えば、

  • 朝起きたらコップ半分の水を飲む
  • 脱いだ靴を揃える
  • 手洗い、うがいをする
  • 帰宅したら机の上にノートを開いて日付だけ書く

など、毎日続けられるようなことを意識して毎日続けていくのだ。

ある程度継続していれば、そのうちにそれをするのが当たり前になってきて、 都度意識する必要がなくなるので、空いた脳内メモリで他のちょっとしたことを やるようにするのがいいと思う。

規律と自己肯定感、あとは食事と睡眠、という感じで生活していれば 徐々に調子も上がってくるんじゃないかな。

OPAM、OCaml をアップデートする

OCaml コンパイラをインストール

まず opam 自体をアップデートする。パッケージマネージャは MacPorts を使っている。

$ sudo port upgrade opam

1.2 から 2.0 へメジャーバージョンアップということで多少コマンドが変わっているみたい。

opam switch list-available でインストール可能なコンパイラの一覧を表示する。

各種オプション適用版も含めて大量に表示されるのでコンパイラのバージョンだけを見るなら | grep base をつけてもいいかもしれない。

$ opam switch list-available
# or
$ opam switch list-available | grep base

最新のコンパイラ 4.07.1 をインストールしてみる。

$ opam switch create 4.07.1

バージョン 4.07 の変更点などはこちら。

各種パッケージをインストール

お好みで。

$ opam install -y utop
The following actions will be performed:
  ∗ install conf-m4     1          [required by ocamlfind]
  ∗ install ocamlbuild  0.14.0     [required by react]
  ∗ install dune        1.8.2      [required by utop]
  ∗ install ocamlfind   1.8.0      [required by utop]
  ∗ install jbuilder    transition [required by cppo, camomile, lambda-term]
  ∗ install base-bytes  base       [required by zed]
  ∗ install result      1.3        [required by lwt]
  ∗ install cppo        1.6.5      [required by utop]
  ∗ install camomile    1.0.1      [required by utop]
  ∗ install topkg       1.0.0      [required by react]
  ∗ install lwt         4.1.0      [required by utop]                        For the PPX, please install package lwt_ppx
  ∗ install react       1.2.1      [required by utop]
  ∗ install lwt_log     1.1.0      [required by lambda-term]
  ∗ install zed         1.6        [required by lambda-term]
  ∗ install lwt_react   1.1.1      [required by utop]
  ∗ install lambda-term 1.13       [required by utop]
  ∗ install utop        2.3.0
=====17 =====
$ opam install -y ppx_inline_test
The following actions will be performed:
  ∗ install sexplib0                v0.12.0 [required by base]
  ∗ install ocaml-compiler-libs     v0.11.0 [required by ppxlib]
  ∗ install ppx_derivers            1.0     [required by ppxlib]
  ∗ install base                    v0.12.0 [required by ppx_inline_test]
  ∗ install ocaml-migrate-parsetree 1.2.0   [required by ppxlib]
  ∗ install stdio                   v0.12.0 [required by ppxlib]
  ∗ install ppxlib                  0.5.0   [required by ppx_inline_test]
  ∗ install ppx_inline_test         v0.12.0
=====8 =====
$ opam install -y spotlib
The following actions will be performed:
  ∗ install ppx_tools_versioned 5.2.1 [required by ppxx]
  ∗ install seq                 base  [required by re]
  ∗ install ppxx                2.3.2 [required by ppx_test]
  ∗ install re                  1.8.0 [required by ppx_test]
  ∗ install ppx_test            1.6.0 [required by spotlib]
  ∗ install spotlib             4.0.3
=====6 =====
$ opam install -y ocp-indent
The following actions will be performed:
  ∗ install cmdliner   1.0.3 [required by ocp-indent]
  ∗ install ocp-indent 1.7.0
=====2 =====
$ opam install -y merlin
The following actions will be performed:
  ∗ install conf-which  1     [required by biniou]
  ∗ install easy-format 1.3.1 [required by yojson]
  ∗ install biniou      1.2.0 [required by yojson]
  ∗ install yojson      1.7.0 [required by merlin]
  ∗ install merlin      3.2.2
=====5 =====
$ opam install -y js_of_ocaml
The following actions will be performed:
  ∗ install uchar                0.0.2 [required by js_of_ocaml]
  ∗ install js_of_ocaml-compiler 3.3.0 [required by js_of_ocaml]
  ∗ install js_of_ocaml          3.3.0
=====3 =====

OCamlFormat というフォーマッタが開発中らしい。 gofmt みたいにカチッとフォーマットしてくれるのだとしたら嬉しいな。おって試してみるかも。

集中して仕事するクセ

いやー、何とか元気でやっています。
前回書いてから、もう 4 ヶ月くらい経ってるのか。早い。

最近の関心事としては、先週末くらいに以下のエントリを読んで、今さらながら「本当に集中しているか?」ということを考えるようになった。

いろいろあって、2 月からは 9 時から 18 時(休憩 1 時間)で、ほぼきっかり 8 時間勤務というスタイルでやっている。

それまでは遅くとも 20 時にはなるべく帰る、19 時台のときもあれば 20 時半とか 21 時を回ることもないわけじゃない、という感じだったので、2 月に入ってからは集中してやらないとすぐ 18 時になってしまうなーと感じてはいた。

でも、本当に集中してやっている時間がどれくらいあるだろうか、と自問するとどうだろう。

仕事の都合上、頻繁に割り込みタスクが発生して中断させられることがままあるという点を考慮したとしても、8 時間フルに集中してやっていると胸を張れるかというと難しい。(Toggl で時間を計ったりちょっとした工夫もしていたけれども)

そんなこんなで上記エントリを読んで、書かれているような 6 時間勤務の会社だと本当に集中してやらないと価値を発揮できないまま 1 日が終わってしまいそうだし、相応のプレッシャーも感じるだろうなと想像した。

ただ、

1 日 6 時間を継続して働き、成果を出し続けるというのは並大抵のことではない。ただこのことで会社に依存する時間をぐっとへらすことができるのは事実だし、6 時間という時間の使い方が慣れていく。

そして、

毎日集中して働き続けるはある意味、修行に近いと思う。ただそれになれることで集中して仕事するクセを付けられるのではないか?という考えに基づいている。

このようにも書かれていて、いずれも全くもってそのとおりだと思う。

最初はプレッシャーがあったり、しんどさを感じるかもしれないけれども、続けていくうちに「集中する筋力」が鍛えられていき、やがてはそれがその人にとっては普通の働き方になっていくのではないか。

頭は使わないと悪くなる一方だというし、文章も日頃から書いていないとスピードが落ちる。

同様に、ものごとに集中して取り組むスキル(?)というのも鍛えれば向上するかもしれないし、鍛えなければ緩やかに低下していく一方なのだとしたら、これは無視できないなーと思っている。

会社の制度も違うし、そのまま同じようにできるかというとそうもいかないかもしれないけれど、できる範囲で集中して仕事するクセをつけられるよう、取り組んでいきたい。

(早速月曜から意識してやってみているんだけどなかなかハードだ)