そうではありませんが、実際には問題ではないかもしれません。
表面上は(foo) => Symbol(foo)
純粋に見えます。ランタイムは副作用のある操作を実行する場合がありますSymbol()
が、同じパラメーターで同時に呼び出したとしても、それらが表示されることはありません。ただし、同じ引数を指定して呼び出すSymbol
と、同じ値が返されることはありません。これは、主な基準の 1 つです (以下の #2)。
MDN ページから:
Symbol("foo") は文字列 "foo" をシンボルに変換しないことに注意してください。毎回新しいシンボルを作成します。
Symbol("foo") === Symbol("foo"); // false
副作用だけを見ると、(foo) => Symbol(foo)
純粋です(ランタイム以上)。
ただし、純粋関数はより多くの基準を満たす必要があります。ウィキペディアから:
純粋に機能的な関数 (または式) には、副作用 (メモリまたは I/O) がありません。これは、純粋関数にはいくつかの有用なプロパティがあり、その多くをコードの最適化に使用できることを意味します。
- 純粋な式の結果が使用されていない場合は、他の式に影響を与えることなく削除できます。
- 純粋な関数が副作用を引き起こさない引数で呼び出された場合、結果はその引数リストに関して一定です (参照透過性と呼ばれることもあります)。つまり、純粋な関数が同じ引数で再度呼び出された場合、同じ結果が返されます。返されます (これにより、メモ化などのキャッシュの最適化が有効になります)。
- 2 つの純粋な式の間にデータの依存関係がない場合、それらの順序を逆にするか、並列で実行でき、互いに干渉することはありません (つまり、純粋な式の評価はスレッドセーフです)。
- 言語全体で副作用が許容されない場合は、任意の評価戦略を使用できます。これにより、コンパイラーは、プログラム内の式の評価を並べ替えたり、組み合わせたりする自由が与えられます (たとえば、森林伐採を使用)。
そのリストの序文は JavaScript のすべてを除外していると主張することができます。なぜなら、操作によってメモリが割り当てられたり、内部構造が更新されたりする可能性があるからです。最も厳密な解釈では、JS は決して純粋ではありません。それはあまり面白くも役に立たないので...
この関数は基準 1 を満たしています。結果を無視し、外部の観察者と同じです(foo) => Symbol(foo)
。(foo) => ()
基準 2 は、さらに問題を引き起こします。を考えるbar = (foo) => Symbol(foo)
とbar('xyz') !== bar('xyz')
、Symbol
その要件をまったく満たしていません。を呼び出すたびに、一意のインスタンスが返されることが保証されますSymbol
。
先に進みますが、基準 3 は問題ありません。競合することなく (並列) 異なるスレッドから呼び出すことができ、呼び出さSymbol
れる順序は関係ありません。
最後に、基準 #4 は、直接的な要件というよりも重要であり、簡単に満たすことができます (JS ランタイムは、進行中にすべてをシャッフルします)。
したがって:
- 厳密に言えば、JS には純粋なものはありません。
Symbol()
は間違いなく純粋ではないため、この例もそうではありません。
- メモ化ではなく副作用だけを気にするのであれば、この例はそれらの基準を満たしています。