ベクトルの次元って?
◯次元ベクトルとかいう言葉をネットで見かけて 「あれ?ベクトルの次元ってなんだっけ」 とよくわからなくなりました

2 次元なら (10, -3) みたいに 2 数字があって二次元平面上の任意の座標を表せるやつだっけ?
つまり 1 次元は単純な数字 1 つだけで通常の数値と一緒?

ただ配列のことを言語によっては Vector と表現してたはず
Hack とか C++ とか

そう考えると 2 次元ベクトル= 2次元配列で [[1, 2], [3, 4], [5, 6]] とかのこと?
ただ 2 次元になると Matrix と呼ばれる気もします
1 次元だから Vector で Vector (配列) の要素数=次元と考えるのがあってるようにも思えます

数学っぽい話は難しいですね
文字列を N 文字ごとに分割したい 他
文字列を N 文字ごとに分割したい

const splitNchars = (str, n) => str.split(new RegExp(`(.{${~~n}})`)).filter(e => e)

splitNchars("abcdefg", 2)
// ["ab", "cd", "ef", "g"]

文字列を N 文字ごとに改行したい

splitNchars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 13).join("\n")
// abcdefghijklm
// nopqrstuvwxyz
// ABCDEFGHIJKLM
// NOPQRSTUVWXYZ
// 1234567890

文字列を N 個に分割したい

const splitNstrings = (str, n) => {
const arr = splitNchars(str, Math.ceil(str.length / n))
return [...arr, ...Array(n - arr.length).fill("")]
}

splitNstrings("abcdefg", 2)
// ["abcd", "efg"]
Nodist で yarn 使うときのパス
Windows に Nodist で Node.js を入れて yarn でパッケージをグローバルインストールすると自分でパスを通さないといけません
普通に Nodist をインストールすると 「C:\Program Files (x86)\Nodist」 にインストールされます
node.exe や npm.exe は 「C:\Program Files (x86)\Nodist\bin」 に保存されます
npm でグローバルにインストールしたパッケージのコマンドもここに配置されます
npm で yarn を入れたあとに確認してみると

user1@pc MINGW64 /c/Program Files (x86)/Nodist/bin
$ ls -1
bin/
etc/
node.exe*
node_modules/
nodist*
nodist.cmd
nodist.ps1
nodist.sh*
nodist_bash_profile_content.sh
npm.cmd
npm.exe*
yarn*
yarn.cmd
yarnpkg*

ここにはパスが通ってるので yarn コマンドは使えます
yarn でパッケージをグローバルインストールしたものはこのフォルダではなくそのさらに内側の bin フォルダにコマンドが配置されます
yarn で parcel をグローバルインストールしてみると

user1@pc MINGW64 /c/Program Files (x86)/Nodist/bin
$ ls bin -1
parcel*
parcel.cmd
parcel.cmd.ps1*
parcel.ps1*
parcel.ps1.cmd
parcel.ps1.ps1*

parcel はパスが通ってないのでそのままでは使えません
「C:\Program Files (x86)\Nodist\bin\bin」 にパスを通せばどこでも yarn でインストールしたツールが使えるようになります
Python のクラスの継承
クラス名のあとのカッコに親クラス名をいれる

class X:
def __init__(self):
self.a = 10

def method():
return 1

class Y(X):
def __init__(self):
self.b = 20

print(vars(Y()))
# {'b': 20}

print(Y().method())
# 1

それだけだと親クラスの初期化処理が行われなくて vars の結果に a が存在しない
初期化されてないだけで継承されてるので method メソッドは使える

他言語で言う super の実行が必要
なくてもエラーはないけど初期化されない

super() は親コンストラクタを表してるわけじゃないので super() で取得できるインスタンスの __init__ メソッド呼び出しが必要

class X:
def __init__(self):
self.a = 10

class Y(X):
def __init__(self):
super().__init__()
self.b = 20

print(vars(Y()))
# {'a': 10, 'b': 20}

子クラスの方で __init__ を書かなければ自動で親クラスが実行される
子クラスで __init__ を定義して初期化するなら 必要あるときだけ親クラスの初期化メソッドを実行できる
実行したくないならしないことができる

class X:
def __init__(self):
self.a = 10

class Y(X):
pass

print(vars(Y()))
# {'a': 10}

実行タイミングも自由に指定できる
self を使う前とか最初じゃなくていい

class X:
def __init__(self):
self.a = 10

class Y(X):
def __init__(self):
self.a = 100
super().__init__()
print(self.a)

Y()
# 10
Liri OS
なんとなく fedora の派生ディストリを眺めたら Hawaii OS というのを発見
なんでハワイ?
ハワイっぽいデザインなのかなと見てみたら

Hawaii is now Liri OS
Hawaii merged with Papyros and is now Liri OS.

http://hawaiios.org/

