ソースコードのコメント内でも Markdown のテーブルを編集したいという気持ちだけは誰にも負けません

こんにちは, シーフードです.

Atom パッケージ markdown-table-editor の v1.1.0 をリリースしました. atom.io

今回の目玉はテーブルの左側のマージンの文字をカスタマイズできるようになったことです. これで何が嬉しいかというと, 例えばパッケージの設定から Scopescomment.block.documentation.js, Left Margin Characters* を追加すると,

f:id:susisu:20180227193347p:plain

以下のように JavaScript のコメント内で Markdown のテーブルを編集することが出来るようになります.

f:id:susisu:20180227194042g:plain

上記の設定方法だと Left Margin Characters の設定が (JavaScript だけでなく) すべてのファイルについて共通になってしまうので, もし問題が発生する場合は config.cson に以下のような設定を書くことで JavaScript 内でのみ * をマージンと扱うように設定できます.

".js.source":
  "markdown-table-editor":
    leftMarginChars: "*"

他の言語での scope の設定はカーソルがコメント中にある状態で Command Palette (Ctrl(Cmd) + Shift + P) から Log Cursor Scope を選ぶと確認できます.

それでは良いドキュメンテーション生活を.

P.S.
コア部分もアップデートしています. VSCode 版とか需要ありそうなので誰か作って.

github.com

Scala の for ... yield の話

みなさんメリークリスマしておめでとうございます. 2019年もよろしくお願いします.

以下は気まぐれに Scala を書いていたら for ... yieldHaskelldo の微妙な違いでつらみが出てきたときのメモです. Scala 素人もいいとこなのでもっと良い書き方があったら是非教えてください.


例として getNumbers(t: T): Either[String, List[Double]] が何か知らないけれど存在するとして, その結果の平均を求めたいとする. もし不都合があればエラーメッセージを Left にくるんで返す.

Haskell で書くとこう.

do
  xs <- getNumbers t
  case xs of
    [] -> Left "no data"
    _  -> Right $ sum xs / fromIntegral (length xs)

Scala ではこうなるはず.

for {
  xs <- getNumbers(t);
  ret <- xs match {
    case Nil => Left("no data")
    case _   => Right(xs.sum / xs.length)
  } 
} yield ret

なんか余計な変数が生えて気持ちが悪い. (注: この場合は ret のかわりに avg と変数名をつければ違和感は減るが, 一般に適切な名前を付けられるかというとそんなことはないのであえてこうしている.) あと気になるのはインデントが最後の行で先頭に戻た上で何か (yield ...) が書いてあることで, 後続の処理があるのかなとパッと見で勘違いしてしまいそう.

一つの解決策として, ここではパターンマッチを使っているけど, もし適当な述語 (isEmpty とか) があるなら when[A](cond: Boolean)(conseq: => Either[A, Unit]): Either[A, Unit] みたいなのを使ってアーリーリターン的に書けば良い. (Scalaz とかに whenM がある.) でももっと特殊な場合とか自前のデータ構造の場合とかは別に述語を定義する必要があって面倒っぽい.

for {
  xs <- getNumbers;
  _ <- when(xs.isEmpty) { Left("no data") }
} yield xs.sum / xs.length

希望としては例えばこんな風に書けるとうれしいかも.

for {
  xs <- getNumbers(t); 
} yield <- xs match {
  case Nil => Left("no data")
  case _   => Right(xs.sum / xs.length)
} 

続きまして, getNumbers に与える引数が長くて (あるいは後で使うので) 別の変数に代入しておいた方が良い場合.

まずは Haskell の場合. (もう平均は面倒なので単に和を求めることにする.)

do
  let t = supercalifragilisticexpialidocious
  xs <- getNumbers t
  Right $ sum xs

続いて Scala.

for {
  t = supercalifragilisticexpialidocious;
  xs <- getNumbers(t)
} yield xs.sum

と書きたいところだけど, これは駄目で,

{
  val t = supercalifragilisticexpialidocious
  for {
    xs <- getNumbers(t)
  } yield xs.sum
}

としないといけない. なんか不必要に { ... } のネストが増えていてつらい.

ちなみに変数定義は先頭でなければできるので, こういうのは書ける.

for {
  xs <- getNumbers(t);
  s = xs.sum
} yield s