日曜プログラミング

休日趣味でやってるプログラミング関連記事をダラダラと

Windows 等幅フォントの到達点

自分が今現在Windows上で作業する際に主に設定しているフォントのメモ。

種類 フォント名 他コメント
日本語 Source Han Code JP 日本語メニューネーム:源ノ角ゴシック Code JP
ASCII JetBrains Mono

他サイトでもかなり賛辞が送られているけど、ほんと見易い。 ASCIIもSource Han Code JPは十分見易いけど、割と最近リリースされたJetBrains Monoは個人的には更に見易いと感じているので設定している。

印刷に最適化されたフォントも当然あるんだろうけど印刷はほぼしないのでそっちは全然追及してない。

Excel のピボットテーブルでのフィルタ一覧から古いのを削除する

Excel でピボットテーブル使う時ってピボットテーブルはそのままにデータソースを変える事が 結構あるのだが、その時ピボットテーブルのデフォルト設定だとフィルタ一覧に新しいデータソースには無いものが残っている。

これを消す設定は以下。

  • ピボットテーブルオプション -> データ -> データ ソースから削除されたアイテムの保持 を「自動」から「なし」に変更

余談

これもググればすぐ出るネタなんだが、GUI ソフトの宿命なのか少し使ってたら 知ってるから要らないよみたいなスクショが多くて目的の情報探すのに一手間かかるので忘備録としてメモ。

それでも画面コピー乗せるなら開発系で最近よく見るアニメ画像が良い気がする。

オレオレ Clojure スタイル

小ネタ。

Clojure スタイルガイド にあるかどうか全部見てないけど、自分がコーディング時に決めてるスタイルを一つ。

マップの値参照時の関数呼び出し

(マップ キー) と言う呼び出しで統一している。 これはマップデータに設定するキーが Clojure の keyword の場合だと、

(something-map :something-key)
(:something-key something-map)

と、どちらの呼び出しも問題なく使えるのだが、 例えばキーを文字列で設定した場合に後者が Exception になるため。

("something-key" something-map)
class java.lang.String cannot be cast to class clojure.lang.IFn

まあ Exception 見れば文字列は関数として呼び出せません(意訳)って感じのメッセージになってるけども 以前どっちも行けるってのだけ覚えてて気にせず後者で書いてて小ハマリしたのと 自分の場合 Clojure のマップデータのキーに keyword にしない事がしばしばあるので。

Calva の v2.0.109 以降で REPL の仕様が変わった模様

盆休み明けで Calva 触って気づいたんだがどうも v2.0.109 から REPL Window の代わりにファイルで REPL するようになったっぽい。

全体を読み込んだ訳ではないので自分が気づいた所だけ。

  • REPL Window 廃止
    • じゃぁ REPL は?と言うと The Output/REPL Window/File とちょっと長めな名前のものに変わるとの事
      • History はあれど基本的に REPL に書き捨てだったものがデフォルトでファイルに吐き出されるようになった感じか?
  • ctrl+c o で Output Window/File に移動

  • REPL で評価したい場合はどうするのか

    • ソースファイル全体読込は従来の ctrl+alt+c enter で良い
    • REPL 上のみで書き捨てていたものは The Output/REPL Window/File に評価したい式を書いた後で ctrl+enter で良い
      • これはソース側の評価も同じで統一したショートカットになるのは良い変更だと思う

Calva を実際に使っている人は分かると思うんだが、上記のコマンドが微妙に統一されてないのも含め他にも REPL Window と ソースファイルとで結構挙動が違ってたりしていた。

VSCode 拡張の内部は良く分かってないのだが、どうも REPL Window とソースファイルで違うモードで動いててこのような不統一ができてたっぽい。参考に挙げた Rationale をちらっと読む感じ REPL 側は Webview API を使ってて、ソース側は違う為云々な事が書いてあった。

じゃぁ REPL もファイルベースにしてしまえばいいよね、ってのが今回の変更の大まかな流れみたい。

まあ盆休み明け久々に触った時は Jack-In しても REPL Window が出てこないもんだからちょっと焦ったが分かってしまえば使用感が相当同じになってきている今の仕様の方が良いと思う。