Liri OS にマージされたみたい
これもはじめて聞いたけど UI のデザインがよさそう
スクリーンショット一覧を見てみてもモダンな感じ
ロゴは折り紙でや名前もわりと好きでちょっと興味あり

Hawaii OS が fedora 派生だったんだからこれも fedora 派生?と思ったのに調べてみると Arch ベースらしい
fedora 以上に新しいのをすぐに取り込む分問題も多いらしいし迷うところ

UI を揃えるために独自にいろいろなソフトウェアも用意してるみたいでリポジトリがいっぱい
https://github.com/lirios
liri ブラウザなんてのもある
VS Code の Python 拡張がメモリ使いすぎ
VS Code の Python 拡張を使うとメモリが使用どんどん増えていく
制限なく増えて 10GB 超え
この辺からは物理メモリに乗らなくなってきて PC の動きが重くなってくるから強制的にプロセス落としてるけど自動で再起動するし しばらくしたらまたメモリが 10GB くらい使ってる
さすがに 10GB 使うのが正常とは思えないし 定義ジャンプ機能使ったらずっとロード中になってるしバグっぽい
バージョンは最新の (2019.1.0) だし しばらくは無効にして使うしかないかなぁ
バイナリファイル中の文字列が半角スペース区切りになってる理由
exe とかのバイナリファイル中でテキストを探すとよく目にするのが半角スペース区切りになってる文字列
"abcd" が "a b c d" という感じ

ビルドしたファイルにローカルのパスが入ってたりしないか探したりするのですが探しづらくて困ります

バイナリファイル中のテキストはそういうふうに入ってるものとなんとなく思ってましたがなんでこんな面倒なことしてるんだろう?
わざわざ検索対策にそんなことするというのは考えにくいです

考えていてひらめいたのが Unicode (UTF-16) だからというもの
バイナリファイル中に見つかる文字はアルファベットばかりで日本語はほぼ見つからないです
あってもちゃんとした意味のある文字列になってないです
UTF-16 ではアルファベットなどは sjis や utf-8 と同じ数値を 0 パディングしたものです
U+0061 が a で U+0041 が A です
1 バイトずつ保存したら 00 と 61 のようになるので エディタで見ると 00 の部分はスペースで 61 の部分が a と表示されて半角スペース区切りというふうに見えると考えられます

試しにエディタで開いてそれぞれの文字コードを見てみると半角スペースは普通の半角スペース (U+0020) ではなく U+0000 になってました
U+0000 は NUL であって半角スペース文字じゃないのでエディタによっては別表示かもしれません

日本語が表示されないのは「あ」は U+3042 ですが 30 と 42 は 0B になってしまうからです
エディタで UTF-16 として開くを実行すれば半角スペースなく表示されますし日本語も表示されます
これで検索しやすくなりました

一応最初にバイナリファイルをエディタで開いたときにエンコーディングをいろいろ試してはいたのですが UTF-16 にすると UTF-8 に比べて文字化けのような変な漢字が大量に出てきて これは違うなと思っていたのですが本当のバイナリデータの部分がそう見えるせいでテキスト部分はちゃんと表示されていました
Python で「,」で終わると
dictionary だったのを個別の変数にコードを修正したときに「,」を消し忘れてたのですが動いてました

こういうの⇩
a = 1,
b = "foo",

Python ってカンマあっても動くんだ
複文みたいな機能があって カンマのあと何もないから何も処理しないってことかな
JavaScript などで ; をいっぱい書いても動くのと同じようなものかな

と思ってたら あっても意味がないというのじゃなく別の意味になってました
カンマで終わるとタプルになります

a
// (1,)
b
// ('foo',)

という感じです
一時的に動かすだけのコードだったのであってもいいならそのままでのつもりだったのですが ちゃんと消さないとダメですね
product ジェネレータ
複数の配列の掛け算的な組み合わせを出力
2 つの配列で 2 重ループで回すようなやつ
任意個数の配列に対応してる
速度求めるなら N 重ループしたほうがいい

function* product(...args) {
if (args.some(e => !Array.isArray(e) || !e.length)) throw new Error("Each argument must be an array.")

function* sub(state, args) {
const [arr, ...subargs] = args

if (!Array.isArray(arr)) {
yield state
return
}

for (const item of arr) {
yield* sub([...state, item], subargs)
}
}
yield* sub([], args)
}

例)
[...product([1, 2], [3, 4], [4], [10, 20, 30])]

// (12) [Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4), Array(4)]
// 0: (4) [1, 3, 4, 10]
// 1: (4) [1, 3, 4, 20]
// 2: (4) [1, 3, 4, 30]
// 3: (4) [1, 4, 4, 10]
// 4: (4) [1, 4, 4, 20]
// 5: (4) [1, 4, 4, 30]
// 6: (4) [2, 3, 4, 10]
// 7: (4) [2, 3, 4, 20]
// 8: (4) [2, 3, 4, 30]
// 9: (4) [2, 4, 4, 10]
// 10: (4) [2, 4, 4, 20]
// 11: (4) [2, 4, 4, 30]

