ダイナミックスコープをレキシカルスコープに直す。
2016年に作った Lisp (Scheme) インタプリタ、ダイナミックスコープだったまま放置していたのでレキシカルスコープに直した。
ダイナミックスコープとレキシカルスコープとは。
スコープの変数の参照のやり方の違い。
例を挙げると
(define x 123) (define (f) x) (let ((x 456)) (print (f)))
のようなコードでは、ダイナミックスコープでは 456 、レキシカルスコープでは 123 である。
大体の言語はレキシカルスコープで実装されている。わかりやすいので。
どうしてダイナミックスコープで実装してしまったか。
実行時の関数呼び出しを評価する際になって初めて環境オブジェクトを生成していた。よって外側の参照を行う際、呼び出し元の環境を遡って参照する=ダイナミックスコープになっていた。
kantele/eval.js at d85caa71fb5206f93b0912b9582e07f3bdb2003c · 45deg/kantele · GitHub
修正
関数(あるいはスコープ)が作られる際に環境を埋め込む。いわゆるクロージャを作る。 完全なインタプリタ型で実装していたので思ったよりかなり楽に実装できた(関数オブジェクトのコンストラクタの引数に加えるだけ) *1
Fixed: dynamic scope -> lexical scope · 45deg/kantele@966ec24 · GitHub
デバッガの実装まとめ(仮)
デバッガの内部について調べてるのでまとめ、追記するかも
- Linux の場合 ptrace が昔から使われている
- How Does a C Debugger Work? (GDB Ptrace/x86 example) - (gdb) break *0x972 gdb の内部(英語)
- ptraceシステムコール入門 ― プロセスの出力を覗き見してみよう! - プログラムモグモグ ichyny さんによる入門
- [Debug] ptrace によるデバッグ - th0x4c 備忘録 コード付きの解説
- マルチスレッドで gdb debug についての資料 → Non-stop multi-threaded debugging in GDB | Mentor Graphics Communities
- ptrace を用いたシステムコールをトレースするツールの strace もある
- Mac でも ptrace が使える? Windows は Windows API を使う *1
- ブレークポイントは ptrace の機能ではない
- 該当部分を SIGTRAP を生成するような命令に差し替える → 実行時に書き戻す。
- コード付きの解説 How debuggers work: Part 2 - Breakpoints - Eli Bendersky's website
まとめ
- [セキュリティ] OSSの脆弱性を探すためにやったこと // Speaker Deck
- [セキュリティ] Web Security Log: The proc/self/environ Injection
- procfs を使えば LFI で 環境変数を取れるという話
- CTF では基礎知識?
- procfs - Wikipedia
- [セキュリティ,機械学習*1] Tail attacks on web applications | the morning paper
- 断続的なリクエストによるDDoS攻撃で、その頻度等のパラメータ調整をフィードバック制御(カルマンフィルタ)でやる論文。
- カルマンフィルタについては How a Kalman filter works, in pictures | Bzarg
- [Web] Popmotion - A functional JavaScript motion library
- リアクティブなアニメーションライブラリ
- [プログラミング言語] A primer on Elixir Stream :: ActiveSphere - Bangalore based software consulting
- Elixir の Stream について。
- [プログラミング言語] Reflecting on Haskell in 2017
- 2017年のHaskellについての動向まとめ
- [システムプログラミング] GitHub - davmac314/dasynq: Thread-safe cross-platform event loop library in C++
- [システムプログラミング] GitHub - celrenheit/sandglass: Sandglass is a distributed, horizontally scalable, persistent, time sorted message queue.
- Go製のメッセージキュー
- [プログラミング言語] GitHub - jll63/openmethods.d: Open multi-methods for the D language. OPEN! Multi is cool. Open is great.
- D言語のマルチメソッドライブラリ
今週のまとめ
- [プログラミング言語] Carp | Veit's Blog
- ボローチェッカー付きの Lisp 方言
- [プログラミング言語] The Cell Programming Language
- Reactive Automata という Reactive な計算要素がある言語。C++にトランスパイルされる。
- [セキュリティ]
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages
- blackhat講演。URLパーサーにある脆弱性について。
- [数学] OSQP solver documentation — OSQP 0.2.1 documentation
- 凸二次計画問題ソルバ
- [アルゴリズム] A Library of Parallel Algorithms
- 並列プログラミングの便覧
- [プログラミング言語] Type-Safe GraphQL with OCaml (part 1) · Andreas Garnæs
- OCaml でつくる型安全な GraphQL ライブラリ
- [プログラミング言語] https://savanni.luminescent-dreams.com/page/haskell-app-monad
今週のまとめ
サボってたらどうして書かないんですか?*1と(暗に)言われたので書きます。
- [プログラミング言語] GitHub - exakat/php-static-analysis-tools: A reviewed list of useful PHP static analysis tools
- PHP の静的解析ツール一覧
- [プログラミング言語] GitHub - szktty/bran: A strongly-typed language with type inference running on Erlang VM, influenced by OCaml.
- [プログラミング言語] GitHub - go-ego/riot: Go Open Source, Distributed, Simple and efficient Search Engine
- Go言語製の分散検索エンジン
- [プログラミング言語] Towards Higher-Order Syntax of C Programming Language
- [プログラミング言語] Perl Regular Expression Matching is NP-Hard
- Perl の正規表現 で 3-CNF-SAT が解ける → NP-hard。 らしい。
- Ruby での翻訳 後方参照のある正規表現の能力 - まめめも
*1: 関係ないんですが、 電話猫 - LINE スタンプ | LINE STORE が発売されました
Coq 末尾再帰の等価性の証明
レイトレーシングを実装する際、光の反射の計算に再帰を用いる。擬似コードを以下に示す。
let ref f ... argN = let a = ~~~~ in (* 加算:光源など *) let b = ~~~~ in (* 乗算:反射での減衰など *) let finished = ~~~~ in (* 計算を終了するか *) if ( finished ) then a else a + b * (f ...)
しかし、このような実装ではスタックオーバーフローが起こる可能性がある。 (特に不偏レンダリングをする際) これを回避するためには再帰しないような関数に書き直す必要がある。
これはwhile を用いた C++ の例であるが、関数型っぽく実装したい場合は末尾再帰呼び出しに書き換える事が考えられる。
let ref f arg0 arg1 ... argN (s, t) = let a = ~~~~ in let b = ~~~~ in let finished = ~~~~ in if ( finished ) then s + a * t else f ... (s + a * t, t * b)
本当に等価なのか怪しいので Coq で証明する。Coq だと上のように停止するかわからない関数は書けないので適当な変数 n を導入し停止する関数にエンコードする。
(* 再帰 *) Fixpoint f (a b : nat -> nat) (n: nat) := match n with | O => a 0 | S n' => (a (S n')) + (b (S n')) * f a b n' end. (* 末尾再帰 *) Fixpoint f_tr (a b : nat -> nat) (n: nat) (acc : nat * nat) := match n with | O => (fst acc) + (a 0) * (snd acc) | S n' => f_tr a b n' ((fst acc) + (a (S n')) * (snd acc), (snd acc) * (b (S n'))) end.
あとは証明を行う。特に難しくない。*1。 肝は a
b
を一般化したままにしておくぐらいか。
Lemma tail_rec_equiv_st : forall (a b : nat -> nat) (n s t : nat) , t * (f a b n) + s = f_tr a b n (s, t). Proof. intros a b n. induction n. - intros s t. simpl. rewrite plus_comm, mult_comm. reflexivity. - simpl. intros s t. rewrite <- IHn. (* やるだけ *) rewrite Nat.mul_add_distr_l. rewrite mult_assoc, mult_comm. assert(H: forall x y z, x + y + z = y + (z + x)). { intros x y z. omega. } apply H. Qed. Theorem tail_rec_equiv : forall (a b : nat -> nat) (n: nat), f a b n = f_tr a b n (0, 1). Proof. intros a b n. rewrite <- tail_rec_equiv_st. omega. Qed.
この証明を行う上において、もっと簡単な fact
の末尾再帰の例を先に証明しそれを参考にした。
Fixpoint f (n: nat) := match n with | O => 1 | S n' => n' * f n' end. Fixpoint f_tr (n: nat) (acc : nat) := match n with | O => acc | S n' => f_tr n' (acc * n') end. Theorem tail_rec_equiv: forall (n : nat) (p : nat), p * f n = f_tr n p. Proof. intros n. induction n. - intros p. simpl. omega. - simpl. intros p. rewrite <- IHn. rewrite Nat.mul_assoc. auto. Qed.
*1: 僕は詰まりました
まとめ
- [プログラミング言語] Rust to WebAssembly, Made Easy – Lord i/o
- Rust から WebAssembly に変換する方法
- [プログラミング言語] A Taxonomy of Software Smells
- コードスメル (危険度の高いコード) の目録
- [プログラミング言語] Braid
- [プログラミング言語] Fable: JavaScript you can be proud of!
- F# to JS
- [Web] React Mosaic
- React でサイズ可変なウィンドウタイルを作るライブラリ
- [Web] Spirit - The animation tool for the web
- CSS Animation をキーフレームベースで制作するツール。プライベートベータ。
- [Web] Paw – A full-featured visual HTTP client
- [Web] Devhints — TL;DR for developer documentation
- 主に Web 技術に関するチートシート一覧