プログラミング言語PHPにおける奇妙な型変換 "Type Juggling"・第2弾。真偽値との比較にも要注意。
<?php var_dump("Dreams come" == true); // bool(true) var_dump("Dreams come" === true); // bool(false) ?>
Type Juggling規則により「片方がbool型の場合は両辺をbool型として比較評価」する。
関連URL
プログラミング言語PHPにおける奇妙な型変換 "Type Juggling"・第2弾。真偽値との比較にも要注意。
<?php var_dump("Dreams come" == true); // bool(true) var_dump("Dreams come" === true); // bool(false) ?>
Type Juggling規則により「片方がbool型の場合は両辺をbool型として比較評価」する。
関連URL
C++20標準ヘッダ <chrono> カレンダー(Calendar)ライブラリが提供する、日付リテラル表記用の/
演算子オーバーロード一覧。
ノート:年月日順で日付リテラルを述する場合、少なくとも年(year
)フィールドは常に型を明示した方がトラブルリスク*1が小さい。/
演算子は左結合となることをお忘れなく。
#include <chrono> using namespace std::chrono; // 2022-06-13 auto date1 = 2022y/6/13; // OK: year_month_day{year{2022}, month{6}, day{13}} auto date2 = 2022/June/13; // NG: ill-formed auto date3 = 2022/6/13d; // NG: month_day{month{337}, day{13}} auto date4 = 2022/6/13; // NG: int{25} auto date2m = 2022/(June/13); // OK: 意図通りに解釈されはするものの auto date2d = 2022/(6/13d); // OK: これらの難解表記は避けるべき…
年月日指定:*2
左辺 | 右辺 | 結果 | 表記 |
---|---|---|---|
year | month | year_month | 年/月 * |
year | int | year_month | 年/月 * |
month | day | month_day | 月/日 * |
month | int | month_day | 月/日 * |
int | day | month_day | 月/日 * |
day | month | month_day | 日/月 |
day | int | month_day | 日/月 |
year_month | day | year_month_day | 年+月/日 * |
year_month | int | year_month_day | 年+月/日 * |
year | month_day | year_month_day | 年/月+日 * |
int | month_day | year_month_day | 年/月+日 * |
month_day | year | year_month_day | 月+日/年 |
month_day | int | year_month_day | 月+日/年 |
最終日指定:*3
左辺 | 右辺 | 結果 | 表記 |
---|---|---|---|
month | last_spec | month_day_last | 月/最終日 * |
int | last_spec | month_day_last | 月/最終日 * |
last_spec | month | month_day_last | 最終日/月 |
last_spec | int | month_day_last | 最終日/月 |
year | month_day_last | year_month_ |
年/月+最終日 * |
int | month_day_last | year_month_ |
年/月+最終日 * |
month_day_last | year | year_month_ |
月+最終日/年 |
month_day_last | int | year_month_ |
月+最終日/年 |
第n曜日指定:
左辺 | 右辺 | 結果 | 表記 |
---|---|---|---|
month | weekday_indexed | month_weekday | 月/第n曜日 * |
int | weekday_indexed | month_weekday | 月/第n曜日 * |
weekday_indexed | month | month_weekday | 第n曜日/月 |
weekday_indexed | int | month_weekday | 第n曜日/月 |
year_month | weekday_indexed | year_month_ |
年+月/第n曜日 * |
year | month_weekday | year_month_ |
年/月+第n曜日 * |
int | month_weekday | year_month_ |
年/月+第n曜日 * |
month_weekday | year | year_month_ |
月+第n曜日/年 |
month_weekday | int | year_month_ |
月+第n曜日/年 |
最終曜日指定:*4
左辺 | 右辺 | 結果 | 表記 |
---|---|---|---|
month | weekday_last | month_ |
月/最終曜日 * |
int | weekday_last | month_ |
月/最終曜日 * |
weekday_last | month | month_ |
最終曜日/月 |
weekday_last | int | month_ |
最終曜日/月 |
year_month | weekday_last | year_month_ |
年+月/最終曜日 * |
year | month_ |
year_month_ |
年/月+最終曜日 * |
int | month_ |
year_month_ |
年/月+最終曜日 * |
month_ |
year | year_month_ |
月+最終曜日/年 |
month_ |
int | year_month_ |
月+最終曜日/年 |
関連URL
*1:date3 は std::chrome::month クラスの未規定(unspecified)仕様により、大半のC++処理系で month_day{month{81}, day{13}} として保持される可能性が高い。(C++20 27.8.4.1/p1, 27.8.4.2/p1)
*2:ISO 8601準拠の記述順(年-月-日)のみをサポートするならば、表中 * 印オーバーロードのみで十分だったはず。
*3:ある月の最終日表現には std::chrono::last 定数を用いる。
*4:ある月の最終曜日を std::chrono::weekday_last 型 = std::chrono::weekday 型 + std::chrono::last 定数で表現する。
プログラミング言語Javaにおけるラムダ式は、その本体部に応じてvoid-compatible/value-compatible/その両方に区分される。
void-compatibleラムダ式はRunnable
などの戻り値を持たない(void
)関数型インタフェース(functional interface)へ、value-compatibleラムダ式はIntSupplier
などの戻り値をもつ関数型インタフェースへと代入できる。
import java.util.function.IntSupplier; // void-compatible Runnable r1 = () -> { }; // OK IntSupplier s1 = () -> { }; // NG // value-compatible Runnable r2 = () -> { return 42; }; // NG IntSupplier s2 = () -> { return 42; }; // OK // void-compatible かつ value-compatible Runnable r3 = () -> { throw new NullPointerException(); }; // OK IntSupplier s3 = () -> { throw new NullPointerException(); }; // OK final boolean TRUE = true; Runnable r4 = () -> { while (TRUE); }; // OK IntSupplier s4 = () -> { while (TRUE); }; // OK
Java Language Specification, Java SE 8 Editionより一部引用。
The rules in this section define two technical terms:
- whether a statement is reachable
- whether a statement can complete normally
(snip)
The rules are as follows:
Chapter 14. Blocks and Statements, 14.21. Unreachable Statements
- (snip)
- A
while
statement can complete normally iff at least one of the following istrue
:
- The
while
statement is reachable and the condition expression is not a constant expression (§15.28) with valuetrue
.- There is a reachable
break
statement that exits thewhile
statement.- (snip)
- A
break
,continue
,return
, orthrow
statement cannot complete normally.- (snip)
A block lambda body is void-compatible if every
return
statement in the block has the formreturn;
.A block lambda body is value-compatible if it cannot complete normally (§14.21) and every
return
statement in the block has the formreturn Expression;
.(snip)
Note that the void/value-compatible definition is not a strictly structural property: "can complete normally" depends on the values of constant expressions, and these may include names that reference constant variables.
Chapter 15. Expressions, 15.27.2. Lambda Body
関連URL
GCCとClangの独自拡張 returns_twice 属性についてメモ。
対象関数から「2回以上制御が戻ってくる可能性」*1をコンパイラに伝える属性。コンパイラによる一部の最適化処理を抑止する。
The
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.htmlreturns_twice
attribute tells the compiler that a function may return more than one time. The compiler ensures that all registers are dead before calling such a function and emits a warning about the variables that may be clobbered after the second return from the function. Examples of such functions aresetjmp
andvfork
. Thelongjmp
-like counterpart of such function, if any, might need to be marked with thenoreturn
attribute.
https://llvm.org/docs/LangRef.html
returns_twice
This attribute indicates that this function can return twice. The Csetjmp
is an example of such a function. The compiler disables some optimizations (like tail calls) in the caller of these functions.
関連URL
*1:関数から制御が戻ってこないことを表明するnoreturn属性と対をなす。
gcc(g++) 12.1にて、inline関数に対して暗黙に constexpr 指定を行うコンパイルオプション -fimplicit-constexpr が導入された。同オプションはC++14/17/20言語仕様に対する独自拡張として機能する。
With each successive C++ standard the restrictions on the use of the constexpr keyword for functions get weaker and weaker; it recently occurred to me that it is heading toward the same fate as the C register keyword, which was once useful for optimization but became obsolete. Similarly, it seems to me that we should be able to just treat inlines as constexpr functions and not make people add the extra keyword everywhere.
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=87c2080b
関連URL
JavaScript(ECMAScript)で連番配列を生成するコード片。いわゆる range 関数に相当。
// NG: [undefined, undefined, undefined, undefined, undefined] // { length: 5 } のみ設定されたArrayオブジェクトが生成される // 各要素は未設定(undefinedとも異なる状態)となっている Array(5).map((val, idx) => idx); [,,,,,].map((val, idx) => idx); // OK: [0, 1, 2, 3, 4] Array(5).fill(undefined).map((val, idx) => idx); Array(5).fill(0).map((val, idx) => idx); Array.from(Array(5), (val, idx) => idx); Array.from({length: 5}, (val, idx) => idx); [...Array(5)].map((val, idx) => idx); [...Array(5).keys()];
関連URL
次期C++2b(C++23)標準ライブラリに追加されるstd::expected<T, E>
クラステンプレートについてメモ。
T
型)またはエラー情報(E
型)を “値” として返す(return)ための部品。std::optional<T>
型の無効値(std::nullopt
)表現に代わり、具体的なエラー情報(E
型)を保持可能に拡張された型。*1expected<T, E>
、補助型unexpected<E>
*2、タグunexpect
、例外型bad_expected_access<E>
expected<T, E>
== 結果T
とエラーunexpected<E>
の直和型*3
expected<void, E>
特殊化 == エラーのみを保持するstd::optional
同様に参照型は未サポートexpected<T, E>
型への代入:
T
へ変換可能な型:r = t;
またはr = {std::in_place, t};
*4E
へ変換可能な型:r = std::unexpected(e);
またはr = {std::unexpect, e};
expected
モナディック(monadic)操作はoptional
モナディック操作(and_then
, or_else
など)は P0789R8 が採択済み。expected
モナディック操作群が追加される。Boost.Outcomeライブラリとの比較:
std::expected<T, E>
is Outcome's checked<T, E>
?関連URL
*1:std::optional<T> ≒ std::expected<T, std::nullopt_t>
*2:C++20現在、識別子 unexpected はZombie nameとして予約されおり、expected<T, E> 導入に伴ってC++2bで蘇生(?)された初のケース。C++的ゾンビのお名前 参照。
*3:無効値 nullopt でデフォルト構築される std::optional<T> とは異なり、エラー情報を明示的に保持する std::expected<T, E> ではデフォルト構築後は結果値 T{} を保持している。
*4:https://cpprefjp.github.io/reference/utility/in_place_t.html
*5:if文の条件式などに expected<T, E> 型の値を記述することで、結果を保持しているか否かを判定可能(→id:yohhoy:20121110)
*6:提案文書P0323R12 §3.14: "Using the indirection operator for an object that does not contain a value is undefined behavior. This behavior offers maximum runtime performance."
*7:https://github.com/cplusplus/papers/issues/1161#issuecomment-1027125553