for(const [a, b] of product([1, 2], [3, 4])){
console.log(`a = ${a}, b = ${b}`)
}
// a = 1, b = 3
// a = 1, b = 4
// a = 2, b = 3
// a = 2, b = 4
Shift+Enter
Chrome で Google の検索フォームなどのテキスト入力中に Shift-Enter を押すと新しいウィンドウで結果のページが開かれる
タブじゃなくてウィンドウ
URL バーのところでも同じ

Firefox だと URL バーだと新しいタブで開く
URL バーの右側の検索フォームや Google のページなどでは効果なし

Vivaldi だと URL バーの右側の検索フォームや Google のページでは新しいタブで開く
URL バーだと効果なし
PHP も Nginx にしようかなー
https://news.mynavi.jp/article/20181108-720142/

Nginx のシェアが 4 割超えたらしいです
徐々によく見るようになってるなぁ とは思ってましたがここまでとは

Apache って安定してる感はあるけど ほとんど変わらず新しくなにかできるようになったりとかは全然ないですしねー
一応年数回のアップデートはあるようですけど ちょっとした修正だけのようで大きな機能が増えるメジャーアップデートはないです
http://archive.apache.org/dist/httpd/?C=M;O=A
https://www-eu.apache.org/dist//httpd/CHANGES_2.4

それに個人的には Apache 設定ファイルが読みづらくてあんまり好きじゃないです
Apache 使う理由はほぼ PHP が楽に使える点ですけど (静的ファイルのホスティングなら Nginx のほうが得意らしい) それも最近は PHP-FPM という Fast CGI 版が流行りつつあるみたいで これを使うなら Nginx にしても問題なさそうです

Nginx にしてみようかな
hyperHTML だと順番が意味がある
select で option が hyperHTML の機能で生成される場合に value 属性で選択中の値を指定ができないように hyperHTML の ${} は順番に実行される
JavaScript で順に処理されるものなので書く順番で結果が変わる場合もある

bind(document.body)`
<e-lem mode=${"foo"} values=${{x: 1}}>${"bar"}</e-lem>
`

これは

elem.mode = "foo"
elem.values = {x: 1}
elem.textContent= "bar"

と同じこと

HTML みたいな定義型のものに見えるから 順番変えても問題なさそうに見えるけど mode と values の順番が変わると実行順も変わる
values が代入時に mode の値を使って shadowDOM 内を書き換えるのなら 順番によって結果も変わる

コンポーネント側でどんな順番でも同じ結果になるようにしてれば対処は可能
values を内部的に保存しておいて mode 変えると再度 values を設定して shadowDOM 内の更新をするとか

無駄な処理が増えて mode と values 両方変えると更新も 2 回必要になる
けど hyperHTML での定義順に依存したくないならそうするしかない
e-lem コンポーネント自体も hyperHTML で作っていれば setter は常に render して再描画する作りになってることが多いと思うのでそこまで気持ち的に無駄なことしてる感はなくなる
bluebird って ES2015 Promise より速かったんだ
ES2015 になってから結構経つのにまだ bluebird を使った Promise をわりと見かけます
古いものはともかく コードは class 構文をつかうなど ES2015 構文で書かれているにもかかわらずです
標準に比べるとキャンセルとか機能は少し多めですが 標準で組み込まれてる機能があるならそっちのほうがパフォーマンスは優秀だと思いますし Promise は特に内部的に違いがあって JavaScript で完全に再現できないものもあります
Promise.resolve().then() の非同期処理は timeout とはまた少し扱いが違うなどです
標準なものにも 現在の状態 (すでに resolve されているか) がわからないなど不便なところは無いとは言えませんが Promise の仕組み自体を JavaScript で作るよりは標準のものを使ってそれをラップして機能追加するほうが良いように思います

しかし 調べてみたらちょっと意外でした
標準 Promise より bluebird のほうが 高速らしいです
https://softwareengineering.stackexchange.com/questions/278778/why-are-native-es6-promises-slower-and-more-memory-intensive-than-bluebird
bluebird の Promise が ES2015 の仕様に完全準拠してるわけじゃないというのが理由みたいです

ただ それも Node.js 10 でネイティブの Promise が高速化したので bluebird のほうが速いとは限らないようです
もう 10 の LTS が開始しましたし いまから bluebird にしようかと考える必要はないかもしれません
Qrunch よさそう?
Qrunch という新しいサービスが最近できたみたいです
https://qrunch.io/

Qiita と個人ブログの間を目指してるとか
Qiita みたいに「これはふさわしくない」とか言い出す面倒な人がいなさそうで気軽に書けそうですね
アカウントでも作って見よっかと思ったのですが ちょっとした技術メモ書くのがココなわけで いろいろ使い分けると自分でどこに書いたかわからなくなって探すのが大変そう
いまでも一応ブログ 2 つと Gist に別れてるので使ってみたいけど悩みどころ

