netflix in train 4
1
chef's table シーズン5を見た
ていうかこれシーズン5なのね、今気づいてしまった。
これは料理のドキュメンタリではなく、シェフのドキュメンタリである。
だけど「シェフの」と言ってしまうのも変に感じる作品だった
確かに主体の職業はシェフであることに間違いない。
だけど、客がいて料理があっての労働的側面よりは文化的な側面が強調された作品だった。
シェフという職業を通して食文化をとらえてきた人のドキュメンタリだった。
シーズン5がそういうテーマなのかもしれない
2
ある生活に結びついた文化をとってきた時に、食文化の存在は大きい
だけど文化としての料理が何をさすのかはあやふやで、レシピをさすだけなのか、家庭で出された事実をさすのか、ある料理店をさすのかはわからない。
ありきたりだが日本で肉じゃがという料理を考えた時に、家庭で出されている事実はあっても代表的なレシピは存在はしない。
過去の肉じゃが発明時のレシピが今の肉じゃがを基礎づけてはあっても今の肉じゃがをさすとは到底思えない。
だけど普遍的に人々は存在を認識はしていて、それこそが文化としての料理なのかもしれない。
そのような中、料理店を構えて自分の作った肉じゃがが”肉じゃが”だと示していく行為は、一見各々が自分で料理する中で生み出す肉じゃがと変わらないように思えるが、それこそが文化として引き継ぐ行為なんじゃないかと思った。
あくまでふわふわした存在から形を作り出しそれを示していく行為をしてくれているのがシェフなんじゃないだろうか。
当然、職業かどうかは関係ないが
鮭に対するアンサー
1
先日作った鮭の昆布締めに対する考察
経緯
鮭は油が多いしサクのまま巻くので長時間寝かせる必要があるのでは?という考えから24時間かけたが、昆布と鮭自体のにおいで田舎っぽくなってしまった。
ので、調味料を足していい感じにする
## 2
試してそんなだったもの
日本酒と塩
アルコール飛ばしてないと調味料としては微妙かも
煎り酒は時間がかかるので断念
マヨネーズ
全てをふっ飛ばす。昆布締めの意味なし
たまり
シンプルに醤油
悪くないけど鮭と醤油はちょっと違うかな
結局両方グルタミン酸なので旨味がバッティングしてるような
タイムと塩
一口目がタイムで後味が昆布、意味がない ディルがあったらな〜みたいな気持ち。ディルは常備してない
レモン汁と塩
ちょっと酸味が強すぎるかも
3
良かったやつ
エシャレット
エシャレットを鮭で巻いて、たまりを少し塗ったり塩振ったり
玉ねぎ感覚で使ったが苦手な人は無理かも知れないけど、さっぱりしてて田舎臭さが消えた
オリーブオイル、塩、胡椒、バルサミコ酢
これが一番合った。後から昆布の旨味がしっかり味わえるし鮭自体の味もしっかりしている。 酸味が大事に感じる。けどレモン汁ではダメで酢酸が必要説。 今あるバルサミコ酢は結構マイルドなやつで甘めなのでそれもあっている感がした。
bs-winstonを作ろうとする過程
1
winstonjsありますよね。jsのlogライブラリ。
BuckleScriptから使いたくなりません?
というわけで、作りながら書いていきます。
今回は作る過程を描く感じで完成してpublishはしないです。
2
README
を読めばぼんやり使い方はわかると思うので、まずはtsの型定義から見ていきます。
https://github.com/winstonjs/winston/blob/master/index.d.ts
createLogger
に色々オプションを渡すとLogger
が出てくる感じです。
今回注目して欲しいのがlevels
optionで、これがかなり胆になってきます。
型的にはこれですね
interface AbstractConfigSetLevels { [key: string]: number; }
objectで表現されたMap<string,number>
型なんですが、winstonはこれのkey情報を使ってmeta的にLoggerにmethodを生やしてきます。
つまり
levels: { hoge: 0, fuga: 1, }
というオプションを渡せばlogger.hoge
やlogger.fuga
みたいなmethodが生えるわけですが、それに対して型をつけるのは厳しいのでその部分は諦めます
ただ、どのlevelがlogに使えるかやどのlevel以上のlogを出力するかというオプションに関わってくるので上のlevelsオプションは作る必要があります。
2
logに使うlevelを文字列で渡す方法がありますが、そんな安全じゃない方法は取りたくないので今回はそれにうまく制約をつけていきます。
イメージとして、 log `Alert "message"
みたいな感じなれば嬉しいですね
ただ、どのようなlevelが使えるかというところはカスタマイズできるように作れるようにします。
Variantからstringにする部分を自動生成するppxが最初から入っているのでこれを使っていきます
一旦Syslogに対応するということで
type t = [ | `Emerg [@bs.as "emerg"] | `Alert [@bs.as "alert"] | `Crit [@bs.as "crit"] | `Err [@bs.as "error"] | `Warn [@bs.as "warning"] | `Notice [@bs.as "notice"] | `Info [@bs.as "info"] | `Debug [@bs.as "debug"] ] [@@bs.deriving jsConverter]
こういう感じにしていきます。
上記から本来はlevels
オプションを生成したいわけですがそれはmetaプロになっちゃってきついのです。あとlevelの順序を定義する必要もあります。
なので一旦どのlevelが使えるかというenabled
という概念を用意してt list
にします。
let enabled = [
Emerg; Alert;
Crit; Err;
Warn; Notice;
Info; Debug]
そしてここからlevelsを生成できます。
let levels = enabled |> List.mapi (fun i l -> (Level.string_of_t l, i)) |> Js.Dict.fromList
結果は
{ emerg: 0, alert: 1, crit: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7 }
こうなります。
3
そういえばFFIの部分を書いてなかったので書いていきます。
winston_internal.ml
type transport (* ここのオプションは諸事情で一部省略 *) type mk_console_transport_option = { eol: string [@bs.optional] } [@@bs.deriving abstract] external console_transport: mk_console_transport_option -> transport = "Console" [@@bs.new][@@bs.module "winston/lib/winston/transports/index"] (* winston本体 *) type mk_option = { levels: int Js.Dict.t; level: string; transports: transport array; } [@@bs.deriving abstract] type winston external create_logger: mk_option -> winston = "createLogger" [@@bs.module "winston"] type mk_log_entry = { level: string; message: string; } [@@bs.deriving abstract] external log: winston -> mk_log_entry -> unit = "" [@@bs.send]
これはもうこんな感じとしかいえないですね。
4
あとは組み合わせると一旦は動くのですが、levelのカスタマイズができません。
そのためにcreate_logger
をFunctorにします
module type LogLevel = sig type t val string_of_t : t -> string val enabled : t list end module Make(Level: LogLevel)(Conf: sig val transports: Winston_internal.transport list val level: Level.t end) = struct type t = Level.t type log_entry = { message: string; level: Level.t; } let _levels = Level.enabled |> List.mapi (fun i l -> (Level.string_of_t l, i)) |> Js.Dict.fromList let w = Winston_internal.(create_logger @@ mk_option ~levels: _levels ~level: (Level.string_of_t Conf.level) ~transports: (Conf.transports |> Array.of_list) ) let log level message = let entry = Winston_internal.mk_log_entry ~level: (Level.string_of_t level) ~message in Winston_internal.log w entry end
こうすることでLogLevel
を実装すればいい感じのLoggerモジュールができる設計になります。
Syslogモジュールは
module Syslog = struct type t = [ | `Emerg [@bs.as "emerg"] | `Alert [@bs.as "alert"] | `Crit [@bs.as "crit"] | `Err [@bs.as "error"] | `Warn [@bs.as "warning"] | `Notice [@bs.as "notice"] | `Info [@bs.as "info"] | `Debug [@bs.as "debug"] ] [@@bs.deriving jsConverter] let enabled = [`Emerg; `Alert; `Crit; `Err; `Warn; `Notice; `Info; `Debug] let string_of_t x = tToJs x end
という風に定義できるので、
module SyslogLogger = Make(Syslog)(struct let transports = Winston_internal.([console_transport @@ mk_console_transport_option ();]) let level = `Debug end)
SyslogLogger
はこのように生成できます。
使用例
let () = SyslogLogger.log `Emerg "yabai";;
LogLevelさえ満たせばいいのでNpmLogLevelのようなものを作れば以下のようなnpm log levelにも対応することできます。 https://github.com/winstonjs/triple-beam/blob/master/config/npm.js
5
実はwinston-transport
(上記のconsole_tranport)に対してもlog levelが設定できるのですが一旦TODOにしました。
またwinstonのformat optionのFFIを書くのがちょっと骨が折れるのでこれもTODOにしています。
昆布締めアンボックス
1
昨日仕込んでおいた、サーモンの昆布締めをアンボックスしていきます
ちなみに、これを見てサーモンの昆布締めが案外いけるっぽいのでtryしました。
2
3
サクだったので24時間巻いておいたというのもあるかもしれないけど、
正直、なんか田舎臭さというか
一口目のファーストインプレッションが柿の葉寿司っぽい、、、
(祖父母が奈良の人間で幼少期に度々奈良に連れていかれ、やたらと奈良では柿の葉寿司を食わされ鯖の柿の葉寿司が苦手だった自分は鮭の柿の葉寿司ばかりを食べていた記憶が唐突にフラッシュバックする)
一旦落ち着いて薬味とかタレとかソースとかの方向性を考えることにした。
もともとサーモンなので玉ねぎとマヨネーズで👍みたいなのを考えていたのだけど、昨日のカレーに玉ねぎを全部使ってしまってない(愚か)&マヨ合わんなって即なった
4
というわけで、色々つけながら何があうか試していきたいと思っていたが時間がかかってきたので一旦アンボックスだけにしました。
内容なさすぎ
続編書くしかない
カレー
1
カレーの説明をすると、自分の好きな食材をスパイスで煮込んだものです。以上。
材料
2
野菜系の処理をしていきます
玉ねぎはみじん切りして電子レンジへ
こんな感じ
セロリも同等の操作を加えます。
ホールトマトは手で潰して、煮詰めていきます
はい
これがゴール
3
次は肉です
牛すじは煮こぼして
洗う
せせりにも同等の操作を加え切りました。
4
スパイス、一番難しい
クミン、ターメリック、カイエン、カルダモン、あとレッドアイ
ニンニクとエシャロット
5
その他の素材として
昆布だしを凍らせてあったもの
ペコリーノロマーノ
余談ですが、イタリア料理のドキュメントを見ていたら、イタリア人はペコリーノをFORMAGIOのカテゴリに入れてませんでした。
formagioはチーズをさすと思ってたのですが、牛の乳から作られているのに限るのかもしれない。
いい感じになったら全てを投入して、パルミジャーノレジャーがぶっこまれてます。
6
ライスを炊いてませんでした、、、、
netflix in train 3
1
最近見てるのはこれ
Hip-Hop Evolution | Netflix Official Site
HipHopの歴史が雑にわかって便利フィルム
間違ってシーズン2から見はじめてしまったので、今シーズン1を見ている。
2
よくあることだが「HipHopとは〜」みたいに語り出すオタクに人々はなってしまう。
まぁでもこのHipHopっていう部分にJazzとかReggaeとかPopの名がつく音楽ジャンル以外を入れても成り立ってしまうことから音楽とオタクの相性というのは切り離せないものではあるかもしれない。
そして、この作品は明らかにHipHopオタクの顔立ちをした職業ラッパーが「HipHopとは〜」をガッツリ歴史からやってくれる最高のアイテムである。
3
HipHopって難しい。中学生か高校生の頃に辞書、多分電子辞書でHipHopとは何かを調べたことがある。
当時の辞書はないからネットの辞書で調べるとこんな感じ
1970年代前半ごろから、ニューヨークの路上で始まった、音楽・ダンス・ファッションを中心とする黒人文化。建造物の壁や地下鉄の落書き(グラフィティアート)、アクロバットのようなブレークダンス、音楽面ではラップやスクラッチなど、貧しい若者たちがお金を使わずに楽しめる娯楽を生み出した。
確かにだいたいこんな感じだった。
当時「なんだよ、全然違う、よくわからん」確かにそんな気持ちになった。
だってネットの発達してない当時にHipHopと認知できる範囲って「Yo」「ターンテーブル」「DJ」「MC」「ラップ」「音楽は鳴り続ける....」
そら、HipHop自体の極々Surfaceしかふれることができないから変な認知になる。僕に限った話ではなく世間一般として。
オレンジレンジとか麻波25をHipHopとかいってしまうのもしょうがない(これは自分の話じゃないよ、一応)
遠いアメリカのカルチャーの話だからね、今でこそアメリカといっても東海岸と西海岸で違うけどさぁ、みたいなオタク発言できるけど。
これは中学時代の自分をウマヅラハギみたいな顔した音楽の先生の授業中から連れ出して一晩かけて見せて教育させる作品である。
4
「一般人がHipHopと認知しているメジャーなJ-POP」っていう単語、ちょっとdisが入っている言い方だけどまぁよくある「これはHipHopじゃない」騒動
すでにアメリカでも1970年代にやっていてちょっと面白いなって思った。
TypeScriptのunknown型
1
3.0から入ったunknown
型がある
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html
というかunknown
型が入ったこともあってmajor versionが上がったという認識をしている
2
コードベース中にJSON.parse
をanyで受けているところをunknownにしてみるか〜と思って試したがうまくいかなかった
function main(x: unknown): string { if (typeof x !== 'object') { throw new Error('x'); } if (x === null) { throw new Error('x'); } // この時点でxが{}まで絞れる // (1) typeof x.y typeof x["y"] // (2) // if ('y' in x) { // x.y // } }
結局 1, 2で詰んでしまう。
まだtypeのnarrowがうまく効かなくて、issueはある状態。
自分の期待しうるunknown
にはまだ遠くてJSON.parse
の返り値に使うのは、真面目に書こうとする限り厳しいなぁという気持ち。