Tkr Blog
Profile image
Web Developer.
RSS
2022/04/04
実装したもの https://github.com/kgtkr/wjit $ cat ./sample.wjit func main() { var x = fib(10) in println(x); func_a(10); println(is_prime(3)); println(is_prime(4)); println(is_prime(5)); println(is_prime(6)); } func fib(n) { if (n < 2) { n; } else { fib(n - 1) + fib(n - 2); }; } func func_a(x) { println(x); if (x <= 0) { x; } else { func_b(x - 1); }; } func func_b(x) { println(x);
2022/03/27
ブログをNext.jsに移行した 今までGatsbyで作っていたブログをNext.jsに移行しました. 動機 Gatsbyの依存関係を久しぶりに更新しようと思ったら新しいメジャーリリースが出ていたり, 大量のプラグインを入れていたことが原因で移行が大変そうだったというのが動機です. Gatsbyはデータの処理にGraphQLを多用しているところなどあまり好きになれない部分があり使うのをやめたいと前から思っていました. またNext.jsはこれだけ有名なフレームワークなのに今まで一度も触ったことがなかったので使ってみることにしました. Reactやunified周りはそこそこ触ったことがあったので, 移行は比較的やりやすかったです. 大きな変更点 Gatsbyで動かしていた時はGitHubにpushしたらNetlifyでビルドが走りデプロイされるというよくあるお手軽構成でした. 今回は, 最近自宅k8sクラスタを立てて, argocdなどを導入したことでGitHubにpushしたらGitHubのWebUIをポチポチするだけでデプロイができ
2022/02/10
はじめに sqldefという目標とするスキーマを書くと, DBに接続して現在のスキーマと比較し, DBのスキーマが現在のスキーマに一致するように CREATE TABLE や ALTER TABLE などを実行してくれるGo製のcliツールがあります. 詳細はGitHubや作者のブログを見てください. これを使うことでスキーマファイルを1つリポジトリに置いておけばいいので, マイグレーションコードを手書きした時の, DBのスキーマの全体像が分かりにくいという問題が解決します. しかし個人的にはマイグレーションコードはリポジトリにコミットして, それを実行したいです. そこで今回はsqldefをマイグレーションコード生成ツールとして使ってみます. 簡単にいうとprisma.jsのmigrate機能のような使い方です(ドキュメント). prisma.jsは独自のDSLでDBのスキーマを定義し, それをDBのスキーマと比較し, マイグレーションコードを生成してくれます. しかし, 独自DSLを使う必要があり, ライブラリ依存です. 今回の方法は,
2021/11/06
実装したもの シンタックスハイライト、エラー報告、補完、フォーマットができるProcessingのLanguage ServerとVSCodeの拡張機能を実装しました。 リポジトリ https://github.com/kgtkr/processing-language-serverhttps://github.com/kgtkr/processing-language-server-vscode インストール 以下のリンクからインストールしてProcessing(現在4のbeta1とbeta2にしか対応していません)のパスを設定すれば使えます。設定した後に再起動すると自動でLanguage Serverがダウンロードされます。そのあともう一回くらい再起動が必要かもしれません(ここらへんは動作が不安定なので改善が必要ですね)。 https://marketplace.visualstudio.com/items?itemName=kgtkr.processing-language-server-vscode 作った動機 弊学科の授業で
2021/09/22
プログラミング言語の基礎概念を読んで実装したのでメモ。OCaml実装。間違っているところがあったら指摘して下さると助かります。 作ったもの コードを入力すると型推論結果を返すプログラムです。型チェック失敗時のエラーメッセージは未実装です。 例 関数合成する compose 関数を例にします。 let compose = fun f -> fun g -> fun x -> f (g x) in compose ↓ (let {3: {'2,'3,'4}(('3 -> '4) -> (('2 -> '3) -> ('2 -> '4)))} = (fun {0: {}('3 -> '4)} -> (fun {1: {}('2 -> '3)} -> (fun {2: {}'2} -> ({0}: ('3 -> '4) ({1}: ('2 -> '3) {2}: '2): '3): '4): ('2 -> '4)): (('2 -> '3) -> ('2 -> '4))): (('3 -> '4) -> (('2 -> '3) -> ('2 -
2020/09/16
対象読者 明大FMSのEP演習という授業で発表した内容の補足資料なので、同大の同級生を対象読者に基本的なところから解説しています。言語実装をしたことある人にとっては知っている話が多いかと思います。 ソースコード https://github.com/kgtkr/BarrageLCL ドキュメントもここにあります。今回はd8d1412をベースに解説していきます。 BarrageLCLの概要 Processing製の3D弾幕生成ライブコーディング言語です。実行環境だけでなく、編集環境も用意されています。自作言語×自作エディタですね。 以下のコードを見てください。 このコードは毎秒15回、初速度を (100cos(0.2i), 100sin(0.2i), 200sin(0.1i)) に、色を赤に設定して弾を発射するというコードです。i は何回目の実行かを表す変数です。 すると以下のように弾が発射されます。 なぜこれを? EP演習第一回のオープニングパフォーマンスで見たライブコーディング言語が面白かったことと、夏休みのEP演習で3D空
2020/09/02
初めに TypeScriptの型システムはチューリング完全なので何でも計算できます。 例えば繰り返し。 type Repeat<T, N extends number, R extends any[] = []> = R["length"] extends N ? R : Repeat<T, N, [T, ...R]>; // type A = ["x", "x", "x", "x", "x", "x", "x", "x", "x", "x"] type A = Repeat<"x", 10>; わーい。ちょっと数増やすか… // error TS2589: Type instantiation is excessively deep and possibly infinite. type A = Repeat<"x", 100>; あれ?(つらい) 再帰制限解除したいですね。しましょう。 注意 当然ですがプロダクトで使うことは想定していません、やめましょう。 バージョンなど [email protected]
2020/05/11
問題 https://atcoder.jp/contests/abc167/tasks/abc167_c 解法 解法としては各本を買う/買わないで全探索するとO(M2^N)で解けます。 C_n A_n_mは型としては[(Int, [Int])]になります。各要素の(Int, [Int])は単位元を(0, 要素が0の無限リスト)、演算をfstは足す、sndはzipして各要素を足すとするとモノイドになりそうですし問題を解くのに使えそうです。このようになる(Int, [Int])のnewtypeは(Sum Int, Ap ZipList (Sum Int))になります。ApはApplicative fとMonoid aからMonoid (f a)を作るnewtypeです。ZipListはpureをrepeat x、liftA2をzipして関数適用というApplicative実装を持つListのnewtypeなのでApと組み合わせると欲しいMonoidが得られます。 ところでnewtypeの変換にはcoerceという関数が便利です。安全に変換できる
2020/02/24
pick関数 lodashなどにはオブジェクトと抽出するプロパティ名の配列を受け取り、指定されたプロパティのみを含むオブジェクトを返すpick関数が存在します。以下のような関数です。 // { a: 1, c: 3 } pick({ a: 1, b: 2, c: 3 }, ["a", "c"]) 今回はこの関数に安全な型定義をすることを考えていきます。 単純な型定義とその問題点 まず思いつくのは以下のような型定義だと思います。 declare function pick<A, K extends keyof A>(obj: A, keys: K[]): Pick<A, K>; // ex1: { a: number } const ex1 = pick({ a: 1, b: 2, c: 3 }, ["a"]); // ex2: { a: number, b: number } const ex2 = pick({ a: 1, b: 2, c: 3 }, ["a", "b"]); // ex3: {} const ex3 = p
2020/02/06
以下のコードを見てください。 type HogeUnion = 1 | 2; function printHogeUnion(x: HogeUnion) { console.log(x); } HogeUnion型、つまり1 | 2であるxを受け取って出力するだけの単純な関数printHogeUnionを定義しています。何も問題がないコードです。 もしTSの型の健全性が壊されてxに1 | 2以外の値が入ってきた時にすぐ気付けるようにランタイム型チェックを行いたくなったとしましょう。例えばprintHogeUnion(0 as any)を実行すると0を出力するのではなく例外を投げるといった具合です。この時unreachable関数を定義し、printHogeUnionにランタイム型チェックのコードを追加して以下のようになります。 function unreachable(): never { throw new Error("unreachable"); } function printHogeUnion(x: HogeUni
2019/12/21
はじめに RustでWebAssemblyインタプリタを作ったのでその実装の話や、wasmの仕様についての記事です。 HListを使ったジェネリックプログラミングの話や、最後の方には「自作言語 on 自作wasmインタプリタ on 自作wasmインタプリタ」みたいな話も出てきます。 分かりにくい所や間違っている所は指摘してくださると助かります。 リポジトリ https://github.com/kgtkr/wasm-rs 作った成果物のリポジトリです。まだpublishはしていませんがクレートになっています。 cargoのexample実行に対応しているのでそれを見ればだいたい分かると思います。 今回はadc-2019-12-22というタグがついたコミットのソースを元に解説していきます。 https://github.com/kgtkr/wasm-rs/tree/adc-2019-12-22 仕様書 この記事では仕様書を読みながら順番に実装を解説していきます。 https://webassembly.github.io/spec/
2019/12/09
Rustにはcatch_unwindという関数がありpanicをキャッチすることが出来ます。 Rustのパニック機構 - 簡潔なQ しかしここから得られるエラー情報がかなり少ないです。キャッチして得られるResultのError型はBox<dyn Any>みたいな型ですが、これがほとんどStringまたは&strとなっており(今の所他の型を見ていませんが詳しい方教えて下さい)、確認した所スタックトレース情報やパニックが発生したソースの位置情報は入っていませんでした。例えば以下のコードはpanic testと出力します。 if let Err(e) = panic::catch_unwind(move || { panic!("panic test"); }) { println!("{}", any_to_string(&*e)); } fn any_to_string(any: &dyn std::any::Any) -> String { if let Some(s) = any.downcast_ref::<S
2019/12/08
資料 31回だったのに32回と勘違いしててURLが32になっていますが気にしないでください。ライブデモ多いので多分LT資料だけじゃよく分かりません。 https://gitpitch.com/kgtkr/slide-student-lt-32 LT動画 内容 自己紹介wasmに関する説明 watについて(watコード読みながら解説した)wasm(バイナリ)について(wasmバイナリ読みながら解説した) rustでwasmインタプリタ作った話 デコーダーエンコーダースタックマシン 自作言語 on 自作インタプリタ(ライブデモ)自作言語 on 自作インタプリタ on 自作インタプリタ(ライブデモ) 補足資料とか 成果物: https://github.com/kgtkr/wasm-rswasm仕様書: https://webassembly.github.io/spec/core/index.html自作言語などについて(去年のアドカレ) WebAssemblyでメモリアロケータを実装WebAssemblyでGCを実装するWebAssemblyに
2019/11/02
はじめに WebAssemblyにはbrという命令があります。 この命令はbr <label>という形になっており、<label>が示す制御構造に対して何らかの動作をします。 例えばブロックに対して使えばブロックを抜け、ループの中で使えばcontinueのような振る舞いをします。 wasmのループについてはκeenさんのWebAssemblyのloopはまりどころという記事を見てみて下さい。 なぜこのように制御構造によってブロックを抜ける働きをしたり、continueの働きをしたりするか仕様書を読んでいたところ理由が分かり面白いと思ったので記事にしました。 br命令 基本的にはbr 数値という形の命令です。この数値は相対的な値となっておりbr命令を囲っているすぐ外側の制御構造に対してなにかするときはbr 0と、その外側であればbr 1と...いうふうに指定します。 また、watでは制御構造に$labelをつけることでbr $labelと書けばbr命令がどの深さに関係なくその制御構造に対して命令を実行することができます。 例 関数に対して
2019/08/27
初めに この記事は型安全な型定義とそれが可能な実装に関する考察であり利用者側にとっての使いやすさなどは考慮していません。ここに型安全ではない例としてあげた、もしくそれと同じような定義となっているライブラリも型推論に頼っていれば基本的に安全な事と、使いやすさを考えると仕方ない部分があることは理解しておりそのようなライブラリに対する批判でもありません。 曖昧な知識で考えた自分用メモのようなものなので間違っている所がある可能性は高いですし参考にはしないで下さい。間違ってる所があればTwitterなどで指摘してくださると嬉しいです。 オブジェクトのキーの集合の値表現 以下のような関数定義があるとする。 function f<T extends object, K extends keyof T>(obj: T, keys: Keys<K>): Result<T, K>; この時型コンストラクタResultの性質によって場合分けし、Keys、つまりオブジェクトのキー集合の安全な受け取り型を考える。 またobj: Tとkeys: Keys<K>を
2019/07/16
TL;DR import { isT, isNotT, defineIsT } from "safe-type-predicate"; // isA: (x: "a" | "b") => x is "a" const isA = defineIsT((x: "a" | "b") => x === "a" ? isT(x) : isNotT() ); GitHub safe-type-predicate type predicate and its dangers TypeScript has a feature called type predicate. This is by coding the return value of a function that takes an appropriate type of value x and returns boolean as x is T. If true is returned, x is of type T, false This is a function that
2019/07/16
TL;DR import { isT, isNotT, defineIsT } from "safe-type-predicate"; // isA: (x: "a" | "b") => x is "a" const isA = defineIsT((x: "a" | "b") => x === "a" ? isT(x) : isNotT() ); GitHub safe-type-predicate type predicateとその問題点 TypeScriptにはtype predicateという機能が存在する。 これは適当な型の値xを受け取りbooleanを返す関数の戻り値をx is Tと書くことで、trueを返せばxがT型、falseを返せばそうでないことを表す機能である。 これによってユーザー定義関数で型ガードを行うことを可能にしている。 例えばunknown型、つまり任意の型を受け取りその値がstring型であるかを返す関数は次のようになる。 function isString(x: unknown): x is
2019/04/15
When type level programming, various errors occur.So we need to suppress it. This article introduces two ways to suppress errors. I checked with v3.4.2. Suppress type constraint error There are operations in TS that can only be of the type that satisfies the condition. Here are some examples. type F<T extends any[]> = T; type X = F<A>;// A require to extends any[] type Y = B["x"]// B require object type and have roperty named `x` However, even if it is known that the con
2019/04/15
TypeScriptの型レベルプログラミングでは様々な型エラーが発生するため、それを抑制しながら作っていかなければいけません。 今回はエラーを回避するテクニックを2つ紹介します。 v3.4.2で動作確認をしています。 型制約エラーを抑制する TSには型の型のようなものがあり、それを満たす型にしかできないような操作があります。 いくつか例を挙げます。 type F<T extends any[]> = T; type X = F<A>;// Aはany[]を継承していなければいけない type Y = B["x"]// Bはオブジェクト型で`x`というプロパティを持っていなければいけない しかしこのような条件を満たしていることが分かっていてもコンパイラが推論出来ておらずエラーになることがあります。 そのような時は以下のようなCast型を定義して使いましょう。 これはTはPを継承している時は分かっている時にCast<T, P>と書いて使います。 type Cast<T, P> = T extends P ? T : P; 例です。
2019/04/13
I made blog using GatsbyJS. I will write an English article. Blog Repository:kgtkr/kgtkr.net
2019/04/13
GatsbyJSを使ってブログを作ってみました。 これまで通りTwitterメインですが、長い文章はなるべくQiitaなどではなくこっちに書いていきたいなと思います。はてなブログは記事移行したら閉鎖します。 英語での発信も積極的にしていきたい。 ブログのリポジトリ:kgtkr/kgtkr.net
2019/04/12
この記事はTS3.4.3で動作確認をしています。 ハイパー演算子とは hyper(1,a,b)=a+b hyper(2,a,b)=a*b hyper(3,a,b)=a^b ︙ のような演算子です(雑) 詳しくはWikipediaを見て下さい。 定義だけ貼っておきます。 hyper(1,a,b)=a+b hyper(_,a,1)=a hyper(i,a,1)=hyper(i-1,a,hyper(i,a,b-1)) 型レベルタプル操作 型レベルのタプル操作を行うので以下の記事を読んでおくといいかもしれません。 TypeScript 3.0のExtracting and spreading parameter lists with tuplesで遊ぼう ちなみに今回は上の記事の型レベルタプル操作などをまとめた自作ライブラリtypeparkを使いますが機能は上の記事の通りです。 再帰制限回避テク FやGが複雑な関数だと以下のような書き方をするとコンパイルエラーが発生することがあります。 type Hoge<T>=F<Cast<G<T
2019/04/11
TypeScriptのランタイム型チェック TypeScriptにはランタイム型チェック機能がありません。 次のようなコードも正常にコンパイルされエラーが発生することなく動作します。 const x: string = JSON.parse("1"); これはパフォーマンスなどとのトレードオフなので仕方ないのですが、部分的に動的な型チェックをしたいときもあります。 このような時の解決策としてio-tsを紹介します。 io-tsのメリット JSON Schemaなどは型とスキーマを2つ書く必要があり大変です。 また大変なだけでなく型とスキーマが異なるといったバグを型システムでチェックすることが出来ません。 コードジェネレーターを使うことで解決できますが、TypeScript上で完結しないのでめんどくさいです。 このような問題はio-tsを使うことで解決します。 ただし再帰型については型推論の関係で型とスキーマを2回書く必要がありますが、型チェックでスキーマと型が違っていればコンパイルエラーが発生します。 基本的な使い方 import
2019/03/20
初めに 以下のコードはstateの値が変わった時どのような動作をすると思いますか? 本質ではないのでclearInterval等の処理は省略しています。 const [x, setX] = useState(0); useEffect(() => { setInterval(() => { console.log(x); }, 1000); }, []); このコード、思うようには動かずstateの値が変わってもずっと0が出力され続けます。 何故でしょうか?JSのクロージャをある程度理解している人なら分かると思います。 コンポーネント関数が呼ばれた時の動作を考えてみましょう。 初回呼び出しではuseState(0)を呼ぶとxに0という値が入ります。 useEffectのコールバックも呼び出されます。この時setIntervalのコールバックはxという変数をキャプチャしています。 2回目以降の呼び出しではxは現在のstateです(このコードだけでは具体的な値は分からない) useEffectの第二引数が[]なのでコールバック
2018/12/09
問題 https://joi2019-yo.contest.atcoder.jp/tasks/joi2019_yo_e 解法 まず{(L,R)}の前処理をします。 サイズNのリストを用意して自分が入っている区間[L,R]のうちRが最大のもので初期化をします。どの区間にも入っていなければ0です。 ただ普通に実装するとO(MN)で間に合わないので工夫が必要です。 まず{(L,R)}(以後LRと呼ぶ)をR→Lの優先順位で降順ソートします。 次に用意したリストを右から埋めていく(既に埋めた所は埋めない)をしていくとO(N)となり間に合います。 疑似コードは以下のような感じです。 let m_list = make_vec(init=0,len=N); my_sort(LR) // my_sortはLRをR→Lの優先順位で降順ソートする関数 let cur = N; for (l, r) in LR { for i in range(l,min(cur-1, r)) { m_list[i] = r; }
2018/12/02
はじめに Haskellでwasmにコンパイルする言語を実装してみたので記事にしました。 LLVMなどには依存せず直接wasmを出力します。 また、現段階ではエラー処理などは未完成なので間違ったコードを入力するとコンパイラがクラッシュするか不正なwasmを出力するかその他色々おかしな事が起きたりします。 メモリアロケータはこの記事で実装したものを使っています。 GCは実装は一応終わっているのですが(記事)まだコンパイラ側の対応が終わっていません。 このようにまだかなりひどい状態ですが少しずつ改善していけたらなと思っています。 リポジトリ https://github.com/kgtkr/cl8w サンプルソース 先にサンプルを見たほうがイメージしやすいと思うので置いておきます。 まず実行の為のJSのソースです。 main.wasmはコンパイル結果、./memory/memory.wasmはメモリアロケータです。 数値のprintも欲しいのでprint関数をimportしています。 エントリポイントはmain.wasmのmain関数とな
2018/12/01
初めに この記事でメモリアロケータを実装したので今回はGCを実装してみます。 様々な事情でアロケータのコードが少し変わっているのでソースはここを見て下さい。 大きな変更点はfreeの返り値でfreeしたブロックのポインタを取得出来るようになった事くらいです(ブロックが消失した時は0が返ります)。 今回もwatでとりあえず動く物を作る事を目標に実装していきます。 方針 参照カウントとmark and sweepを組み合わせたような実装をします。 ローカル変数などからの参照のみを参照カウントで管理し(これはコンパイラがinc_countとdec_countを呼び出すコードを挿入する必要がある)、参照カウントが0でないブロックをルートセットとして扱いmark and sweepします。 ブロックには2種類あり「データブロック」と「参照ブロック」です。 これはmark and sweepで使用し、データブロックの場合はbodyをただのバイト列として扱うのでmark and sweepの再帰的なマークには影響しません。参照ブロックの場合はbodyを全
2018/12/01
初めに WebAssemblyには線形メモリがあるだけで動的なメモリ管理機能はありません。 ライブラリを使うことも出来ますが、今回はmallocとfreeを実際に実装してみます。 方針 パフォーマンスは気にしない。とにかく動くものを作るwasmのテキストフォーマットであるwatで実装する 仕様 mallocを呼び出すとメモリブロックが作られます。 メモリブロックにはヘッダ部とボディ部があり、mallocはボディ部の先頭アドレスを返します。 このボディ部の先頭アドレスをブロックのポインタとします。 メモリアドレスは0から始まり、ボディの前にヘッダが入ることからブロックのポインタが0になることはないことがわかるかと思います。 ブロックの間には隙間がなく、またmallocは要求サイズ以上確保するのではなくぴったり要求サイズ確保するものとします。 ヘッダのメモリ配置 |サイズ|名前|説明| |:--|:--|:--| |1|flag|終端ブロック:0、未使用:1、使用中:2| |4|size|ボディのサイズ| |4|prev|前ブロックのポイ
2018/10/13
何かツイート流れてきたので 証明 n, an,\ an, aが整数の時、n0+n1+n2n^0+n^1+n^2n0+n1+n2、すなわちn+n2n+n^2n+n2が6a+56a+56a+5の倍数にならないことを証明する 6a+56a+56a+5の倍数はkkkを整数とすると(6a+5)k(6a+5)k(6a+5)kと表す事が出来る 1+n+n21+n+n^21+n+n2が6a+56a+56a+5の倍数だと仮定すると、 1+n+n2=(6a+5)k1+n+n^2=(6a+5)k1+n+n2=(6a+5)k n, an,\ an, aが555の倍数の時、p, qp,\ qp, qを整数としn=5pn=5pn=5p、a=5qa=5qa=5qとすると、 (左辺)=1+5p+(5p)2=1+5p+25p2=1+5(p+5p2)\begin{aligned} \text{(左辺)} &=& 1+5p+(5p)^2 \\ &=& 1+5p+25p^2 \\ &=& 1+5(p+5p^2) \end{aligned}(左辺)​===​1+5p+(5p)21+5p
2018/10/02
Extracting and spreading parameter lists with tuples TS3.0で追加されたタプル型をより強力に扱うための機能です。 型パラメーターとして受け取ったタプルを展開したり出来ます。 基本的な構文は解説しないので公式ブログあたりを見ておいて下さい。 参考 Tuples in rest parameters and spread expressions #24897 このPRで紹介されているものを主に解説していきます。 注意 TypeScript3.0.xにはバグがありコンパイラやエディタ(正格にはtsserver)がクラッシュすることがあるのでTypeScript3.1.xを使って下さい。 前提知識 TSの基本的な型システムの知識宣言的なリスト操作(Haskellなどでやるあれ) 用語 この記事では、type F<T>=...;を関数のように扱うので、Fを関数、Tを引数、タプル型をリスト、type V=...;を値と表現します。 紹介 Head リストの先頭の要素を返す基本的な関数で
2018/09/19
メモ -- リスト(右結合) [1,2,3,4,5] ++ ([6,7] ++ [8]) [1,2,3,4,5] ++ [6,7,8] -- コスト2(合計2) [1,2,3,4,5,6,7,8] -- コスト5(合計7) -- リスト(左結合) ([1,2,3,4,5] ++ [6,7]) ++ [8] [1,2,3,4,5,6,7] ++ [8] -- コスト5(合計5) [1,2,3,4,5,6,7,8] -- コスト7(合計12) -- 差分リスト(右結合) fromDiffList(toDiffList [1,2,3,4,5] <> (toDiffList [6,7] <> toDiffList [8])) fromDiffList((\a->[1,2,3,4,5] ++ a) <> ((\b->[6,7] ++ b) <> (\c->[8] ++ c))) fromDiffList((\a->[1,2,3,4,5] ++ a) <> (\x->(\b->[6,7] ++ b) ((\c->[8] ++ c) x))) fro
2018/09/18
はじめに TypeScript(TS)には高カインド型(HKT)がありません。一応提案がありますが… しかし様々な機能を組み合わせればHKTを実現することが出来るのでそれの方法と解説を行います。 この記事ではHKTとは何かなどといった解説は行いません。表記は*->*のような表記を使います。 またfp-tsというライブラリを参考にしています。 使う機能 interfaceのマージ(Declaration Merging) TypeScriptでは同名のinterfaceを複数定義出来ます。 そしてこれらは自動的にマージされます。 例えば次の2つの宣言は同等です。 export interface Hoge { x: number; } export interface Hoge { y: number; } export interface Hoge { x: number; y: number; } そしてこの機能は別ファイルや別モジュールで既に定義されているinterfaceを拡張する事も出来ます
2018/09/10
やり方 準備 export type TypeEq<A, B> = (<T>() => T extends A ? 1 : 2) extends (< T >() => T extends B ? 1 : 2) ? true : false export function assertType<_T extends true>() {} export function assertNotType<_T extends false>() {} 色々複雑になっていますが、これは any や union、never などに対応するためです。 ここらへんの型は少し特殊なため、このようにしないと正常にテスト出来ません。 テストの書き方 assertType<TypeEq<1, 1>>() assertNotType<TypeEq<1, 2>>() テストが正しくなければコンパイルエラーが発生します。 例 import { TypeEq, assertType, assertNotType } from "./test" asse
2018/09/03
spread operator interface Tweet{ id:string; user:string; body:string; } //tweetはTweet型、userはUser型とする let tw={...tweet,...{user:user}}; この時の変数twの型を定義したい時どうしますか? 素直に書いてみましょう interface Tweet2{ id:string; user:User; body:string; } 面倒ですね。プロパティが増えるともっと大変です。 typelevel-ts typelevel-tsという便利なライブラリがあります。 このライブラリを使うとこう書けます。 import {ObjectOverwrite} from 'typelevel-ts'; type Tweet2=ObjectOverwrite<Tweet,{user:User}>; これだけです。 他のライブラリ type-zootypical というライブラリもあります。
2018/08/30
競プロで標準入力のパースがめんどうだったのでマクロ作りました。 AtCoderのRust(1.15.1)でテスト済みです。 ソースコード https://github.com/kgtkr/procon-lib-rs/blob/master/src/parser.rs 使い方 事前準備 標準入力を全て読み込む let text = { let mut s = String::new(); io::stdin().read_to_string(&mut s).unwrap(); s }; 例 入力値 5 10 20 1 a 2 b 3 c 4 d 5 e 1 2 3 4 5 input!(text=> (n:usize) (a:i64 b:i64) {n;list:(i64,#)} (arr:[i64]) ); assert_eq!(n, 5); assert_eq!(a, 10); assert_eq!(b, 20); assert_eq!(list, vec![(1,"a"
2018/08/22
今回のデータ (id,update) ページング処理は大変 要素が追加されていくだけのデータであればページング処理は簡単です。追加されたdateなどをキーにしてlimitするだけで出来ます。 しかしupdateをキーにしたい時などは上手いことしないと抜けが発生します。 まあやったことある人なら分かると思います。 elasticsearchのscrollAPIとか使えば出来ますが…あれスナップショットの有効期限とか設定する必要があるので好きじゃない。永続的に使いたい 今回やること add(id=1,update=1)add(id=2,update=2)add(id=3,update=3)get(key=INF,limit=2)update(id=1,update=4)get(key=2,limit=2) 単純にやると 1,2,3 |id|update| |:-|:-| |3|3| |2|2| |1|1| 4(result) |id|update| |:-|:-| |3|3| |2|2| 5 |id|update| |:-|:-| |
2018/08/17
CK/CS/TK/TSに認証情報を、LIST_NAMEにリスト名を入れて実行すると同期されます import os import tweepy def list_split(n: int, list): return [list[i:i+n] for i in range(0, len(list), n)] # 環境変数取得 ck = os.environ["CK"] cs = os.environ["CS"] tk = os.environ["TK"] ts = os.environ["TS"] list_name = os.environ["LIST_NAME"] # 認証 auth = tweepy.OAuthHandler(ck, cs) auth.set_access_token(tk, ts) api = tweepy.API(auth) # リストを検索 list_id = None for x in api.lists_all(): if x.name == list_name: li
2018/06/23
初めに TypeScript(以下TS)はJSに静的型システムを取り入れた言語です。 しかしTSの型システムには多くの穴があり、知らないと型の整合性を壊してしまいます。(型システムが健全でないという) そこで今回はそのような操作をまとめてみました。 間違え、不足等があればコメントで指摘してくださると助かります。 この記事の目的 この記事は「TSの型システムの穴」を批判することが目的ではありません。 実行時のオーバーヘッドを無くすことや利便性などとのトレードオフであることは理解しています。 TSを書く多くの人が「このような操作をすると型の整合性が壊れることがある」ということを理解した上で使ってほしいというのがこの記事の目的です。 型システムの健全性とは 静的言語に限ると、「コンパイルが通ったなら実行時に型情報と値が矛盾しない事が保証されている」事を言います。 例えば「number型の変数に"hello"が入っている事は絶対にありえない」といった感じです。Javaなど多くの静的型付け言語の型システムは健全、つまりこのような事が保証されている
2018/06/18
AGC024-A Fairnessの考察を頑張って書いたので残したいなと。 解説の解き方とは全く違う解き方をしたけど答えは同じになったので数学って凄いなと思いました(こなみ) あとwolframalphaってのが凄い。 複雑な式変形とか漸化式も自動で解いてくれる。競プロでDPしたい時とか使えそう。 って事で考察です。 k回操作後のa,b,cの値をそれぞれ fa(k),fb(k),fc(k) とする a,b,cはfa(0),fb(0),fc(0) を表す事とする 操作を行っていくとa,b,cはそれぞれ fa(0),fb(0),fc(0)=a,b,c fa(1),fb(1),fc(1)=b+c,a+c,b+c fa(2),fb(2),fc(2)=2a+b+c,a+2b+c,a+b+2c fa(3),fb(3),fc(3)=2a+3b+3c,3a+2b+3c,3a+3b+2c fa(4),fb(4),fc(4)=6a+5b+5c,5a+6b+5c,5a+5b+6c となっていく fa(k),fb(k),fc(k)のa,b,cの係数を (fa(
2018/06/16
ABC100で水色になりました。せっかくなので色々振り返ってみようと思います 競プロを始めるまで 主にWebプログラミングをやってました。というか今もやってますし、ずっとこっちがメインです。 Webと競プロはかなり文化が違うので競プロはかなり戸惑いました。 かなり昔にpaizaとか少しやった記憶ありますが全く解けませんでした。 初めてのコンテスト 初めてのコンテストは9/23の「CODE FESTIVAL 2017 qual A」、たまたまTLに流れて来たちょくだいさんのツイートに反応したらリプとフォロー貰えて嬉しかったので試しに参加してみました。 言語はJS、結果は1完で初期レート14。流石に無理だと思いしばらく競プロは放置していました。 初めてのABC 12月頃になると、何故か競プロerとかなり関わるようになりました。そして12/23に始めてのABC、「ABC083」に参加しました。 結果は3完。思っていたより解けたので楽しくなってきてABCは毎回出るようになりました(今の所ABCは皆勤です)。途中でAPCも出ました。 Rust
2018/03/21
初めに けんちょんさんの↓の記事の10問をScalaで解いてみました https://qiita.com/drken/items/fd4e5e3630d0f5859067 せっかくScalaで書くので変数の再代入、破壊的変更とfor/whileを一切使わずにやってみます。 テンプレート object Main{ def main(args: Array[String]){ if (sys.env.getOrElse("TEST", "")=="1"){ println(test()); }else{ val input=io.Source.stdin.getLines().mkString("\n"); println(solve(input).trim()); } } def solve(input:String):String={ input.split(" ").map(_.toInt).sum.toString() } val tests=Li
2018/01/01
初めに 継承が必要ない場合は他の方が書いた下記記事を参考にして下さい。 https://qiita.com/nwtgck/items/bbfd6e3ca16857eb9c34 必要な物 ts-copyable:上で紹介されていたnpmパッケージ applyMixins関数:ここからutils.tsにコピペしておいて下さい。export忘れずに。 実装の方針 mixinを使う。 実装 import Copyable, { PartialMap } from "ts-copyable"; import { applyMixins } from "./utils"; export abstract class Base<C extends Base<C>>{ abstract readonly a: number; abstract readonly b: string; abstract copy(partial: Partial<Base<C>>): C; abstract mapCopy(partial: Part
2017/12/02
tc39のリポジトリを中心に気になる提案をまとめます。 do expressions(stage-1) リポジトリ https://github.com/tc39/proposal-do-expressions 概要 関数型言語のようにifやtry、switchなどを式のように扱えるようにする為にdo式を追加しようという提案です。 例 let b = true; let x = do { if (b) { 'hoge'; } else { 'foo'; } }; assert(x === 'hoge'); その他 「doいらなくね?普通にifなどを式として扱おうぜ」みたいなissueがあがっています。 https://github.com/tc39/proposal-do-expressions/issues/9 何故これではダメなのかはよく分かりません。後方互換性的な問題があるのでしょうか? optional chaining(stage-1) リポジトリ https://github.com/tc
2017/12/02
strictNullChecks時の改善 今まではmapやforEach関数に渡すコールバックの第一引数がT?でしたが、v4ではTになりました。 これによってstrictNullChecks時でも!が不要になりました。 例: //v3以前 x.map(x=>x!+1); //v4 x.map(x=>x+1); v3以前もxにundefinedやnullが渡されることはなかったのに型定義はT?で気持ち悪かったので修正されてよかったです。 Recordが型安全になった const MyRecord = Record({ x:1,y:2 }); const myRecord = new MyRecord({}); //v3以前は以下のコードのコンパイルが通る //v4では型エラーになる myRecord.get('a'); 今までは型安全じゃなかったのでRecordを使うのは避けていたのですが、これによって安心して使えるようになりました。
2017/11/18
bind operatorとは func.call(obj)をobj::func()と書けるシンタックスシュガーです。 ::obj.funcと書くとobj.func.bind(obj)となる構文もありますが今回は不要なのでスルーします 今までのJavaScript ここでは例として引数の文字列を2倍して返す関数twoを作ります function two(str){ return str+str; } 呼び出し two('x');//'xx' 問題点 この程度なら特に問題はありません。 しかし、文字列加工の処理などで以下のような事になってしまう事ありますよね? z(y(x(str))); まず括弧の対応が分かりにくいです。 そして関数はx→y→zの順に呼び出されるのに、見た目はz→y→xと逆になってしまいます。 プロトタイプ拡張は? 名前の衝突などの危険があるので使いたくない。 bind operator function two(){ return this+this; } 呼び出し "x"::two(
2017/11/06
普通に 普通に読み込むとエラーになります。 app.ts import * as hoge from 'hoge'; 推奨 ソースフォルダに適当な名前.d.tsファイルを作って以下の内容を書きます。 types.d.ts declare module 'hoge'; あとは普通に読みこめばOKです。 app.ts import * as hoge from 'hoge'; ワイルドカード ワイルドカードも使えます。 types.d.ts declare module '*'; 非推奨 これでも一応出来ますが、あまりおすすめはしません。 app.ts declare function require(path: string): any; const hoge = require('hoge'); 参考 https://github.com/Microsoft/TypeScript/issues/6615
2017/09/10
普通に書く let arr1:(number|string)[]=['a','b','c',1,2,3]; let arr2=arr1.filter(x=>typeof x==='string'); arr2にはstringしか入ってないはずなのに型は(number|string)[]になってしまいます。 型ガード let arr2 = arr1.filter<string>((x): x is string => typeof x === 'string'); これでarr2はstring[]になります。 注意 let arr2=arr1.filter<number>((x): x is number => typeof x === 'string'); このような事をしてもコンパイルエラーにはなりません。 arr2の実際の型はstring[]なのにTypeScriptはnumber[]と認識します。 キャストと同じように危険な操作なので注意しましょう。 他のライブラリ immutable.jsやrxjsでも似たような事を出
2017/09/06
構文エラー ()=>{x:1} 長い ()=>{return {x:1};} こうしよう ()=>({x:1})
2017/08/30
余計なタグとは 下記のようなテンプレートがあったとします。 //<my-msg>コンポーネント <div>{{msg}}</div> //使う <my-msg [msg]="'はろー'"></my-msg> reactやvue.jsの場合以下のように出力されます。 <div>はろー</div> しかしAngularの場合は以下のように出力されます。 <my-msg><div>はろー</div></my-msg> つまり余計なタグとは<my-msg>など独自コンポーネントのセレクターの事です。 一般的な場合の回避方法 selectorをdiv[myMsg]と指定し、テンプレートを以下のようにすることで回避する事が出来ます。 //定義 {{msg}} //使用 <div myMsg [msg]="'はろー'"></div> しかし、この方法はASTの再起では使えません。 (正確には使えないことはないがNodeの種類^2コピペしないといけないのでしたくない) 解決方法 ng-templateとngTemplateOu
2017/04/01
解決法 innerHTMLに設定するHTMLはデフォルトでサニタイズされるようになっており、iframeタグが自動的に除去されるのが原因でした。 サニタイズされるのはjavascriptだけだと思っていましたが、iframeも駄目みたいです。 import { DomSanitizer } from '@angular/platform-browser'; constructor(private sanitizer: DomSanitizer) {} let innerHTML = this.sanitizer.bypassSecurityTrustHtml(html); 注意 サニタイズすると、iframeだけではなくjavascriptも埋め込み可能になるのでXSSには注意して下さい。 参考 Security - GUIDEDomSanitizer - API