ところでこのサービスって個人開発みたいですね
作るだけならともかくちゃんと公開して運用・アップデートしていってるのはすごいと思います
私なんてその時の思いつきであれこれ作るものの作ったまま放置で結局自分でも使わず作って満足なものがいっぱい……
ただ使う側からすると急にサービス終わってしまったりとかいう心配もちょっとあったり
使ってみるかもうちょっと考えてみることにします
WebLocks API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API
https://developer.mozilla.org/en-US/docs/Web/API/Lock

Web Lock API というのを見つけた

きっかけはこの記事

JavaScriptでデッドロックを作ってみた

Promise で await とかしてるとデッドロックになって先に進まなくなることあるよねーと思って開いてみたら全然違った
こんな機能も実装されたなんて

ちなみにこの記事書いた人ってこのサイトの管理人さんみたい
最近は見てないけど昔 JavaScript 初心者のときにはお世話になったなぁ
懐かしい
見たいページがエラーが起きる
サービスっていうほどでもなくてホームページの延長的なものでそこが提供してる情報の検索ができるみたいなページ
その情報が見たいのになにかエラーで見れないです

ウェブページなので元のソースが github とかにあればこっちで直して見れるのにすごく思います
とは言っても作ってる人は github とは無縁そうな感じのところだし仕方ないけど

ホームページくらいなものでもオープンソースにしておけば見たい人が勝手に直してくれたりしていいんじゃないのって思いました
見れないのも不便なので全部ローカルにコピーして minify されたの読んで動かすかなぁ……

JS 合併とか言うから期待したのに
JS が合併とかいうニュースを見かけて Node.js とブラウザがとうとう?コレは期待!
と思ってたのに

Node.js と JS Foundation

らしいです

JS Foundation?? どこだよそれ
ブラウザ系は ECMA とか whatwg とか W3C とかいろいろ名前あるけど そんな名前はなかったような
調べてみたら jQuery とかライブラリ管理してるところで 元 jQuery Foundation

JS を代表してるかのようなを名前を名乗るほどのところでもないですし Node.js と対等とは思えません
なんか期待に反してどうでもいいような話題でした
input の datetime-local では valueAsDate が使えない
使えるのは date のみ

d: <input type="date">
dtl: <input type="datetime-local">

get
d.value = "2020-01-01"
// "2020-01-01"
d.valueAsDate
// Wed Jan 01 2020 09:00:00 GMT+0900 (日本標準時)
dtl.value = "2020-01-01T00:00:00"
// "2020-01-01T00:00:00"
dtl.valueAsDate
// null

set
d.valueAsDate = new Date()
// Sat Oct 06 2018 20:55:17 GMT+0900 (日本標準時)
d.valueAsDate
// Sat Oct 06 2018 09:00:00 GMT+0900 (日本標準時)
dtl.valueAsDate = new Date()
// Uncaught DOMException: Failed to set the 'valueAsDate' property on 'HTMLInputElement': This input element does not support Date values.

"2020-01-01T00:00:00"
形式しか使えないのも面倒だし対応してほしいなぁ
Chrome が 69 にならない
win7 の PC の Chrome が 68 のままだったからアップデートしようとバージョン画面に行ったら
再起動してくださいってボタンが出てたので押したんだけど
ウィンドウ閉じて一瞬でまたウィンドウが出てきてバージョンは 68 のまま
いったんちゃんと終了してプロセス一覧にないことも確認
そこから起動してもやっぱり 68 のまま
何回やっても一緒だし 69 にならない

ついでにあまり使ってない win10 の PC もやってみたら問題なく 69 になった
……けどデザインが昔のままで 69 からの Firefox っぽいタブにはならなかった
Vivaldi のバージョンが 2 になった
アップデート来てるのを見つけたのでアップデートしてみたらメジャーバージョンアップだったみたいで バージョン 2 になった

とは言っても 見た目は特に変わらないし普段使ってる機能も変わりないみたいで特にいつもどおり
changelog 眺めてみたけどメジャーアップデートっていうほどの大きい変化もない気がする

Chrome バージョンは "Chrome/69.0.3497.102"
Chrome の最新は Chrome/69.0.3497.100 だから微妙にこっちのほうが新しい?
Thunderbird の mintrayr の代替
サンダーバードを常駐化させるためのアドオン MinimizeToTray revived
最小化するとタスクバーから消えてタスクトレイに収まってくれるもの

便利なのに Thunderbird 60 にアップデートすると使えなくなりました
WebExtension に移って既存のが使えなくなってるのが原因みたい

Issue ができていて 読んでみるとフォークして動くようにしてくれてるバージョンがあるみたい
いずれ廃止予定だけど現状で実現できる方法が一応残ってるようです

リポジトリ
アドオン

