スキップしてメイン コンテンツに移動

Punning いろいろ

Perl 6 に colon pairs という構文がある。名前の通りコロンから始まる Pair のコンストラクタで、例えば次のように使う:

:foo(42)   # foo => 42
:bar<yay>  # bar => 'yay'; 値が括弧類を使うリテラルの場合は小括弧は不要
:baz       # baz => True; 値を省略すると True になる
:!quux     # quux => False;  実に Perl らしい否定形
:$var      # var => $var

言う間でもないがこれは Hash を生成する場合のみならず、名前つき引数を渡す際にも便利である。 :$var という形式は変数の (sigil を除いた) 名前がそのままキーになるので、Perl 5 でよくある f(foo => $foo, bar => $bar, ...) といった繰り言をひとまとめにできる。 こういう構文を Punning (語呂合わせ、地口) と言ったりする。

対称的に関数のシグネチャも同様に書ける:

sub f(:$x, :$y) { $x - $y }

my $x = 42;
say f(:$x, :y(1));   # 41
say f(y => 1, :$x);  # ditto; 名前つき引数なので順番は可変

JavaScript の場合

JavaScript は冗長な用語を好むので Punning より Destructuring Assignment (の省略構文) と言った方が通りが良いだろう。 Destructuring Assignment の正確な構文は複雑だが、「右辺のオブジェクトを構築するときに値を置くべき場所に識別子を置くと対応する値が束縛される」程度の認識で概ね正しい:

const { x: value } = { x: 42 };  // value === 42

そして代入しようとする識別子名がオブジェクトのキーと同じ場合は識別子を省略できる:

const { x: x } = { x: 42 }  // x === 42
const { x } = { x: 42 };    // ditto; 上記の省略形

このようにオブジェクトを分解して代入できるのだから、オブジェクトの構築も対称にできるのが自然である:

const foo = 42;
const bar = 'yay';
const baz = true;
{ foo, bar, baz };  // { foo: foo, bar: bar, baz: baz } 即ち { foo: 42, bar: 'yay', baz: true }

OCaml の場合

Punning という用語を公式に使っているのは OCaml が有名だろう。対象はレコード型のフィールドと名前付き引数である。前二者の言語と違い静的型検査があるので安全である。

type record =
  { foo: int
  ; bar: string
  ; baz: bool
  }

let f { foo; bar; baz } =
  Printf.printf "foo: %d, bar: %s, baz: %b\n" foo bar baz

let () =
  let foo = 42 and bar = "yay" and baz = true in
  let r = { foo; bar; baz }  (* { foo = foo; bar = bar; baz = baz } *) in
  f r  (* foo: 42, bar: yay, baz: true *)
let f ~x ~y = x - y

let () =
  let x = 42 and y = 1 in
  print_int (f ~x ~y); print_newline ();  (* f ~x:x ~y:y = 41 *)
  print_int (f ~y ~x); print_newline ()   (* ditto *)

フィールド名はモジュールに所属しているので、モジュール外からレコードを生成しようとすると微妙な構文になる:

module M = struct
  type record =
    { foo: int
    ; bar: string
    ; baz: bool
    }
end

(*
  M.record 型の M.foo フィールドの値を変数 foo に束縛する。
  bar, baz も同様だが、既に M に所属していることが明らかなのでモジュール名を省略可能。
*)
let f { M.foo; bar; baz } =
  Printf.printf "foo: %d, bar: %s, baz: %b\n" foo bar baz

let () =
  let foo = 42 and bar = "yay" and baz = true in
  let r = { M.foo; bar; baz } in  (* { M.foo = foo; M.bar = bar; M.baz = baz } *)
  f r

コメント

このブログの人気の投稿

部分継続チュートリアル

