プログラムdeタマゴスマートフォン用の表示で見るプログラムdeタマゴnodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです2019-09-20JavaのOptionalは現状失敗作JAVAチマチマとは書いていたんですが、1年ぶりぐらいに真面目にJava書いています。前からずっと思っていて、実際何度か口にしたことがあるんですが、やっぱ言いたい。JavaのOptionalは失敗作JavaのOptionalの何が悪いの?言語機能じゃないから。完全にここに集約されると私は思っています。Java8で登場したOptionalですが、この時にコンパイラを拡張しなかったのがそもそもの問題だと思っています。AutoBoxing例えばKotlinのnullableのような機能の導入、というのは慎重になるべきでしょうし、すぐできるとは思えません。Optionalへのオートボクシングぐらいは実現できたのではないでしょうか?int→Integerというオートボクシングは既に存在しているわけで、最初から導入すべきだったと思います。Optional.empty()に}実に鬱陶しいofやらemptyやらofNullableが省略できる上、Optionalの癖にnullが返せるという謎の状況も生まれにくいでしょう。(※上の例だと、OptionalIntをそのまま返すとしてるけど、ここでnull挿入できる)むろん、色々な議論があったのでしょうが、導入が許されるのは、最初だけなのです。オートボクシングはもはや、実現不可能です。現在、nullが返せるという謎の状況が合法だからです。null;}オートボクシングを認めてしまうと、後方互換を破壊してしまいます。今から可能なのは、Kotlinの様に言語機能を拡張するか、後方互換の破壊か、nilとかnullに変わる単語を導入する(ミスる自信があるぞ!)か、アノテーションで処理変えるか、Optionalに暗黙に変換されるOptional2見たいな型でも用意するかぐらいでしょうか。Auto-UnboxingOptionalのオートボクシングを認めるなら、当然、アンボクシングもあるべきです。Optional<T>→Tへのアンボクシング.........の前にOptional→booleanへのアンボクシングです。アンボクシングと言うよりは、暗黙の変換ですね。以下の様な状況を考えると、二つ目のif文の方が読みやすいと思います。isPresentって長いし面倒くさいよ。//戻り値は特に使わない処理}else{}ifPresentOrElseがあるだろ、この馬鹿たれ!というお叱りの声が聞こえますが、本気でそれが読みやすいと思っています?ifPresentOrElse(()->{},()->{})より、単純にif文の方が、私には読みやすいです。条件式がOptionalだったら、trueの場合は_にアンボクシングした結果が格納される、みたいな構文でアンボクシングされると良いかなーとか思います。value;}なるべくキーワードを増やさない様に_ってかいたけど、$1とか$2でもいいかもね。ifPresentOrElseなんかよりずっと読みやすいし、ラムダ式の変数のキャプチャとかも発生しない。推し進めて、存在演算子が導入されても良いと思います。0;まとめJavaもプリミティブのラッパーやString、列挙体、Cloneable、AutoCloseableなど、幾つかのクラスでは言語的に特殊処理しているのだから、Optionalは何が何でも絶対駄目という理由はないと思います。言語として特殊扱いすべきだったと思います。C++は難しすぎる、Javaの方が簡単と言われますが、OptionalはC++の方が簡単ですね。オートボクシングやbooleanへの変換は、C++では暗黙の型変換で普通に使えます。最近のJavaは言語機能の拡張に積極的ですから、早いところ、言語機能に組み込んで欲しいな。02:19もっと読むコメントを書く2019-09-10組み込みでラムダは使って良いけど、std::functionは駄目っぽいC/C++例えば、組み込みでウォッチドックタイマー(WDT)を使う場面を想定しましょう。}}無茶苦茶長い処理をする場合は処理中にクリアを挟むことはあるだろうけど、基本形はこれでいいでしょう。?なんとも思わない?よし、君は素晴らしい人格者だ。さぁ、無駄な時間を過ごす前に、ブラウザバックするなり、タブを今すぐ閉じるんだ。した何かを感じるかい?奇遇だ、私もだ。さぁ、私と一緒に地獄に堕ちようよ。書きたいさて、上記の様なコードを見ると、私としては、例えばこう書きたくなります。});}クリアだなのなんだのは隠蔽して、勝手にやって欲しい。一回のループでするべき処理だけ定義して、後は自動でやって欲しいのです。処理の「意味」だけに注力したいのです。レジスタとか後から読んで読めないゴミクズを、一々触りたくないのです。(なお、1msはstd::chrono_literalsに定義してあります。ユーザー定義リテラルで自作できます。)std::functionで関数を渡すこのように、何か勝手にやって欲しい処理の間に、ユーザー定義の処理を挟むには大凡以下の方法があります。関数を定義して、関数ポインタを渡す関数オブジェクトを渡すラムダ式を渡す先に書いた例ではラムダ式を使っていますね。実際にはラムダ式は2の糖衣構文なので、基本的には二つですね。「C++は関数ポインタよりも、関数オブジェクトの方が最適化が効きやすい」という話もありますが、最近のコンパイラは賢いので、関数ポインタでも最適化がいけてる気がします。実際、手元にあるIARのコンパイラでリリースビルドすると、関数ポインタの最適化ができています。どれを使うにせよ、受け取る側(loopメソッド)はC++11以上では、std::functionで簡単に同じように受け取ることができます。func);これをビルドするとどうなるのでしょうか?以降はWDTの例を引きずるとコードが長くなるので、以下の様な単純なコードで考えてみましょう。});}IARのコンパイラで上記のコードをデバッグビルドすると、マップファイルは以下の様になります。[1](略)newとかdeleteとかallocatorとか、組み込みの敵なメソッドがずらり。最適化してないからしょうが無いのかと思ったら、リリースビルドにしても、deleteや仮想テーブルが残る結果になりました。これでは、組み込み的にはちょっと使えません。ARM8.40のコンパイラでは消えませんでした。そこで、もうちょっと最適化させやすくしてみます。f)fooにinlineを付けてみました。これでリリースビルドをすると、デリータ関連が消えました。fooも消えたので、fooがinline展開されて、デリータがいらなくなったのでしょう。(というか、C++において、inlineは基本的にヘッダーに関数をかける以上の意味は無いと思っていたのですが、消えてびっくり)しかし、仮想テーブルは残りました。std::functionという情報を消せてないようですね。(無論コンパイラによっても違うでしょうが)ということは、どうも組み込み的にはstd::functionが敵のようです。君もstd::vectorとかと同類の禁止薬物だったか。sdt::functionを使わず、templateにしてみるfunctionがだめならば、使わなければいいのだろう?と単純にtemplate化してみました。f)これを、デバッグビルドしたときのマップファイルが以下です。1)]という型の関数オブジェクトになったお陰で、デバッグビルドだというのに、newだとかallocとかdeleteとか仮想テーブルが一切なくなっています。ちなみに、最適化すると、fooもラムダ式もインライン展開されて、全部消えてました。これなら、組み込みでもニッコリですね。関数ポインタテンプレートでもニッコリですが、関数ポインタにもしてみましょう。例の様に、キャプチャしていないラムダ式は関数ポインタに暗黙に変換できます。0;}これを同様にIARでデバッグビルドするとこんなんができてて、微妙に8byteほどサイズが大きい。[1]この_FUNってなんじゃらほい?というわけで、逆アセンブル。PC}単にインスタンスを置いてラムダ式をコールしてreturnしてるだけですね。暗黙変換されるとき、こいつが渡されるようです。いう処理が入る分、8byteほどデバッグビルドのサイズが大きくなった様子。最適するとどっちも同じ結果になりました。まとめ組み込みにおいては、肥大化しても良いならテンプレートを、そうでないなら関数ポインタを使いましょう。近年のコンパイラは賢いので、関数ポインタでもちゃんと最適化してくれます。これは2019年現在の話であって、コンパイラが賢くなれば、std::functionでも良くなるかも知れませんが。00:50もっと読むコメントを書く2019-08-23static_assertで比較した値を表示したいC/C++「C++のconstexprの値がおかしいんだけど、static_assertで間違った値表示できないの?」と聞かれました。できねぇんだな、これがC++11からstatic_assertはあるというのに、何故static_assert_eqやstatic_assert_ltとかがないのだろう。"x?");これをg++でコンパイルすると、以下の様なエラーになります。xが何だかは全然分からないですね。~~^~~~~static_assertのメッセージには、ストリングリテラルしか入れられないので、動的に生成することもできないです。C++20でconstexprにおけるメモリ確保までできる様になるんだから、そこら辺も緩和して欲しいところです。組み込みの定数計算ぐらいならなんとかなるかも表示できないと言いましたが、整数値なら、裏技的に値を表示する方法があります。1,"test<NUMBER>");};static_assert(test<x>::value,"");これのg++のエラーは以下の様になります。test<10>':」ここ(赤字)に値が出るんです。ちなみに、clang++だと、NUMBER==1じゃなくて、10==1と表示してくれます。複雑なクラスなど使わない組み込みで、整数を計算するだけのconstexprなら、これで十分な場合も多々あると思います。いうわけで、まとめておいた一々書くのも面倒くさいと言うことで、まとめておきました。github.comこんな感じで使えます。>」という形で表示されるので、その言葉を探してください。Workbench等で使う場合は、エラーログを右クリックし、ログのフィルタリングを無し(全て)にして表示してください。g++だとこんな感じ。>':」の所に、pow(10)の間違った結果が出ています。ライセンスはCC0なので(Unlicenseとどっちがいいの?)、適当に改変して結構です。.........static_assert_eqとかC++で対応してくれないかなぁ。00:05もっと読むコメントを書く2019-08-04C++の相互参照ってどう作るのが良いの?C/C++スマポと相互参照GCを持っていない以上、根本的にC++のスマポと循環参照は相性が悪いけど、私が問題にしたいのはソコではないです。前回公開したSVDライブラリだと以下の様に、木構造の情報を構成します。デバイスはペリフェラルを複数保持するペリフェラルはレジスターを複数保持するレジスタ―はフィールドを複数保持するただ保持しているだけなら、vector<レジスタ>か、vector<unique_ptr<レジスタ>>でいいでしょう。SVDのデータ構造は、フィールドの情報を確定するにはレジスターの情報が必要である、という様に、子→親への参照も必須なのです。(むろん、木構造の構築時に確定してしまっても良いけど。実際、最初に作ったときは、どうせ編集するつもりがないので確定して作った。この場合、子が親を必要としないので、単にvectorで困ることはないないばーですね。)で、今更生ポインタ(ナマポ?)で管理ってのもあれなので、スマポ使いましょう。相互参照するので、shared_ptrとweak_ptrを使えばいいのでしょうか?しかし、これだと問題が発生します。それは親ポインタ(オヤポ?)をいつ確定するのってことです。fields;};オヤポ?とか書いてるところがネックです。ナマポだったら、コンストラクタにthisを渡せば済むことが、スマポだと、コンストラクタで完結できないなさそうです。次の様な関数を定義するなりして、後で呼び出すしかない。}};もしくは、諦めて、親への参照はナマポにするか。今回の場合なんかは、そもそも、親への参照が壊れたら正常に動かないので、ソコを気にしない(ユーザー責任)というのは一つの答えとして悪くない気がします。fields;};うーむ.........。Java何かだと一切悩まない様なところで、変に悩むのがC++ですな。一般にはどうするのが良い手段なんだろうね。Schemaがあるんで、自動的にバインドさせれば、案外簡単に解析できますよ。2019年5月18日ブーメランという言葉をご存じだろうか。今は無き民主党のあれである。SVDgithub.comはい、というわけで、私が必要になりました。C++のSVD解析器。その成果を公開しておきます。使い方は大体こんな感じ。パターンも用意してあるので、各要素にアクセスするプログラムも割とサクッと書けます。//visitorパターンに投げる実際に私が必要になった機能とかも大凡作ってあるので、まぁまぁ実用に耐えられるんじゃないかな。これ、誰か使ってるの?っていう様な仕様も、それなりにきちんと解析してます。cluster周りはあんまりテストしてないけど.........。エラー処理は甘いので、その内追々修正するかな。C++ワカラン...ちなみに、これを最初から作ったのではなく、一回別に作った物を、腹立ち紛れに作り直しました。C++の魔窟メタプログラミングに私がどれだけ耐えられるのか、試してみたかったのもあります。気が向いたらソースコードを見て貰えると良いかもしれませんが、なんでここまで複雑に作ったのって言うぐらい複雑です。実務でこんなコード書くやついたら、人格を否定しても許されると思います。C++ゼッンゼンワカラン。私はあまりRustやりこんでないから分からんけど、C++のはコンパイラとの死闘だったよ。私「.........ソコ、ナニモオカシクナイヨ」もうこんなことがしょっちゅう。コンパイラがエラーに気がついた場所で会って、実際のエラー原因は遙か遠いところにあったりするの。何度コンパイラにブレークポイントぶち込みたいと思ったことか。長大なエラーレポートを追っていって、どこで型が化けたのかを解析するんだけど、結局は大体の原因は以下の5つに分類されると思う。いつの間にかconstがついてた・消えてたいつの間にか参照がついてたいつの間にかポインタが消えてたいつの間にか暗黙に変換されてた勘違いによりそもそも型・変数が違う(タイポ含む)こういう、なんか思ってたんと違う型の化けにより、本来私が進むと思ってるルートを外れて、別な関数コールを走り始め、問題にぶち当たったところでエラーが出される訳です。二度とやりたくないね。sourceって言うて動かない。Helm本体の仕様が変わったらしく、1年放置されているhelm-swoopが仕様変更に対応してないのが問題っぽい。helm-swoop--edit)を追加して、byte-reconpile-fileして、file-loadをしたら、動きました。19:08もっと読むコメントを書く2019-06-04組み込み屋さんのC++学習は普通にやっちゃ駄目って話C/C++周囲の組み込み屋さんを闇のC++プログラマに堕落させたいと目論む訳ですが、組み込み屋さんが普通のC++の教科書を片手にお勉強しちゃ駄目だよねって話。取り纏めもないメモ書きなんだけど。私はもう流石にC++の入門書は手元にないのですが、例えば、私もかつては書籍を持っていたロベールのC++教室などは、第一章をすっ飛ばすと第二章でクラスの話に入っていく訳です。普通それでいいんですけど、組み込みのリソース少ない世界において、オブジェクト指向は不要とまで言い切りはしませんが、必須じゃありません。それどころか、new,delete,virtual辺りは害悪と言っても良いでしょう。コンストラクタとかも、場合によっては危険ですね。staticだったり、グローバルな変数の初期化順序とか絡むので。なによりvolatileが絡むとクッソ面倒くさい。メモリ小さいから殆どスタックに変数を配置することもないですし、極論を言ってしまえば、組み込みのC++で有効なオブジェクト指向は、デストラクタ以外に特に見当たりません。ステップ数増えるからポインタによる間接参照は極力したくないしね。その辺はコードサイズとの兼ね合いもあるけど。C言語からの差分でC++を勉強するんだったら、大体、以下の内容を勉強すれば良いんじゃないかなぁ。string,vector,mapなど、ていうかstd::arrayとstd::tuple以外の殆どのクラス。型(struct)を用いた静的なポリモーフィズムtuple,type_traits,utility,initializer_listヘッダマクロ可変長引数マクロま、何にせよ、普通に学習してstd::coutだの、string、vectorだの、クラスだのを勉強するのは、無駄とは言わないけど、後で良いと思います。03:18もっと読むコメントを書く次のページプロフィールJavaで画像AI屋だったハズが、気がついたら制御論理やってて、Eclipse開発してて、組み込み屋で、CortexM4周りの開発してて、VerilogでRTL書いてて、STAしてて、色んな小さいインフラ管理してる、何でも屋。働きたくないでござる。(14)スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。