ここから xpi を落としてインストールすると最小化でタスクトレイに収まるようになりました
ただ アイコンが右クリックできないです
コレに対する Issue はクローズしてるのでアップデートされてないだけかも

それと公式にサポートしてという要望も出てました
https://bugzilla.mozilla.org/show_bug.cgi?id=1486221

完全に WebExtension になるとこの一時的な代替アドオンも動かなくなるし 本来こういう機能はアドオンじゃなく本体がサポートしておくべきだと思うので標準機能になってもらいたいものです
youtube が一時停止する
最近 youtube で作業用 BGM 流してると途中で止まることがある
エラーというわけじゃなく普通に一時停止されてる
全体が暗めになって真ん中にダイアログで一時停止したって書いててボタン押せば再開はできる
だけど BGM だからバックグラウンドのタブだしわざわざ開いて止めるの結構面倒

拡張機能で自動でそのボタン押すことはできそうではあるけど止まってからボタンでるから一瞬音楽が途切れるはず
広告じゃないから広告ブロッカー入れてみても起きた

アフィリエイトとかあるから機械的に再生数稼ぐのを対処するためだと思うけど普通に再生してるユーザに迷惑かけないでほしいな
有名どころ http client をコンプリートしそう
いろいろライブラリを使うものを作ってて http client が各ライブラリごとに別の使ってて有名どころ全部入ってそうな気がしてきた
request, superagent, axios が使われてて 自分で使うものは node-fetch
Webサーバは hapi 使ってるから wreck

http client に限らず同じことするのに別ライブラリがいっぱいあって初回起動に 10 秒近くまたされる
コード変えてももう一回アクセスするだけで更新される PHP ってけっこう便利だったんだなぁって思った
super に渡す関数内で this を使えない
class A {
constructor(){
this.x()
}

x(){}
}

class B extends A {
x(){
console.log(1)
this.value = 1
}
}

new B()

これは問題ないコードです
A のコンストラクタ中で this.x を呼び出して B の x メソッドが呼び出され this.value を更新しています

しかし

class A {
constructor(fn){
fn()
}
}

class B extends A {
constructor(){
super(() => { this.value = 1 })
}
}

new B()

こっちはエラーです
this を使う前に super を呼び出さないといけないというものです
先に super を呼び出して入るものの super の処理が終わる前に 中で this を使う処理を呼び出すとダメみたいです

fn 呼び出しを 「Promise.resolve().then(fn)」 にしてあとで実行させると エラーはでないですが 「new B()」 の時点ではまだ実行されてないのでその後の処理に影響が出ます

super を呼び出していればその中で実行されるものはエラーにしないでほしいです
というか super 呼び出し必須という制限すら不要だと思います
やっぱり class 構文は使わないほうが扱いやすいですね
uws が消された
ちょうど消された頃に知ったのですが忘れてたので short の方に

WebSocket ライブラリの socket.io のソースをみていたら ws という別の WebSocket ライブラリを発見
engine.io が WebSocket のコア部分のライブラリかと思ったら engine.io が中で ws を使ってるみたい

socket.io って結局 ws のラッパー?
よく見ると ws 以外にも uws というのがあって switch 文でどっちを使うか切り替えてる

https://github.com/socketio/engine.io/blob/master/lib/server.js#L108

調べてみたら C++ で書かれた速度重視版で ws と基本的互換性があるとか
npm をみたら deprecated になってた
https://www.npmjs.com/package/uws

見つけたときはちょうどなったばかりで 99.0.0 というバージョンもあって どうなってるんだろう?と思って調べてたらこんなページが

https://www.reddit.com/r/node/comments/91kgte/uws_has_been_deprecated/

Google 翻訳で軽くみた感じでは 作者が npm の考えに賛同できなくてパッケージの公開をやめたみたい
問題のあるバージョンでも消すことができないというのが嫌だったとか
マイナーバージョンアップの 10.148.2 で中身が空のパッケージをリリースしたせいで確認せずアップデートして一部ではトラブルにもなったみたい

使ったこと無いパッケージだったけどこんな事が起きてたんですねー
hapi の inert で 403 エラーになる
confine オプションが true だと relativeTo で設定したフォルダの中しか許可しない
外部だと 403 エラーになる
デフォルトでこのオプションが true

relativeTo は基本的な静的ファイル置き場にして動的に /tmp 以下を返すとかは外部だったのでエラーになって困ってたらこんなところが原因だった
綺麗に出来てるのを複雑にしたくない気持ち
綺麗にできてるツールに機能を追加したいけど綺麗さが崩れてしまうのであんまり直したくない感
最近だと オブジェクトのデータのフォーマットチェックする関数が再帰で return するだけで済んでたのにどこが悪かったのかわからなくてエラー箇所情報などの補足データも入れようとするといろいろごちゃごちゃするし再帰関数外部のデータを保存するところを更新したりとなんだかなぁというコードになった

単純なのだと

value = update(value)



const tmp = update(value)
if (!tmp) return
value = tmp

