片栗粉とろみ

本の紹介と技術。某ベンチャー勤務。新卒一年目。

全射と単射/エピ射とモニック射のイメージについてのメモ

www.youtube.com

英語の勉強も兼ねてBartosz Milewski先生の講義を観て圏論に入門しようとしている。そのメモ。

エピ射とモニック射のイメージ

エピ射(epimorphism)

始域の像が終域の上に覆いかぶさるようなイメージ。「epi-」の意味はupon
集合の圏だと全射(surjective / onto function)。

「upon(上に)」も「onto(上に)」も「sur-(上に)」というイメージ。

f:id:sushi__melody:20190417133341p:plain

全射

fの終域がYをすっぽり覆う感じ。

モニック射(monomorphism)

始域の像が終域にポコっと入るイメージ。
集合の圏だと単射(injection / injective function)。

「inject(注入)」というイメージ。「mono-(単一)」はたぶん一対一対応のイメージ

f:id:sushi__melody:20190417133336p:plain

単射

fの始域と終域が一対一対応を保ったままYのなかにスッポリ収まる感じ。

 

さいごに

間違っているところが多々ありそうなので指摘していただけるとありがたいです

心理的安全性を取りに行く + ACTの話

心理的安全性

チームの生産性をあげるために心理的安全性の大切さが叫ばれて久しい。

bizhint.jp

チームメンバーが心理的安全性を確保できるように配慮するのは当然のこととして、ぼくのように新卒1年目でもっともジュニアなメンバーとしては"心理的安全性を取りに行く"のが大事ではないかと思った。

心理的安全性を取りに行く

ぼくはもともと内向的で人の顔色を伺うタイプなので、すこし油断すると「話して悪く思われないか不安 => しゃべる機会が減る => 機会が減ることで反応が予想ができなくなり、より不安になる」という負のループに陥ってしまう。

しかし一方で、ぼくは一度心を許してしまえば何でも率直に言えるタイプだ(これはみんなそうかもしれない)。

だから、少し勇気をだして雑談に入っていったり、少し勇気を出して1on1をセッティングするなど、自分が積極的に意見を言うための足場を整えることが大事だ。

べつに雑談を盛り上げたり笑わせたりなど成果を出す必要はなくて、いざ自分の意見が必要な場面になったときのために足場を整えておく。

行動療法ACTとの関連性

心理的安全性のために勇気をだすのは、チームと自分の生産性のためだ。

この"勇気"というのは決して「不安に打ち克つ」のようなニュアンスではなく、「不安を受け入れる」に近い。

生産性という価値のために、コミュニケーションへの不安を受け入れ、行動する。

書いていて気づいたが、これはまさに行動療法ACTの不安のアクセプタンスと価値へのコミットメントだ。

www.psychological-skils.com

nlpvoice.com

少し前にビジネスマンのあいだで流行ったマインドフルネスについて

ACTはその治療体系にマインドフルネスを組み込みんでいることで有名だ。ACTではマインドフルネスを、感情から距離を取り、受け入れ、価値に基づいた行動につなげるためのツールとして用いる。

『SOFT SKILLS』では瞑想を"プラスの感情を経験しやすくなる"のような文脈で捉えているが*1、もう少しテンションを下げて"勇気を出すためのツール"くらいのものとしてマインドフルネスを使っていって良いのだと思う。

ということでこれから一週間マインドフルネスに取り組んでみようかな。

*1:SOFT SLILLS 第66章

Javascriptでfor文を使わずにpythonっぽくn回ループする

pythonのループ

n回ループしたいだけなのに i++とか書きたくないですよね?pythonっぽくループ回したくないですか?

for i in range(5):
  print(i)

うんうん!いいね!こんな感じで回したい!回したいよね!ね?同意してください!

方法

Arrayとfor-of文を使う

5回ループしたいときは

for (const i of Array(5).keys()) {
  console.log(i);
}

ループの中で繰り返し回数を使わないならもっと簡単に書けます。

for (const _ of Array(5)) {
  // なんかする
}

使いどころ

ほとんどの場合mapを使って書けるので必要ありませんが、強いて言えば非同期処理を直列に行いたい場合に使えます。

const f = async (n) => {
    for(const i of Array(n).keys()) {
        await someAsyncFunction()
    }
}

Generator式で複数直列にyieldしたい場合にも使えます。以下の例は自作のなんちゃってrange関数。

function* range(stop) {
  for(const i of Array(stop).keys()) {
    yield i   
  }
}

なんでこうなるか

ドキュメントにはArrayのコンストラクタに整数を渡すと、渡した数だけ空の要素をもったリストが生成されると書いてあります*1

じっさい、中身を表示してみると

for (const value of Array(5)) {
  console.log(value) // => undefined
}

undifinedが表示されます。

(実際に配列の中にundefinedが入っているわけではなく、長さのみもった空の配列が生成されるようです)

さらに、Arrayのkeys()を呼ぶと、キーを順番に返却するイテレータが返却されます*2。試しにイテレータと、イテレータのnext()を呼んでプリントしてみます。

const iter = Array(5).keys()

console.log(iter) // => {} 
// 配列が返ってくるわけではない。

console.log(iter.next()) // => { value: 0, done: false }
console.log(iter.next()) // => { value: 1, done: false }
console.log(iter.next()) // => { value: 2, done: false }
console.log(iter.next()) // => { value: 3, done: false }
console.log(iter.next()) // => { value: 4, done: false }
console.log(iter.next()) // => { value: undefined, done: true }
console.log(iter.next()) // => { value: undefined, done: true }

