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でも似たような事を出