にするのでも 嫌だなぁって気持ちになる
{...obj} は null でも大丈夫
{...obj}

ってかなり便利で既存のオブジェクトに代入したいとき以外は Object.assign は使わず基本こっち

だけど obj がオブジェクト以外だと問題起きそうで null とか来そうなら Object.assign にしたり

{...(obj || {})}

とかやってました
だけどそんなことしなくても null でもエラーなりませんでした

{...null}
// {}
{...undefined}
// {}
{...false}
// {}
{...123}
// {}
{..."abc"}
// {0: "a", 1: "b", 2: "c"}
{...[10, 20]}
// {0: 10, 1: 20}

false や 123 などもオブジェクトじゃないならなにもせず空のオブジェクトになります
ただ 文字列や配列の場合はインデックスをキーとしてオブジェクト扱いされます

ちなみに配列の場合は

;[...null]
// Uncaught TypeError: null is not iterable

数値などでも iterable じゃないものはすべてエラーになります

pax という Rust 製 JavaScript バンドラーを見つけた
JavaScript のバンドラーというと

◯ webpack
◯ parcel
◯ rollup

くらいだろうと思ってたらこんなのをみつけた

https://github.com/nathan/pax

JavaScript じゃなくて Rust で作られてるみたい
バンドラーって基本 Babel みたいなトランスパイルや UglifyJS みたいなミニファイツールを使うし それらは基本 JavaScript で作られてるからバンドラーも JavaScript だと思ってけど Rust らしい
そういうの全部含んでる大規模なプロジェクトには見えないし どういうものなのか軽くみただけだとよくわからない

少し気になったところがあって 前の名前が 「parcel redux」 で略して 「pax」 らしい
https://github.com/nathan/pax/commit/ae70ce4a5370bbfcd5395b287f4595e10b9b98f5

内部で parcel 使ってて Rust はただのラッパーと考えたけど それだと直接 parcel 使うのより遅そうだしあんまりメリットがない
速度は早いらしいし たまたま名前かぶっただけであの parcel とは関係ないのかな?
もうひとつの redux の方はフロントエンドの状態管理ライブラリなわけでバンドルには関係なさそうだし
node-dev マウント環境で使えない
サーバ側の Node.js でも変更監視してリロードできると聞いて node-dev を入れてみたけど動かなかった
基本 実ファイルは Windows で動かすための Linux 環境はそこを mount してるから監視系ツールは使えないの多め

フロントエンドの parcel の watch は結局 Windows 側でしてるし

cifs マウント可能性高そうな VirtualBox のマウントだったけどやっぱりダメだった
監視するツールが動く OS で管理してるファイルシステムじゃないと無理っぽいね

Node.js のプロセス管理ツールの PM2 でも watch できるみたいだけどたぶんこれも動かないと思う
hyperHTML でカスタムイベントをリッスンする
on から始まると以降をイベント名としてリスナ扱いになる
「-」 や 「_」 があっても気にせず on*** にすればいい

customElements.define("x-elem", class extends HTMLElement {
constructor(){
super()
this.attachShadow({mode: "open"})
this.render()
}

render(){
bind(this.shadowRoot)`
<div
onxxx=${eve => console.log("event xxx")}
onx-x=${eve => console.log("event x-x")}
onx_x=${eve => console.log("event x_x")}
>
<button onclick=${
eve => {
eve.target.dispatchEvent(new Event("xxx", {bubbles: true}))
eve.target.dispatchEvent(new Event("x-x", {bubbles: true}))
eve.target.dispatchEvent(new Event("x_x", {bubbles: true}))
}
}>event</button>
</div>
`
}
})

on が最初の区切りまでとくっついて見づらいので 区切り文字は使わず全部小文字にしたほうがいいのかも

注意するところは大文字小文字を同一視したときに同じ名前は別々に設定できないこと

<div
onxxx=${eve => console.log("event xxx")}
onxXx=${eve => console.log("event xXx")}
></div>

これは無効
hyperHTML 内部でエラーが起きる

原因は

document.body.innerHTML = `<div a="1" A="2" b="3"></div>`
document.body.innerHTML
// "<div a="1" b="3"></div>"

HTML 自体が大文字小文字を区別しないで 同じ属性をふたつ作れないから

後のほうは消される
消された結果 属性と埋め込み値の数が合わなくてエラーになる
Dart2 やっぱり使わないかな
Dart2 がリリースされたとかいうのを少し前に聞いたので見てみました
Flutter とかモバイル系向けになった?みたいだけど JavaScript の置き換えはやめたのかな?

軽くみてみた感じは C 系をベースにした言語と大差ない感じの構文
var や const にもできるけど型指定あり
しかもここも C 系みたいな書き方

String name = 'Bob';

Future<String> lookUpVersion() async => '1.0.0';

void main() {
assert(sort is Compare<int>); // True!
}

