サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
衆議院選挙2026
zenn.dev/qnighy
背景 本記事が扱う内容は、標準ライブラリやそれに準ずる基礎的なI/Oライブラリの作者に関係のある内容です。 Rustでアプリケーションを書くときに必要になる知識ではありませんが、Rustに関する理解を深めることができるかと思います。 読み込みストリームの抽象化 さて、RustはJavaやGoなどと同様、「読み込み処理」ができるI/Oオブジェクトを一般化したインターフェース std::io::Read を持っています。この核となるのが以下のメソッドです。 /// 1バイト以上 buf.len() バイト以下の読み取りを試み、 /// 結果を buf の先頭に書き込む。 /// /// 読み取ったバイト数を返す。 /// EOF または buf が空の場合は0バイトの読み取りとなる。 fn read(&mut self, buf: &mut [u8]) -> Result<usize, io:
結論 カレントディレクトリ (以下cwd) は、以下の2つの組み合わせで管理される、プロセス状態の構成要素です。 物理的なcwd: ディレクトリそのものを指すポインタ。カーネル側で管理される。 論理的なcwd: ディレクトリパス。 PWD という名前の環境変数を経由して、ユーザーランドで管理される。 ポイント 一般論として、ファイルを特定する方法には、ファイルへのポインタを保持する方法とパスを保持する方法の2通りがあります。この2つの方法は一長一短で、様々な場面で振る舞いが異なります。 ファイルポインタを保持する方法は、同じファイルシステム内でのファイルの 移動やリネーム を追跡します。一方、パスを保持する場合は移動やリネームを追跡せず、かわりに元の場所に新しくファイルが作られればそちらを参照するようになります。 ファイルポインタを保持する方法は、ファイルが削除されてもファイルの実体を参照
本稿は、2024年2月頃に書き溜めていたシリーズです。最後まで温存させるのが勿体ないので、未完成ですがそのまま公開します(公開日: 2025/9/21)。そのため、内容の重複や記述方針の不一致があるかもしれませんが、ご理解ください。 CSSの仕様を理解するために、1日ごとにテーマを決めて説明する企画4日目です。今日のテーマは前回に引き続き「閲覧環境」です。 ビューポートとページ 視覚的なブラウザにおいては、文書はビューポートと呼ばれる領域かページと呼ばれる領域に描画されます。 ビューポートは液晶ディスプレイのようなデバイスで使われる描画領域です。ビューポートは無限に広い領域の一部を表示しており、ユーザーがスクロール操作をすることで表示位置を変えることができるようになっています。 ページ (Working DraftのCSS Paged Media Level 3も参照) は印刷系のデバイス
本稿は、2024年2月頃に書き溜めていたシリーズです。最後まで温存させるのが勿体ないので、未完成ですがそのまま公開します(公開日: 2025/9/21)。そのため、内容の重複や記述方針の不一致があるかもしれませんが、ご理解ください。 CSSの仕様を理解するために、1日ごとにテーマを決めて説明する企画3日目です。今日のテーマは「閲覧環境」です。 WebブラウザはCSSの指定を必ず守るのか? もちろん、そんなことはありません。閲覧環境の技術的な制約から、指定通りに表示できないこともありますし、ユーザーの事情や好みにあわせて表示をカスタマイズする必要がある場合もあります。 たとえば、一部の電子書籍端末に代表されるように、色を表示する機能を持たないディスプレイも存在します。このような端末では、当然、 color: red; はその意図の通りには表示されません。 ユーザーによっては、視力の問題で、文
本稿は、2024年2月頃に書き溜めていたシリーズです。最後まで温存させるのが勿体ないので、未完成ですがそのまま公開します(公開日: 2025/9/21)。そのため、内容の重複や記述方針の不一致があるかもしれませんが、ご理解ください。 CSSの仕様を理解するために、1日ごとにテーマを決めて説明する企画2日目です。今日のテーマは「文書とボックス木」です。 文書 CSSの処理モデルにおいて、 文書 (document) とはCSSのスタイルが適用される対象のことです。これはほとんどの場合HTML文書なので、以降では文書はHTML文書のことであるとします。 DOM HTML文書の形式的な構造はDOMで規定されています。DOMにおいて、文書はノードの木構造として定義されています。 ノードはNodeクラスのインスタンスですが、Nodeには様々なサブクラスがあります。 この中でも重要なのが Elemen
本稿は、2024年2月頃に書き溜めていたシリーズです。最後まで温存させるのが勿体ないので、未完成ですがそのまま公開します(公開日: 2025/9/21)。そのため、内容の重複や記述方針の不一致があるかもしれませんが、ご理解ください。 CSSの仕様を理解するために、1日ごとにテーマを決めて説明する企画1日目です。今日のテーマは「仕様書」です。 仕様書 CSSはWebの標準化団体であるW3Cによって標準化され、各ブラウザベンダによって実装されている規格です。 標準化して挙動を仕様書として書き起こすことによって、Webブラウザ間の相互運用性が高まり、Web開発者も互換性の高い記述を心掛けてCSSを書くことができるようになります。 とはいえ、仕様書と実装の関係は必ずしも一方向的ではありません。「仕様書に記載される → 実装される」というシンプルな順番であるとは限らないのです。実装されたものにあわせ
主要な言語について、演算子の優先順位の設計を比較します。 自作言語の設計等に役立ててください。 算術演算 vs ビット演算 多くの言語では、算術演算がビット演算に優先します。 *, / +, - & | しかし、GoとSwiftではこれらの階層が混在しています。 *, /, & +, -, | 半環だと思えば似たようなもの、という発想でしょう。 単項マイナス vs 冪乗 冪乗の演算子 ** をもつ言語では、しばしば単項マイナスとの順序について特別なルールを持ちます。つまり、基数にマイナスがついた場合、それは項全体を反転させると考えます。この場合 -2 ** 2 は 4 ではなく -4 になります。 JavaScriptの ** は、基数が前置演算となることを禁止しています。自動的に項全体に適用されることもありません。 Perl, PHP, Pythonの ** は、基数についた前置演算を項
Node.js 24.0.0 でECMAScript source phase importsが動くようになりました。 (--experimental-wasm-modules が必要です) Node.jsエコシステムは様々なサードパーティーツールに支えられているので、Node.js自身が新しい機能をサポートしたからといってすぐさまアプリケーションやライブラリで採用できるわけではないですが、この機会に何が嬉しいのか説明しようと思います。 サンプル まず以下のサンプルコードを見てください。 本コードで重要なのは以下の3行だけです。 import source addModuleSource from "./add.wasm"; const addModule = await WebAssembly.instantiate(addModuleSource); console.log("123
本稿では、Proxyを使う際はオブジェクトの原理をよく理解した上で、PreventExtensions時の挙動とPrivate Identifierに気をつけましょうという話をします。 そもそもProxyは何なのか Proxy は Reflect と対をなすプリミティブAPIで、オブジェクトの低レベルプロトコルの操作を提供します。 Proxyは、オブジェクトの低レベルプロトコルをユーザーが実装できるようにします。 Reflectは、オブジェクトの低レベルプロトコルをユーザーが利用できるようにします。 そのため、Proxyを理解するにはまずオブジェクトの低レベルプロトコルを理解する必要があります。 オブジェクトとは何か { foo: "bar" } や [1, 2, 3], () => 42 がオブジェクトであることはすでに知っていると思いますが、ここでは定義に戻って確認をします。 オブジェ
WebAssemblyをちょっといじってみて思ったところをまとめてみます。 設計思想 WebAssembly/designに設計文書がまとまっています。特にHighLevelGoals.mdから読み取れるポイントは以下の4点です。 サンドボックス化された環境であること。 移植性があること。つまり、特定の実CPUアーキテクチャ等に依存しないこと。 少なくともC/C++の(十分に高速な)コンパイルターゲットとして機能すること。 安定した仕様を持つこと。 サンドボックスという観点からは、先行技術として以下のようなものが特筆に値します。 Webサンドボックス JavaScript および asm.js Javaアプレット Flash (ActionScript) NaCl, PNaCl Web以外のサンドボックス OSのユーザーランド、特にLinux userland これらのサンドボックスとの比
デザインパターンライブラリを作った JSRの話だけ読みたい人は読み飛ばしてもOKです。 JavaScriptのtry-catchはC++の影響を受けており、以下の特徴があります。 (A) throwは大域脱出的である。 (B) try-catchはブロック内の全ての例外副作用に対して一括で作用する。 (C) try-catchは文であり、値を返せない。 (D) TypeScriptにおいて、例外型は明示されない。 このうち (B), (C), (D) の問題を解決するため、RustのResultや類似のパラダイムをJSに輸入する試みがしばしば行われています。しかしこの解決手段にはいくつかの問題があり、 (E) rethrowの専用構文がないためボイラープレートが増える。 (F) 出力ストリームに対するwriteなど、戻り値を持たない副作用関数に対するエラーハンドリングが抜け落ちないようにL
以下のページに主要ブラウザのuser agent stylesheetへのリンクがまとまっています。 しかし、2024年2月時点で、これらは最新リビジョンへのリンクを参照していません。以下が現在の正しい最新版URLです。 Chromium (Chrome) のuser agent stylesheet 奇妙なことに、Chromiumのソースツリーの third_party/blink 以下の内容は、フォルダ名に反し、Blinkの正式な最新版のようです。 GitHub上の公式ミラーからもアクセスできます。 WebKit (Safari) のuser agent stylesheet
all: unset; などを使ってUAスタイルシートを消してまっさらな場所からスタイルを当てるのは気持ちがいいですが、アクセシビリティ等の観点から重要な分岐が見落とされる可能性があります。 ここではChromeのUAスタイルシートを参考に、検討しておいたほうがいい状態をいくつかリストします。 (もちろん、既存のUIコンポーネントライブラリの使用が可能であれば、それが最も堅牢な選択肢でしょう。) 参考 各ブラウザのスタイルシート HTMLのスタイルシート UAスタイルの中には、CSSのカスケードルールの範疇で実装されているものもあれば、レンダリングエンジンの特別処理として書かれていて作者スタイルシートでの上書きが不可能なものもあります。これはブラウザ実装により異なります。 スコープ UIコンポーネントを作るような場面を想定しています。したがって、要素名自体は固定として、その中で見落としがち
Xで出したクイズの解説です。 問題は次の通りです。 以下のJavaScriptの比較は常にtrueになるでしょうか? それともfalseになる可能性があるでしょうか? (そして、あるとしたらそれはどのような場合でしょうか?) JSON.stringify( eval( "(" + JSON.stringify(x) + ")" ) ) === JSON.stringify(x) ただし、以下の条件を仮定します。 Objectなどのビルトインの定義は汚染されていないものとし、evalはglobalThis.evalを指しているものとします 内側のstringifyがエラーになる場合は除外します 答え この出題をわざわざすることからだいたい予想がついてしまうと思いますが、これは「falseになる可能性がある」というのが正しいです。 問題は、具体的にどのような場合があるかです。 これについて、当
課題 Rustでシンプルな単一化を書くことを考えます。単一化は主に型推論の実装に用いられます。 ここでは以下の方針で実装します。 一階の単一化。 変数は非負整数のidで表現し、0から順に付番する。 変数以外の項はRustのADTを使った通常の木構造で表現し、ノードの共有は行わない。 変数参照の縮約は行わない。 この方針のもと実装すると、およそ以下のようなコードになります。 #[derive(Debug, Clone)] pub struct UnifyEnv { vars: Vec<Option<Type>>, } #[derive(Debug)] pub struct UnificationFailure; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Type { Var(usize), Constr { constr: u32, ar
何を作ったか これを作りました。 解決しようとした課題 「小説家になろう」は公式に「小説Atom」というフィードを提供しており、小説の最新話を読むにはこれで事足ります。 しかし、すでに多くの話数が投稿されているストーリーを一気に読むのは大変なことがあります。 このような場合に、一度にまとめて読み進めるのではなく、一定のペースで少しずつ読み進めていく仕組みがあると便利だと考えました。 仕様 配信方法 やりたいことは「一定のペースで、過去のエピソードを配信する」ということです。 このような更新情報を提供するには古典的な仕組みとしてRSS/Atomがあります。RSS/Atomによる最新情報の取得は以前ほどは広くは使われていないように思えますが、今でもフィードリーダーは生き残っています。特定のSNSに連携するよりは汎用的な形式のほうが応用の幅は広くとれます。また、RSS/Atomであればpush通
TLSの有無 言うまでもないことですが、httpsでは通信路をTLSを使って保護することが想定されています。[1][2] デフォルポート httpは80、httpsは443です。[3][4] 権威性 以降の説明に入る前に前提を確認します。本稿は「httpとhttpsの違い」と題されていますが、これはURLのスキーム部分のことを指しています。URLはリソースの所在を指すものであり、通信方法はそこから二次的に決まるものです。このことを前提に置きつつ権威性について説明します。 Webにおいて、所望のリソースにアクセスする方法はひとつではありません。このような方法のうち、リソースの所有者の制御下にある(第三者による加工などが行われていないと期待される)方法で取得することを権威的アクセスと呼びます。[5] どのようなアクセス方法が権威的とみなせるかについて100%客観的で統一的な指標があるわけではな
何が大変か? VSCodeはMSが作っているだけあってTypeScript統合がほぼ整っており、特に設定を頑張らなくてもそのままIDE機能が効くことが多いです。現代の多くのJavaScriptプロジェクトはこれで事足ります。 しかし、これには例外があります。Reactの実装は現時点ではFlowで書かれています。FlowはTypeScriptと同様のコンセプトを持つAltJS言語です。FlowはReactと同じくMeta(Facebook)製であるため、これまでReactでFlowが使われてきたのは一定の合理性があると言えるでしょう。 Flowの拡張子が *.js であることから、TypeScriptのIDE機能はFlowのソースコードに対しても反応します。文法が似ていることもあり、Go To Definitionなどの機能もある程度までは動作しますが、完全ではありません。また、エラー表示が
export type Bookmark = { id: number; url: string; comment: string; }; このファイルには型しか書いてありませんね。ということは、「型定義ファイル」として bookmark.d.ts という名前にするべきでしょうか。実はそうではなく、この場合は bookmark.ts とするべきです。 「型定義ファイル」とは、「どこか別の場所にある実装に型をつけるためのファイル」です。たとえば、以下のファイルは「どこか別の場所にある実装」に型をつけているから、 *.d.ts にするのは自然です。 いっぽう、 type Bookmark は別のどこかにある *.js の型を与えているわけではないので、 *.ts でよいです。 このように本来 *.ts であるべきものを *.d.ts にしてしまうことには問題があります。代表的な問題として型エラ
Rustで値の文字列表現を返すにあたって、 String を直接返すのではなく Display を実装するのが一般的です。この派生パターンとして以下の4つのパターンを紹介します。 基本: 文字列化を実装したいとき 文字列化をインターフェースに含めたいとき カスタム文字列化 カスタム文字列化をインターフェースに含めたいとき 基本: 文字列化を実装したいとき Displayを実装すると、文字列化できるようになります。 println!, format! などのフォーマット処理から呼べるようになるほか、 .to_string() というヘルパ関数が使えるようになります。 以下はプログラミング言語処理系において、「変数」をあらわす構造体に文字列化を実装する例です。 Playground pub struct Var(String); impl std::fmt::Display for Var {
本稿の目的 Rustに存在しない「クラス」をRustの既存機能の組み合わせとして表現することで、一般的なOOP言語とRustのデータ表現に対する考え方の違いと、各概念がどのように対応しているかを理解しやすくすることが主な目的です。 主な想定言語 C++, Java, JavaScript, Rubyのクラスを主に想定しています。 方針 サブタイピング Rustにはごく限定的なサブタイピングしかないため、クラスのサブタイピングに相当する変換は明示的に .as_ref() / .as_mut() として表現します。 Deref / DerefMut を使うことで、このような振る舞いを部分的に再現できる場合もあります。ただし、この用途でDeref / DerefMutを使うのは推奨されていません。 カプセル化 一般的なOOP言語では継承関係に基づいたアクセス制御 (protectedなど) が行
型推論オプション 型推論の結果が変わるもの。 ⭐strict ... 以下のセット alwaysStrict strictNullChecks T | null や T | undefined が T に縮退しなくなる。 例 strictBindCallApply Function の各種メソッドが any に縮退しなくなる。 例 strictFunctionTypes コールバック関数の引数が共変でもunifyするようになる結果、型変数の推論優先度が変わることがある。 例 strictPropertyInitialization noImplicitAny 宣言型がない場合にflow typeが使われる機会が増える。 例 noImplicitThis thisの宣言型がない場合に文脈から型が決定される機会が増える。 例 useUnknownInCatchVariables catch (
dyno (RFC3192) はopen traitのための仕組み (言い換えると、trait downcastingの仕組み) をライブラリレベルで実現する提案です。 できることのイメージ 例として、以下のようなトレイトを考えます。 (std::error::Error を説明のために簡略化したものです) // エラー型はこれを実装する pub trait Error { // エラーの文字列表現を取得する fn to_string(&self) -> String; } これを拡張可能トレイトにするのが本RFCの目的です。 実際の実装はライブラリレベルで行われていますが、わかりやすくするために「拡張構文として書くならこんな感じ」というイメージを先に説明します。 open traitとしての説明 次のように、定義済みのError traitを拡張できる仕組みであると説明できます。 ⚠️こ
いかにも既知な気がしますが、ぱっと既存の議論が探せないのでとりあえず書き出してみます。 ※用語は独自のものです。また、証明・定義は厳密に検証しているわけではないので誤りがあるかもしれません。 この定義でカバーできること 先頭 ^ 末尾 $ 肯定先読み (?= ... ) 否定先読み (?! ... ) 肯定後読み (?<= ... ) 否定後読み (?<! ... ) この定義でカバーしないこと 選択の左右の優先度 (r1|r2 vs. r2|r1) 最長優先と最短優先の区別 (r* vs. r*?) 基本の正規表現 基本の正規表現は通常以下のように定義されます。 \Sigma はアルファベットで有限サイズとします。 文字リテラル a (a は文字 a \in \Sigma) 空文字列 \epsilon と連接 R_1R_2 (R_1, R_2 は正規表現) 空集合 \emptyset と
事前条件も事後条件もテストも全部 assert!() でいいの? まあ、いいんじゃないでしょうかという話 Rustでは実行時表明とテスト表明の双方を同じ仕組み (panic機構) を用いて行います。 Rustを書くにあたって、この部分に違和感を覚えた人もいるのではないかと思います (多数派ではないと思いますが)。本稿ではこの違和感について分析し、Rustではそれで問題ないと確認することを目指します。 ※割とフワッとした話に終始します Resultとpanic Rustではエラー処理の方法としてResultとpanicの2種類の方法を提供しています。これは大まかに以下のように使い分けられます。 プログラムが想定しなければいけないエラー (ユーザーが誤った入力を与えた場合や入出力エラーなど) はResultを使う。 プログラムが想定外の状態に陥った場合 (意図しない配列の境界外参照など) はp
本稿では直和による多態性を実現する2つの機能、enumとtraitを拡張性の観点から比較します。 → Expression problem ※enumとtraitを使い分けるにあたってはパフォーマンス要件など他の条件も考慮するべきですが、本記事は多態性の観点のみ説明します。 数式 — enumによる例 本稿では数式をあらわすデータ型を例として扱います。enumではこのように定義されます。 #[derive(Debug)] pub enum Expr { Var(String), Add(Box<Expr>, Box<Expr>), Sub(Box<Expr>, Box<Expr>), Mul(Box<Expr>, Box<Expr>), Div(Box<Expr>, Box<Expr>), } impl Expr { pub fn eval(&self, vars: &HashMap<St
データをシリアライズするには、独自のフォーマットを定めるよりも、基本的な定義済みの構造を組み合わせてフォーマットを作るほうが望ましい場合が多いです。 そのような仕組みとしてJSON, S式, XMLなどが存在しますが、これらは 「基本的な構造」として何を選ぶか、という観点からそれぞれに個性を持っています。 本記事では、具体的な構文のことは基本的に忘れて、各フォーマットが採用するデータモデルの違いに焦点を絞って比較します。 JSON data JSON = Value data Value = -- Compounds Array [Value] | Object (Map String Value) -- Scalars | Null | Boolean Boolean | String String -- UCS-2 | Number IntegerOrFloat -- no NaNs
次のようなパッケージ (クレート) を作ったので解説します。 動機 Rustには所有権があるため、普通のswapパターンが動かない場合があります。これに対応するため、std::mem::swapという関数が用意されています。 let mut x = 'a'; let mut y = 'b'; std::mem::swap(&mut x, &mut y); assert_eq!((x, y), ('b', 'a'));
TypeScriptではデザインパターンとしてtagged unionによる直和がよく使われます。このときパターンマッチに相当する処理はswitchで行われますが、そこで直和に対する分岐が網羅的であることの保証を実行時と型検査時の両方で賢く行う方法がこれまでも模索されてきました。 今回、ヘルパー関数を導入せずにいくつかの問題を同時に解決する賢い方法を思い付いたので共有します。 コード これだけです。 // switch (action.type) { ... default: throw new Error(`Unknown type: ${(action as { type: "__invalid__" }).type}`); // .. } 以下、より詳しく説明します。 問題 TypeScriptではオブジェクトに type プロパティーを用意し、決まった文字列を入れることで直和を実現
次のページ
このページを最初にブックマークしてみませんか?
『Masaki Haraさんの記事一覧』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く