Rustで一行が100文字以上になるとフォーマットできなくなる
100字以上の文字列を扱う場合、その行orファイル全体がフォーマットができなくなる時がある。
また、vscodeやIDEAでは書いてる時に怒られないし、ビルドしてもエラーになるわけではないので全然気付けなかった…
※この記事は明確な根拠はなく推測である部分があります。
結論
直接的な原因は見つけられなかった…
推測だが、rustのガイドラインでは一行の文字数を99文字以下にするように推奨しているらしいので、100文字以上にすると想定外な挙動になってしまうこともあるのかもしれない。99文字以下を心がけよう!
環境
❯ cargo -V cargo 1.59.0 (49d8809dc 2022-02-10) ❯ rustc --version rustc 1.59.0 (9d1b2106e 2022-02-23) ❯ rustup component list | grep "(installed)" cargo-aarch64-apple-darwin (installed) clippy-aarch64-apple-darwin (installed) rls-aarch64-apple-darwin (installed) rust-analysis-aarch64-apple-darwin (installed) rust-src (installed) rust-std-aarch64-apple-darwin (installed) rustc-aarch64-apple-darwin (installed) rustfmt-aarch64-apple-darwin (installed)
確認してみたこと
以下のように引数内の行ではインデント含め100文字未満で記述する必要があるようだ。ただし、コメントやカンマや丸括弧はカウントされてなさそう…
// これより長い文字列を引数内で扱うと、この行だけorファイル全体がフォーマットができなくなる assert_eq!( "678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", // 99文字(インデントとダブルクォーテーション含める, `,`を除く) "678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" // 99文字 ); // インデントが増えても同様 fn main() { assert_eq!( "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", // 99文字(インデントとダブルクォーテーション含める, `,`を除く) "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" // 99文字 ); let s = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"; } fn hellooooo12345678901234567890123456789012345678901234567890123456789012345678901234567890123456( ) -> i32 { 5 } // これより長い関数名を引数内で扱うとファイル全体でフォーマットができなくなる assert_eq!( 5, helloooooo1234567890123456789012345678901234567890123456789012345678901234567890123456789012345( // `(`を除いて99文字 ) );
また、以下のように100行越えを一行で書く分には、ファイル全体がフォーマットできなくなるわけではないが、
assert_eq!("test", "6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789") let s = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
以下のように謎に空白を作ってしまっても、この行だけはフォーマットできない
assert_eq!( "test" , "6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789") let s = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
調べたこと
残念ながら直接的な原因は見つけられなかった…。
推測だがrustのガイドラインでは一行の文字数を99文字以下にするように推奨しているらしいので、100文字以上にすると想定外な挙動になってしまうこともあるのだろうか…
ちなみに100文字ではなく99文字というのは、pep8の79文字推奨と同様の理由らしい。以下参考
以下、pep8の引用
ほとんどのツールのデフォルトの折り返し動作は、コードの見た目の構造を壊し、理解するのを難しくします。79文字という制限は、ウィンドウの幅を80に制限し、行を折り返すときにツールが行末にマーカーを置いたとしても、エディタに折り返す動作をさせない目的で選ばれています。
引用: はじめに — pep8-ja 1.0 ドキュメント (参照: 2022/4/6)
また、rustのガイドラインについて、こちらのPRまでは「一行は80文字以下にすべきで、100文字以下は必須」ということだった。というのもあり、100文字に対する折り返しを考慮すると99文字ということらしい。
rustのガイドラインのPR: Decrease line lengths by one by chris-morgan · Pull Request #12 · rust-lang/rust-guidelines
Vue2系とTypescript周りの個人的な実装方針と所感
個人開発やプロダクト初期のVue 2系とTypescriptを用いたSPAの開発で得た知見のメモ。まだ試行錯誤中。
- 注意
- 適宜更新します。もし気になる点ございましたらご指摘いただけますとうれしいです。
- 自分が所属している団体を代表するような意見ではございません。
- 現在執筆中
小ネタ
リアクティブな連想配列
Vue 2系ではオブジェクトのプロパティを更新してもDOMが更新されずに困ることがある。 以下は、オブジェクトの参照自体がリアクティブなVueインスタンスのプロパティの場合、オブジェクトの任意のプロパティを更新した時に、オブジェクトの参照も都度変更してしまえばDOMの更新がされるだろうというやり方。オブジェクトのプロパティが多ければ処理効率は悪そう…
data(): { return { hashMap: Vue.observable<MyHashMap>(new MyHashMap({}) } },
class Xxx { constructor(public aId: number, public bId: number | undefined) {} } // aIdとbId毎のXxxを保持するコレクションオブジェクト // TODO: ジェネリクス使って再実装 class MyHashMap { // key: `${aId},${bId}` constructor(private state: { [key in string]: Xxx }) {} get = (aId: number, bId: number | undefined): Xxx | undefined => { const key = MyHashMap.createKeyBy(aId, bId) return this.state[key] } values = (): Xxx[] => Object.values(this.state) valuesBy = (aId: number, bId: number): Xxx[] => { return Object.values(this.state).filter( xxx => xxx.aId === aId && (xxx.bId || undefined) === bId ) } has = (aId: number, bId: number): boolean => { return this.get(aId, bId) != undefined } set = (aId: number, bId: number | undefined, xxx: Xxx): void => { // NOTE: リアクティブにするために新しくオブジェクトを生成して代入する. const newState = { ...this.state } const key = MyHashMap.createKeyBy(aId, bId) newState[key] = xxx this.state = newState } replace = (before: Xxx, after: Xxx): void => { this.set(before.aId, before.bId, after) } // NOTE: このクラスのstateのkeyを生成する時は必ずこのメソッドを使うようにする. static createKeyBy = (aId: number, bId: number | undefined): string => { return `${aId},${bId}` } // NOTE: このクラスのstateのkeyからkeyの構成要素を取得したい時は必ずこのメソッドを使うようにする. // return [aId, bId] static fromKey = (key: string): [number, number | undefined] => { const maybeIds = key.split(',') if (maybeIds.length === 3) { return [Number(maybeIds[0]), maybeIds[1] == 'undefined' ? undefined : Number(maybeIds[1])] } console.log(`Error in MyHashMap#fromKey: ${maybeIds}`) return [NaN, NaN] } }
子コンポーネントへのメソッドの渡し方は$emitよりもpropを使う
- 理由
- $emitは文字列でメソッド名を扱ったり、引数が可変長で型がAnyだったりで型安全ではないため
- propであれば型安全に扱えるため
↓以下、子コンポーネント側の例
props: { inputFunc: { type: Function as PropType<(value: string) => void>, required: true, }, }
vuexよりはstoreパターンをなるべく使う
- vue.observableを使ったシンプルなstoreパターンを採用する
- オブジェクトをリアクティブにするため(storeの値が変わったとき、変更をDOMにも反映させるようにするため)
- シンプルなstoreパターンで事足りるため。
今のところvuexはあまり利用していない。vuexを利用していない理由としては - そもそも小さなプロダクトには、vuexがは向いていないから - 型安全ではないから(型安全にしようとすると、デコレータをたくさん使う…)
nullよりもundefinedをなるべく使う
- 理由
- Optional Chainingではnullではなくundefinedを扱うため
扱うUIフレームワークに合わせるのもいいかもしれない。Vuetifyではnullよりもundefinedを扱っているケースが多く見受けられる
axiosに渡すAPIのリクエストやレスポンスを表すオブジェクトの定義はclassかinterfaceか
classを定義すれば同名のinterfaceも定義したようなものなので、インスタンス化してなくてもメソッドが使えないだけでプロパティは参照できる。 そのため、axiosで受け取る・axiosで渡すオブジェクトの定義はclassかinterfacelかの選択肢がある。
- class
- interface
- 利点
- 表示ロジックやビジネスロジックとは隔離されているので、やや変更に強い
- 欠点
- 手続っぽい書き方になりがち
- さらにクラスに変換するようなことになるので冗長になりがち。実装コストが高くなる
- 利点
所感
- 型安全はありがたい。
- 関数の引数に違う型のものを渡そうとするとエラーになってくれるので嬉しい
- 仕様変更でとあるフィールドを修正するとき、安心して修正できる。型を修正すれば、その型のフィールドを使ったものはほとんどエラーになるので、修正漏れしにくい。
- もし型定義がなかったらオブジェクトにはどんなフィールドがあるか覚えてないといけない or 仕様ページ(wiki等)を見に行く手間があるので、ストレスフルだと推測できる。
- ライブラリに型定義ファイルがないときは、自分で作る必要があるので面倒
m1 macで原神するために1台に11.2.3と最新の2つのバージョンを両方インストールした
概要
m1 macでいくつかのiosアプリがインストールでき、そのうち「原神」もできていたのですが、macOS 11.3にアップデートしたところできなくなったのでそのメモ
※2022年2月 追記
旧タイトル: m1 macで原神をするならOSアップデートは11.2.3まで説【2021年5月現在】
旧タイトルは語弊がありそうなので変更しました。
対象読者
※この記事は多くの方に役立ちません。自分用のメモとして残してあります。
結論
- 一台のm1 macにmacOS 11.2.3と最新のmacOSをインストールしておく
- PlayCoverやNoxPlayerは使わない
- macOS 11.2.3のインストーラーはもう配布していなそうなので要注意
所感
- PlayCoverやNoxPlayerはシステム整合性保護を一時的にでも無効にするのでリスキーかなっと思ったのと、原神のログイン認証のたびにシステム整合性保護を無効にするのは面倒かなと思い避けました。
- Appleサポート公式に紹介されてはいますが、デュアルブートはPC的にはやや不安定な印象があるので、OS切り替えまくってPCがお釈迦にならないか若干心配ではあります。
- 別のバージョンのOSに切り替えるためには再起動が必要なため煩雑です。原神のプレイ頻度は減ってしまいました…。
- Time MachineでバックアップしておけばOSのバージョンも復元できる的な記事をよく見かけますが、実際に試したことないので自信ありません。
- 上記のような懸念や煩雑さがあるくらいならiPad買って原神した方が幸せかもしれない。
↓別のバージョンのOSをインストールする際の参考
個別の APFS ボリュームに macOS をインストールする - Apple サポート (日本)
以下、2021年5月に書いたもの
前提
過去のmacOSのインストーラーの入手
アップデートして既存のアプリが使えなくなったのなら、元に戻せばまた使える!ということで過去のmacOSのバージョンを入手します。
↓以下のサイトにありました。以下のサイトでは他にも過去のバージョンのmacOSの変更点やインストーラーのリンクを掲載してくれているので重宝しそうです。 macOS Big Sur 11.2.3 Update (20D91) is Live! What’s New?
↓macOS 11.2.3のインストーラーのリンク。ドメインがappleのものなので信用して使ってます。 http://swcdn.apple.com/content/downloads/12/32/071-14766-A_Q2H6ELXGVG/zx8saim8tei7fezrmvu4vuab80m0e8a5ll/InstallAssistant.pkg
その他メモ
↓記事投稿現在、iosアプリの原神はm1 macと互換性がないっぽいらしい… 完全無料!Mac/iPhoneアプリと M1 Macの互換性をチェック|iMobie
懸念点
OSのアップデートをしないということはセキュリティ的にリスクがあるので、あまり嬉しくはないのですが、それでもm1 macで原神を遊びたいのでしばらくはアップデートには慎重になると思います…。自己責任で…。
私のはてなブログの使い方
気軽になんでも書いてみる
日頃の日記感覚で書いていくつもりです。
趣味や日常、プログラミング関連とか思いついたらアウトプットするように使いたいと思います。