私としては型指定とかメタデータ的なのはアノテーションみたいなコードの外部に置いてほしいんですよね
最近の型あり言語の仕様を見ては毎回書いてる気がしますが elm (Haskell) 的な型指定の見た目が好きで 型指定の有無は別の行に独立させて変数の宣言代入処理とは切り離してほしいです
変数名や関数定義の前に長い型名とかあると見づらいだけです

流し見程度なのでよくわかってませんが型付けできる altJS としてなら TypeScript で良くない?というところ
そういえば前に Android 代替 OS が Dart とか噂を聞いた気がしますし そういう別方面の言語になればいいと思います
なんにせよあんまり使ってみたいと思えないものでした
一見問題なさそうに見える
if [x == y]:
print(1)
else:
print(0)

何がおかしいんだろうと思ったけどこれは絶対 1 が表示される
[] は比較条件を書くところじゃなくてただの配列
Python は配列に要素が 1 つでもあったら True になる
比較結果の boolean 値があるので常に True の場合の分岐になる
Hack は using + disposable を使うらしい
少し前に Hack がいろいろ変わって PHP の悪いところ切り捨てていくみたい とかいう話を聞いてしばらくしたのでなにか変わってるのかなと見てみると……
もう 少し前の話みたいですがデストラクタが廃止されて using+disposable 使うようになったみたいですね

この組み合わせ C# ぽいですね (C# にはデストラクタもありますけど

IDisposable を継承したクラスで __dispose メソッドを実装して

class Handle implements \IDisposable {
public function __dispose(): void {}
public function foo(): void {}
}

using を使って そのクラスのコンストラクタを呼び出します

using ($x = new Handle()) {
$x->foo();
}

基本は C# と一緒

ただ関数スコープもできるみたいで

using new Handle();

と書いたらそのスコープが終わってから __dispose が呼び出されるようです

PHP もこうすればいいのに
そろそろライブラリは ShadowDOM を考慮してほしい
JavaScript のライブラリで ShadowDOM 考慮されてないのが多い
全部の要素が document からつながってる前提 クエリセレクタで取ってこれる前提
そんなのが多すぎ

そろそろ WebComponents を意識したのが増えてきてほしい
WebComponents 使ってたら body 以下って xxx-app みたいなタグ一つだけでほかは全部その app の ShadowDOM の中ってことが普通にある
だからこれまでの DOM 構造を前提としてたら何もできないようなものもありうる


jQuery は一応親指定できるけど基本 document からだし WebComponents で作るなら使わないのが基本になってくれるといいなぁ
使いたい人が勝手に使う分には別にいいんだけど 割と良さそうなライブラリがあってそれが jQuery 必要とか書いてるとすごく嫌な気分になるから
結局 jQuery 入れるくらいなら自分で作ると言って自作ツールが増えてる……
正規表現の */ が地味に迷惑
function a(str) {
const reg = /\d*/g
return reg.test(str)
}

こんな感じのコードがあってまとめてコメントアウトしたいから /**/ で囲んだのになんかエラーでてる
確認してみたら 正規表現の */ でコメントが終わってて それ以降が JavaScript として扱われて構文エラー

正規表現リテラルが 「/」 なの地味に困る

ブロックコメントのネスト機能もないし その行の最初に // 入れてもコメント中なら無意味だし */ の後に入れたらコードの途中だからコメントアウトを外すとき辛いし
ブロックコメントは使わず矩形選択してブロックコメント化したいところ全行の最初に // 入れるのが良いのかな
Promise の回収
Node.js でこれを実行したら 1 秒後に 1 を表示して Node.js のプロセス自体が終了する

function a(){
return new Promise(resolve => {
setTimeout(() => {
console.log(1)
return 2
}, 1000)
})
}

function rec(){
a().then(e => rec())
}

rec()

ずっと繰り返されそうにと思ってたけど Promise 内で resolve を使わず return してた
こういう resolve も reject もせず放置された Promise ってちゃんと回収されるのかなんか不安があったけどちゃんと回収されてるみたいで安心

ところで return 2 を resolve(2) に直すと毎秒 1 がで続ける
2 には特に意味はない

今回のだと絶対に resolve も reject もされないってわかるからであって fetch したときにサーバが end 忘れててレスポンスが永遠に来ないとかだとダメだと思う
そういうことはあまりなさそうだけど WebSocket のライブラリで socket に対してレスポンスを返せるもので返し忘れはわりとありそうな気はする
関数をクローンしたいとき
オブジェクトをディープクローンするとき 中に関数があるとどうするか困るのが関数
プリミティブ値はそのままで 配列とオブジェクトはプロパティを再帰的にコピーでなんとかできる
でも関数はどうするのがいいかベストな方法がわからない

考えられるのは

◯ そのまま
◯ 文字列から再作成
◯ 元関数を通すだけの関数を作る