コマンドでコマンドプロンプトのサイズを変更する(別サイトのブックマーク)

ブクマ。

コマンドでコマンドプロンプトのサイズを変更する

余談だがコマンドヘルプ(/?)だと省略記法って書いてなかったんだけど どこに情報あったんだろう?

Clojure の Macro 中(defmacro)での型ヒント

英語ならググれば割とすぐ出てくる話題だが自分用にメモ。

最近は ClojureCLI ツール書く時、GraalVM で実行 exe を生成できる可能性を残すべく 自分が書くコード中では reflection warning を出さないよう型ヒントをつけまくってる。

ある日 defmacro 中で reflection warning 出てる時これを解消するにはどうすれば良いのかが分からなかった。どうも defmacro 中では単純に 公式リファレンスのように書いてもダメみたい。

自分がやりたいのは defmacro 引数中に型ヒントを付与したかったのだが stackoverflow にあった。

(defmacro def-string
  [name value]
  `(def ~(vary-meta name assoc :tag `String) ~value))

引用元:Stackoverflow の Clojure defmacro loses metadata トピック回答

なるほど ^ ってリーダーマクロだったのか(あまり良く分かってない)。

以下余談。

余談

余談1: シンタックスクォート中のアンクォート(~)中にまたクォートする(') のは未だにパッとは分からんなあ。

余談2: はてなmarkdown の解釈の問題かどうかは分からんけどシンタックスクォートの文字も余談 1 に表示したかったけどエスケープの仕方が良く分からんので諦めた。

余談3: 今回初めて知ったけどClojure公式サイトのマクロの説明ってものっそい説明少ないのね。肝になる余談1に上げた主要文字に関する説明全然ないし。あんまり使わせたくないのかなあ。

この Protocol の使い方正しいんだろうか?

Clojure に限らないんだが関数名決めるのってプログラミングで一番難しいとか 誰か偉い人も言ってた気がする。

んで、自分で作った関数に付けたい名前が clojure.core にある関数名と被っている事があった場合どうするのが良いのか。

最も単純なのは被らない名前にしてしまう、だがそれも面白くないなとちょっと考えてたら そういや Protocols 使えるんじゃね?とふと思って試してみた。

name で使った例

name ってのは引数で Symbol か Keyword を受け取ると文字列を返す関数。

(name 'a)
"a"
(name :b)
"b"

これが例えば String と言う java.lang.Class を渡すとエラーになる。 java.lang.Class は未対応なので当然の話。

(name String)
Execution error (ClassCastException) at~

これを Protocols で拡張してみる。

(defprotocol ExtendName (name [x]))
(extend-protocol ExtendName
  Class (name [x] (.getName x))
  Object (name [x] (clojure.core/name x)))

最後に Object に指定しておくとここが実質デフォルト実装になる。 公式 でも以下のように書かれてるのでこの書き方は別に問題なさそう。

To define a default implementation of protocol (for other than nil) just use Object

nil 以外と言う但し書きがあるけどそんな問題にならないかと思う。

これを評価すると既存の実装上書きするよと Warning 出るがそこはしょうがない。 再び実行してみると、

(name 'a)
"a"
(name :b)
"b"
(name String)
"java.lang.String"

結果 java.lang.Class にも対応した name になった。

デフォルト実装の書き方はまだしも、core に定義されてるのを上書きするのは どうなんだろうかと言うのが疑問として残ってる。

name は単純だから元の処理を邪魔しない形になってるが、 拡張しようとする関数を良く理解してないと思わぬ所でハマりそうな気がしないでもないが どうなんだろう。

と、疑問を残しつつも思いついたネタだったので今回記事に上げてみた。

余談: Multimethods と Protocols どちらを使うべきか

自分は関数の引数の最初の型による dispatch で事足りるなら Protocols、 そうでないもっと複雑な dispatch をしたければ Multimethods と言う理解。

実際に比較検証した事はないが Protocols の方がパフォーマンスも良いらしい。

後者が必要になる場面と言うのは実際かなり少ないと思う。