関数型プログラミング言語に関するいくつかの質問から、XSLT が関数型プログラミング言語であるかどうかについて考えさせられました。そうでない場合、どの機能が欠けていますか? XSLT 2.0 はギャップを縮めたり、埋めたりしましたか?
6 に答える
XSLT は、ステートフルではなく宣言型です。
XSLT は関数型プログラミングのアイデアに基づいていますが、完全な関数型プログラミング言語ではなく、関数をファースト クラスのデータ型として扱う機能がありません。不要な評価を減らすための遅延評価や、明示的なループの不在などの要素があります。
ただし、関数型言語のように、複数のプロセッサ間で自動的に安全なマルチスレッド化を行うことでうまく並列化できると思います。
ウィキペディアからXSLT :
言語として、XSLT は関数型言語や、SNOBOL や awk などのテキスト ベースのパターン マッチング言語の影響を受けています。その最も直接的な前身は DSSSL でした。これは、XSLT が XML に対して実行するのと同じ機能を SGML に対して実行する言語です。XSLT は、テンプレート プロセッサと見なすこともできます。
これは、 FXSL の助けを借りてXSLT を関数型言語として使用するための優れたサイトです。FXSL は、高階関数のサポートを実装するライブラリです。
FXSL のおかげで、XSLT 自体が完全に機能する必要はないと思います。将来的には FXSL が W3C 標準に含まれる可能性がありますが、その証拠はありません。
皆さんは今ではこのリンクを見つけたと確信しています:-) http://fxsl.sourceforge.net/articles/FuncProg/Functional%20Programming.html .
XSLT のまあ関数は、結局、いくつかの回避策を備えた第一級市民です :-)
プログラミングをしている時はこんな感じです。
XSLT は、関数の定義と、入力ストリームを下って来る選択されたイベントへの関数の適用に完全に基づいています。
XSLT を使用すると、変数を設定できます。関数型プログラミングでは、関数に副作用を持たせることはできません。これは大きな問題です。
それでも、XSLT で書くと、「FP のやり方で作業するのと同じ感覚になります。入力を操作しているのであり、入力を変更しているのではなく、出力を作成しています。
これは、DOM API を使用するときに使用されるプログラミング モデルとは非常に異なるプログラミング モデルです。DOM は入力と出力をまったく分離しません。あなたはデータ構造を手渡され、躊躇も制限も後悔もせずに、あなたが適切だと思う方法でそれを壊します。
FP とその背後にある原則が好きなら、おそらく快適に作業できるでしょう。イベント駆動型プログラミング (および XML 自体) の経験があれば、それに慣れることもできます。
あなたの唯一の経験がトップダウンの非イベント駆動型プログラムである場合、XSLT は非常になじみのない、異質な風景です。少なくとも最初は。少し経験を積んでから、XPath 式とイベント処理が本当に快適になったときに XSLT に戻ると、かなりの成果が得られます。
ほとんどの場合、XSLT が 100% 関数型プログラミング言語ではない理由は、関数をファーストクラスのデータ型として扱うことができないためです。
他にもいくつかあるかもしれませんが、それが明白な答えです。
幸運を!
Saxon-SA は、XSLT を機能させるいくつかの拡張機能を導入しました。を使用saxon:function()
して関数値 (実際には{http://net.sf.saxon/java-type}net.sf.saxon.expr.UserFunctionCall
値) を作成し、それを で呼び出すことができますsaxon:call()
。
Saxon-B には、 と の組み合わせによる同様の機能がsaxon:expression()
ありsaxon:eval()
ます。違いは、saxon:expression()
任意の XPath 式を取り、それをsaxon:eval()
評価するのに対し、呼び出すsaxon:function()
関数の名前を取ることsaxon:call()
です。
変数を宣言することしかできず、宣言後にそれらの値を変更することはできないため、これは実際には引数ではありません。その意味で、ノバチェフ氏の記事で述べられているように、これは命令型ではなく宣言型です。
Scheme や Erlang などの関数型プログラミング言語を使用すると、変数を宣言することもできます。Haskell では、それも可能です。
-- 関数 'test' は変数 x を取り、それをリスト xs のすべての要素に追加します
test :: [Int] -> [Int]
test xs = map (+ x) xs
where x = 2