関数自体の機能はイミュータブルなのでそのまま参照をコピーするだけで基本は大丈夫
でもオブジェクトだからプロパティがあって それが使われてる場合はクローン後の関数のプロパティを書き換えたら元の関数のプロパティも変わってしまう

ちゃんとクローンするなら toString の文字列を元に eval などで再作成
パフォーマンスが悪そうなのと静的スコープが維持されないので外部を参照してると動かなくなるなど問題もある

だから新しく同じ処理をする関数を作るのじゃなくて クローン元の関数を実行するという関数を作る
プロパティを引き継ぐために プロパティだけは通常のオブジェクトと同じようにクローンする
呼び出しの階層が 1 つ深くなるくらいしかデメリットもないし ちゃんとクローンするのならこの方法が一番いいのかな
条件演算子とスプレッド演算子
フラグによって引数を変えたいときで 引数の数も変わるとき

console.log(true ? ...[1, 2] : 3)

って書いてみて なんかおかしい気が
「...」 って引数のところに使える構文で式ではないはず
エラーになりそう

やってみるとやっぱり
「Unexpected token ...」

正しいやり方は?


単純にやるなら

true ? console.log(...[1, 2]) : console.log(3)

if 文で関数呼び出しを 2 回書きたくないから ?: つかってるのに結局 2 回書いてる
console.log 程度ならいいけどここが長いと書くの大変

まとめるなら引数に 「...」 を使うのは確定させて 「...」 のあとの式を ?: で書く

console.log(...(true ? [1, 2] : [3]))
for-of でオブジェクトを使いたい
for-of は便利ですが オブジェクト型の場合はそのまま使えません

for(const item of [1, 2, 3]){
console.log(item)
}
// 1
// 2
// 3

for(const item of {a: 1, b: 2}){
console.log(item)
}
// error
// オブジェクトが iterable じゃないと言われる

Object.entries を通せば

for(const item of Object.entries({a: 1, b: 2})){
console.log(item)
}
// ["a", 1]
// ["b", 2]

でも毎回は面倒です
そこで

Object.prototype[Symbol.iterator] = function*(){ yield* Object.entries(this) }

を用意しておくと

for(const item of {a: 1, b: 2}){
console.log(item)
}
// ["a", 1]
// ["b", 2]

どうしてこれがデフォルトで設定されていないのかな

parcel 1n もダメだった
bigint の 1n も parcel で使えなかった
ブラウザで使えるのしか使わないから babel の変換通さずモジュール解決だけでしてそのまま出力してくれないのかなー
この制限が邪魔すぎる

使えないところを文字列にして

const a = WILLREPLACE`1n`
const b = WILLREPLACE`{...obj}`

これでバンドルして バンドル済みファイルを

js.replace(/WILLREPLACE`(.+?)`/g, "$1")

で置換して使うとか考え始めた

build だといいけど watch とかだと変換通すのが難しいかも
service worker 使えばソースコード改変できるんだっけ?
できても service worker 使うのは https 必要かぁ

いっそのことバンドルしなくて良いんじゃないかと思い始めた
socket.io のページが新しくなってた
たまたま数週間前に socket.io のページを開いていて さっきいらないタブを閉じていたら新しくなってるのに気づきました

これまでのページのドキュメントってすごく読みづらくて 毎回 github の方で見ていたので読みやすくなって助かります
と言っても socket.io を使うことがそうそうないのですけどね
ページだけじゃなくて socket.io 自体もメジャーアップデートしたのかなと思いましたがバージョンは前見たときと一緒でした
HTML 文字列から簡単に append する
document.body.append(`<div class="x"><span>1</span>23</div><div>45</div>`)

って書きたい
innerHTML ならできるけど append にはできない
これだとそのまま文字列として追加される

一旦 innerHTML に入れて全部の子要素を追加するの面倒
なので HTML テキストを DocumentFragment 化するもの

const fr = html => Object.assign(document.createElement("template"), {innerHTML: html}).content

これを使って

document.body.append(fr(`<div class="x"><span>1</span>23</div><div>45</div>`))
document.body.append(fr`<div class="x"><span>1</span>23</div><div>45</div>`)

() 書くの面倒ならなくしてテンプレートストリングのタグとしても使える
ただし間に ${} による埋め込みがないときだけ

せっかくだからタグならではの機能でエスケープ機能を入れる

const html = (strs, ...values) => {
const esc = value => Object.assign(document.createElement("div"), { textContent: value }).innerHTML
const fmt = value => value != null
? (value.html ? value.html : value.text ? esc(value.text) : esc(value))
: ""
return fr(strs.reduce((a, e, i) => a + fmt(values[i - 1]) + e))
}

これを使うと

document.body.append(html`<div class="x"><span>1</span>23</div><div>45</div>`)
document.body.append(html`<div class="x"><span>${1}</span>${"<br>"}${{html:"<b>bold</b>"}}</div><div>45</div>`)

「<br>」はエスケープされて文字列として表示されて 「<b>」 は太文字になる