私が歌川です

@utgwkk が書いている

トップページには最新N件の記事を出してほしいけどこのタグを持った記事は出さないようにしてほしいな~というときのSQL

スキーマはこちら。型をかなり省略しています。いわゆるToxi法(中間テーブルがある)ってやつです。

create table article (
  id integer primary key,
  ...
);

create table article_tag_rel (
  article_id,
  tag_id,
  ...
);

create table tag (
  id integer primary key,
  name,
  ...
);

どうやって書きますか? 私はこう書きました。

select distinct a.* from article a
left join article_tag_rel atr on a.id = atr.article_id
left join tag t on atr.tag_id = t.id
where t.id is null
or t.name not in ('dame', 'desu', ...)
order by a.id desc limit N;
  • タグがない記事は t.id is null になるので表示される
  • タグがあるならNGタグが付いてないか確認してから表示する

という処理が行われています。記事に対して必ず1個以上のタグがあるならぜんぶ inner join でいい気もする。

SQLだけでやろうとしてこうなっているけど、実用的にはアプリケーションでうまく計算してキャッシュしたりマテリアライズドビュー使ったりするほうがよさそう? このへんどういう実装にすることが多いのか事例を知りたい。

最初はleft joinが3つあったけど、2つでいいじゃんということになった。

参考

家のネットワークが遅すぎるまま週末が終わった。 遅すぎるといってもYouTubeAmazonプライムビデオは不自由なく見れており、よりによってAWS S3やGitHubUbuntuのapt sourceなどへの接続がめちゃくちゃ遅く、タイムアウトしてしまう。

何もできなくて、YouTubeを見てたら終わってしまった。

imagemagickで富豪的にアニメーションGIFをリサイズする

みんな大好きimagemagickの回です。

imagemagickでは convert -resize 幅x高さ in out のようにして画像をリサイズできるのですが、一部のアニメーションGIFがうまくresizeされず、表示がおかしくなります。 アニメーションGIFはリサイズしたい、しかし表示がおかしくなっては元も子もない、なのでどうしよう……。

結局取った手法は「各フレームごとの画像をリサイズしてアニメーションGIFに戻したらOK」になりました。 後述するようにこの方法は富豪的です。もっといい方法があれば知りたい。

yoyaさんありがとうございます、同ツイートのスレッドが詳しいのですがどうやらimagemagickのバグらしい……? coalesceしたのちresizeすることは変わらないのですが、引数の順序が違っていたようで、ご指摘の通り修正すると1コマンドで正しくリサイズできました。

手順

magick convert in.gif -coalesce -resize 幅x高さ -layers optimize out.gif

  • -coalesce でフレームごとの差分を展開して
  • リサイズして
  • -optimize で再びアニメーションGIFを最適化している

注意

coalesceとresizeを同時にやるとうまくいきません。 画像サイズやフレーム数が多いとimagemagickが死ぬほどリソースを食います。imagemagickのリソースリミットを一時的に上げるとよいと思います。

参考

軽めのプログラムをGoで書きがち

単機能のSlack BOTとかコマンドラインツールとかは最近ずっとGoで書いている。なんで書いているのかまとめてみた。

静的型がある

型システムとしてはまだ弱い、とか、冗長すぎる、という意見があるかもしれないけど、ないよりはマシだと思っている。 静的解析でエディタで書いてるそばから型エラーを検出できるし補完が効いて便利。

ライブラリがある

PythonとかRubyとかを使うときとだいたい同じ感じで、欲しいライブラリを探して使うことができる。 今のところライブラリが足りなくて困るといったことに出くわしたことはない*1

最近はgo modulesも入っていよいよGOPATHのことを忘却して好きに書けるようになった。

ワンバイナリで動く

LLだとどうしても、依存ライブラリを入れて、処理系のバージョンを揃えて、みたいなことをやる必要があるけど、Goはコンパイル済のバイナリを実行すればよいので楽。 コンパイルオプションがんばって指定しなくてもデフォルトでスタンドアロンビルドになるのは何も考えなくてよい。

*1:ライブラリの実装が雑で困ることはある

CHANGELOG / リリースノートどうやって書いてますか

VSCode拡張機能どんどんアップデートしてるけど、リリースノート何も書いてないことに気づいた。 ユーザからすると気がついたら新機能が増えてるけど、どうなったかはcommit logを見ないとわからない状態になっている。 そしてcommit logを見ても、全体としてどんな機能が増えたのかは分からないかもしれない。

みなさまはどうやってリリースノート書いてますか。とくにエディタ拡張についていま一番知りたいです。

  • 気合
  • いいツールありますよ
  • その他

文字列を負の数回repeatしたときの言語ごとの挙動

プログラミング言語の組み込み関数・演算子・ライブラリで文字列を負の数回repeatしたときの挙動について調査した。空文字列になる場合と、例外を送出する場合と、コンパイルエラーになる場合に分かれている。

言語 (バージョン) コード 結果
D (dmd 2.076.0) "a".replicate(-1) OutOfMemoryError が送出された
replicateの引数はsize_t (unsigned)
引数がキャストされた結果巨大な文字列を生成しようとして落ちる
F# (fsharpc HEAD 10.1.2-24c798b) String.replicate -1 "a" System.ArgumentException: The input must be non-negative. が送出された
Go (1.12.8) strings.Repeat("a", -1) panic (negative Repeat count) になった
Haskell (ghc 8.4.2) concat $ replicate (-1) "a" "" に評価された
JavaScript (Node.js 8.12.0) "a".repeat(-1) RangeError: Invalid count value が送出された
PHP (7.3.3) str_repeat("a",-1) "" に評価された
警告が出る
Perl (5.22.1) "a" x -1 "" に評価された
use warnings してると警告が出る
Python (3.8.0) "a" * -1 "" に評価された
Ruby (2.6.1p33) "a" * -1 negative argument (ArgumentError) が送出された
Rust (1.18.0) "a".repeat(-1) コンパイルエラーになった
(繰り返し回数はusize)

文字列をrepeatするコードを書くときに予期しない例外送出の原因となってしまうことがあるので、みなさまにおかれましては気をつけましょう。

参考文献

文字列を負の数回repeatしたときの言語ごとの挙動 - 私が歌川です

JavaScriptはRangeErrorになります

2019/11/06 17:49
b.hatena.ne.jp

以上を受けてDのreplicateの引数に関する注釈を追加し、またJavaScriptの場合を追加しました。

情報提供を受けてF#の場合を追加しました。

ターミナルでmarqueeしたい (1)

marqueeというのは、こういう感じで、文字が横にスクロールしてめちゃくちゃ楽しいやつです。

ターミナルで使えるmarqueeの中で最も有名なものとしては、slコマンドが挙げられますが、SLしかmarqueeできないという問題があります。 文字列ならなんでもmarqueeしたい、と思っているので、いま実装を進めています。

このたび、1行の文字列をmarqueeさせることに成功しました。 ncursesの薄いラッパーを使いつつ、文字のオフセットは頑張って計算する、左にはみ出るのもうまくやる、といったことが行われています。

Image from Gyazo

張り切ってRustで書きはじめたけど、Rust久しぶりに書いたしまだ入門完了してないので、ググりながら書いています。 言語処理系やLanguage Serverがよくできているので赤線が出たところを修正すればよいみたいな感じで、コンパイラペアプロしてもらっている感じ。

github.com

複数行の文字列やワイド幅文字を考慮したmarqueeなどがまだ実装されていないので、やっていく必要があります。