for-of文はof以下にイテレータが渡されると、イテレータがdoneになるまでnextを呼び続けてvalueを渡すので*3

const iter = Array(5).keys()

for (const i of iter) {
  console.log(i);
  // => 1
  // => 2
  // => 3
  // => 4
  // => 5
}

となり回数指定ループが実現できます。

ReactDatePickerでlocaleを指定しようとすると RangeError: locale must contain localize property になる問題

開発はじめたての頃だったら絶対解決できない問題だったのでメモ

問題

example( ReactJS Datepicker crafted by HackerOne )を参考にしてReactDatePickerに日本語Localeを指定する。

import React from 'react';
import DatePicker, { registerLocale } from 'react-datepicker';
import ja from 'date-fns/locale/ja';

registerLocale('ja', ja);

class SomeComponent extends React.Component {
  // ...
  render() {
    return(
      <DatePicker
        // ...
        locale="ja"
      />
    )
  }
}

すると RangeError: locale must contain localize property というエラーがでてしまいローカリゼーションに失敗する。

対処法

data-fnsのv2.0.0-alpha版をインストールする。

yarn add date-fns@next

もしくは

npm install --save date-fns@next

でOK。

原因と解決までの経緯

たしかにexampleのコメントには

Note: Make sure to npm install the right version of date-fns as specified in packaged.json. The default one may not be compatiable npm install --save date-fns@version

意訳: デフォルトで入るdate-fnsのバージョンだと互換性がないかもしれないからバージョンを指定して入れてくれ

と書いてある。

「どのバージョンを指定すれば…?🤔」となったものの、いったんデフォルトで入る最新のバージョンから1つずつバージョンを下げていった。

しかし、3つバージョンを下げてみてもエラーは出続けた。

ソースコードを読む

ライブラリ内部でエラーを投げている箇所のソースコードを確認すると

function formatDate(date, formatStr, locale) {
  // ...
  var localeObj = getLocaleObject(locale);
  // ...
  return format(date, formatStr, {
    locale: localeObj ? localeObj : null,
    awareOfUnicodeTokens: true
  });
}

function getLocaleObject(localeName) {
  // registerLocaleで登録したdate-fnsのオブジェクトをreturnする処理
}

function format(dirtyDate, dirtyFormatStr, dirtyOptions) {
  // ...
  var options = dirtyOptions || {};
  var locale$$1 = options.locale || locale;
  // ...
  if (!locale$$1.localize) {
    throw new RangeError('locale must contain localize property') // <= ここでエラー
  }
}

となっていて、ようはregisterLocaleで登録したdate-fnsのオブジェクトに localize というプロパティが含まれていないのが原因らしい。

githubリポジトリまでファイルを確認しに行く

date-fns/locale/jalocalizeが含まれるバージョンをgithubに探しに行く。

ライブラリのバージョンはたいていtagで指定されるので、tagを切り替えながら該当するバージョンを探す。

するとv2.0.0-alpha.*にはlocalizeが存在することがわかった。

https://github.com/date-fns/date-fns/blob/v2.0.0-alpha.27/src/locale/ja/index.js

確かにバージョンを指定しろって言われたけど、まさかアルファ版だとは...🤦

インストールする

date-fns@2.0.0-alpha.27を指定してインストールしてもよいが、https://date-fns.org/ によると

⚠️ The provided examples are for v2 which is in pre-release right now. If you want to give it a try, install the latest version: npm install date-fns@next

意訳: リリース前のバージョン2を使いたいやべえヤツは npm install date-fns@next で最新のをいれてくれよな

とあるので、date-fns@nextでインストール。

zsh: no matches foundの解決策

エラー「zsh: no matches found」

PDFファイルの1ページ目を指定してImageMagickに処理をさせたかった。

PDFのページを指定するにはファイル名の後ろに[]を用いて処理させたいページのインデックスを指定すれば良いとのことだったので*1、以下のコマンドを実行した。

convert images.pdf[0] image.jpg

しかし、これを手元のzsh環境で実行すると

zsh: no matches found: images.pdf[0]

というエラーが出た。

エラーの原因

調べてみると、zsh[] * ? などglobに使われるメタ文字を発見するとファイル名としてglob展開してから実行しようとするようで、それが原因になっているようだ*2

globとはUnix環境でワイルドカードを用いてファイル名をマッチさせるパターンのことで、globと呼ばれているのはファイル名をマッチさせるためのインタプリタの名前が globだったことから来ているらしい*3

globで[abc]はa, b, cいずれかの文字にマッチすることを示す。

そのため、今回のコマンド

convert images.pdf[0] image.jpg

が実行されると、zshimages.pdf0というファイルをマッチさせようとして失敗し、
zsh: no matches found: images.pdf[0]というエラーが発生する。

解決策

方針は2つ

  • マッチに失敗してもエラーで中断させない
  • glob展開させない

1.nomatchオプションをOFFにする

エラーで中断させない方針。
zshのデフォルトの設定ではマッチに失敗したときエラーを発生させるようになっているが*4、その設定をオフにする。

以下を~/.zchrcに記述して再読込み。

setopt nonomatch

2. 実行時にglobメタ文字が含まれる部分を"で囲む

こちらはglob展開させない方針。
メタ文字が含まれる引数を"で囲んでglob展開させなくする。

convert "images.pdf[0]" image.jpg

3. コマンドの最初にnoglobをつける

こちらもglob展開させない方針。
コマンド全体のglob展開をOFFにする

noglob convert images.pdf[0] image.jpg

#

個人的に.zshrcを汚したくなかったのでnoglobをつけて対処することにした。