この文書についてこれはCommunity Scheme Wikiで公開されているcomposable-continuations-tutorial(2010年09月30日版)の日本語訳です。誤字脱字・誤訳などがありましたらコメントあるいはメールで御指摘いただけると幸いです。本訳は原文のライセンスに基づきCreative Commons Attribution-ShareAlike 2.0 Genericの下で公開されます。Original text: Copyright© 2006-2010 Community Scheme WikiJapanese translation: Copyright© 2011 SATOH Koichi本文部分継続(Composable continuation)は継続区間を具象化することで制御を逆転させるものです。 ウンザリするほど複雑な概念を表す長ったらしいジャーゴンのように聞こえますが、実際はそうではありません。今からそれを説明します。resetとshiftという2つのスペシャルフォームを導入するところから始めましょう[1]。 (reset expression)は特別な継続を作るなりスタックに目印を付けるなりしてからexpressionを評価します。簡単に言えば、expressionが評価されるとき、あとから参照できる評価中の情報が存在するということです。 実際にはshiftがこの情報を参照します。(shift variable expression)は目印のついた場所、つまりresetを使った場所にジャンプし、その場所からshiftを呼び出した場所までのプログラムの断片を保存します; これはプログラムの区間を「部分継続」として知られる組み合わせ可能な手続きに具象化し、この手続きにvariableを束縛してからexpressionを評価します。組み合わせ可能(Composable)という語はその手続きが呼び出し元に戻ってくるため、他の手続きと組み合わせられることから来ています。 Composable continuationの別名として例えば限定継続(Delimited continuation)や部分継続(Partial continuation)もありますが、ここでは一貫して「組み合わせ可能」という用語を使います(訳注: …

多分週刊チラシの裏 (Sep 14-20, 2020)

自分にとってのニュースは自らまとめるしかないと思い至ったので興味深かったものをまとめる。Moment.js 開発終了JavaScript における日時処理の定番であった Moment.js の開発がメンテナンスモードへの移行を宣言した。歴史のあるライブラリであり、オブジェクトが可変で flux アーキテクチャと相性が悪いとか、自前の国際化リソースが全部バンドルされているので昨今の Dead Code Elimination (a.k.a. Tree-Shaking) を伴うバンドラでもサイズが縮まらないといった問題が指摘されていた。 互換性を保ったまま問題を解決できる見込みがなく、非互換な新バージョンをリリースして移行の混乱を生むよりは設計段階で問題を解決している別ライブラリに移行せよとのこと。参考に個人的な見解を述べると、代替候補として挙げられている dayjs はお勧めしない。タイムゾーンのサポートなど多くの場合に必要な機能がプラグインで実現されており、それらプラグインは dayjs オブジェクトにメソッドを実行時に追加したり差し替えたりするので TypeScript や flow の型定義と一致しなくなるためである。結局利用するプラグインを適用したバージョンの型定義ファイルを自分で作る羽目になるのだ。dayjs に限らず TypeScript や flow はプラグイン機構を持った JavaScript ライブラリと相性が悪いので、オールインワンなモジュールを採用する方が良い。代替候補の中では最初に挙がっている Luxon が無難である。20年来の銀英伝ファンからみた今回の揉め事「銀河英雄伝説」という古いスペースオペラ小説を原作とするアニメについて以下のツイートが炎上した件: 銀河英雄伝説のリメイク。3期以降も続くのかな。もしそうなら、男女役割分業の描き方は変更せざるをえない気がする。旧アニメのままだと、さすがに時代にそぐわない。作品として大変に面白いのは踏まえたうえで。…なんてことを書いたら炎上するかな。 — Shotaro TSUDA (@brighthelmer) September 11, 2020どう読んでもただの感想だが、話題がジェンダーかつ発言者の津田正太郎教授の所属が「社会学部」ということで表現の自由戦士の標的にされたもの。「社会学者1が『…

多分週刊チラシの裏 (Sep 21-27, 2020)

Killed by MozillaMozilla がディスコンにした製品およびサービスのリスト。COVID-19 パンデミックで収入が激減し全社の四分の一にあたる従業員の解雇と収益を得られる製品への集中に踏み切った Mozilla Corp. の最初の犠牲はノートアプリ Firefox Notes とファイル送信サービス Firefox Send となった。過去には第三のモバイル OS を目指した Firefox OS とか Mac ネイティブな Gecko ベースブラウザ Camino など懐かしい名前も見られる。ちなみに元ネタは Google が終了したサービスをリストしている Killed by Google で、こちらは 2020 年 9 月 26 日現在 205 個の製品とサービスが挙がっている。Firefox 81.0 リリースノートMozilla Firefox 81.0 が Release チャンネルに公開された。最大の新機能はメディア再生のキーボードないしヘッドセットからの制御である。要はバックグランドで再生している YouTube タブを AirPods から一時停止できるようになった。Developer Tools における色覚異常シミュレーションの改善やブラウザ標準 audio/video 要素のアクセシビリティ改善なども含まれている。Facebook が自社プラットフォーム上での複数国による組織的政治工作を認識しながら放置していたFacebook が大量の偽アカウントを動員した政治工作を認識していながら、特に小国のそれに対して対策を放棄していたという内部告発。元 Facebook のデータ科学者である Sophie Zhang 氏の告発によれば、ホンジュラスで大統領派の工作が行われていることを氏が報告してから実際に対策が為されるまでに 9 ヶ月、アゼルバイジャンでの与党の工作を同様に報告してから組織的な調査が始まるまでに実に 1 年を要したという。本来この手の濫用に対応するはずの専任チームは濫用の圧倒的な割合を占めるスパム対応にかかりきりで、政治工作については対象が合衆国か西欧である場合を除いて積極的に行動せず、小国の民主主義は Zhang 氏の空き時間を利用した片手間の対応にかかっていたとのこと。Rust じゃダメな理由近年人気が出てい…