Movatterモバイル変換


[0]ホーム

URL:


ぐるぐる~

この広告は、90日以上更新していないブログに表示しています。

プログラミング言語の構文って大事だよね、という話

Twitterでこんなつぶやきをしました。

プログラミング言語としてのSQL(select)とか、プログラミング言語としてのXSLTとかやると、構文大事って実感持ててオススメ。オススメはしない。

— ぐるぐる系SQL (@bleis)2021年4月24日

が、ちょっと違う感じに受け取られたかな、と思ったので補足します。

プログラミング言語としての」とは

つぶやきの中でいちいち「プログラミング言語としての」と書いたのは、「普通の」SQLや「普通の」XSLTとは違って、ということを明示したかったからです。

普通はSQLは問合せのための言語だし、XSLTXMLを変換するための言語*1であって、JavaC#などのプログラミング言語と同じようなものと見ている人はほぼいないでしょう。ただ、ちょっとしたテクニックを知っていると、これらを使って「普通の」プログラミング言語でやるような処理が書けてしまうのです。

XSLTでプログラミング

XSLTにはループや分岐が組み込まれているので、手続き型プログラミングであればどうとでもなります。なりますが、それでは面白くないのでループを封印してみましょう。

ループを使わないXSLTプログラミング

XSLTではtemplate を関数とみなすことで、ループを使わなくても再帰呼び出しが使えます。あとは高階関数が使えればざっくり関数プログラミング的なものが出来ますね。詳しい説明はそのアイディアを形にした人が書いたドキュメント に譲るとして、そのテクニックを使うことでFizzBuzzrange 関数とmap 関数とfizzbuzz 関数を組み合わせることで書けてしまいます。

<?xml version="1.0" encoding="UTF-8"?><!-- 最近のXSLT事情がよくわからないけど、Saxonで動作確認(ファイル名: style.xsl) --><xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:fizzbuzz="fizzbuzz"version="3.0"><xsl:outputmethod="text"/><!-- fromからtoまでの数列を作る関数 --><xsl:templatename="range"as="xs:integer *"><xsl:paramname="from"as="xs:integer"/><xsl:paramname="to"as="xs:integer"/><xsl:choose><xsl:whentest="$from&lt;= $to"><xsl:sequenceselect="$from"/><xsl:call-templatename="range"><xsl:with-paramname="from"select="$from + 1"/><xsl:with-paramname="to"select="$to"/></xsl:call-template></xsl:when><xsl:otherwise></xsl:otherwise></xsl:choose></xsl:template><!-- シーケンスのmap関数 --><xsl:templatename="map"><xsl:paramname="sequence"/><xsl:paramname="f"/><xsl:choose><xsl:whentest="empty($sequence)"></xsl:when><xsl:otherwise><xsl:variablename="v"><xsl:apply-templatesselect="$f"><xsl:with-paramname="arg0"select="$sequence[1]"/></xsl:apply-templates></xsl:variable><xsl:sequenceselect="$v"/><xsl:call-templatename="map"><xsl:with-paramname="sequence"select="$sequence[position() > 1]"/><xsl:with-paramname="f"select="$f"/></xsl:call-template></xsl:otherwise></xsl:choose></xsl:template><fizzbuzz:fizzbuzz/><!-- 数値を与えるとFizzBuzzかFizzかBuzzか数値自身を返す関数 --><xsl:templatename="fizzbuzz"match="*[namespace-uri()='fizzbuzz']"><xsl:paramname="arg0" /><xsl:variablename="n"select="number($arg0)"/><xsl:choose><xsl:whentest="$n mod 15 = 0"><xsl:value-ofselect="'FizzBuzz&#x0A;'"/></xsl:when><xsl:whentest="$n mod 5 = 0"><xsl:value-ofselect="'Buzz&#x0A;'"/></xsl:when><xsl:whentest="$n mod 3 = 0"><xsl:value-ofselect="'Fizz&#x0A;'"/></xsl:when><xsl:otherwise><xsl:value-ofselect="$n"/><xsl:value-ofselect="'&#x0A;'"/></xsl:otherwise></xsl:choose></xsl:template><!-- エントリーポイント --><xsl:templatematch="/"><xsl:variablename="from"select="input/from"/><xsl:variablename="to"select="input/to"/><xsl:variablename="xs"as="xs:integer *"><xsl:call-templatename="range"><xsl:with-paramname="from"select="$from"/><xsl:with-paramname="to"select="$to"/></xsl:call-template></xsl:variable><xsl:call-templatename="map"><xsl:with-paramname="sequence"select="$xs"/><xsl:with-paramname="f"select="document('')/*/fizzbuzz:*[1]"/></xsl:call-template></xsl:template></xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?><!-- 入力ファイル(ファイル名: input.xml) --><input><from>1</from><to>100</to></input>
# 実行方法$ saxon -s:input.xml -xsl:style.xsl -o:output.txt

長いので折り畳みましたが、これと同じようなことを F# で書くとこうなります。

letrecrange from ``to``=if from<= ``to``then from:: range(from+1) ``to``else[]letrecmap f=function|[]->[]| x::xs-> f x:: map f xsletfizzbuzz n=if n %15=0then"FizzBuzz\n"elif n %5=0then"Buzz\n"elif n %3=0then"Fizz\n"elsestring n+"\n"letxs= range1100xs|> map fizzbuzz|>List.iter(printf"%s")

大体機械的に対応は取れると思います。

SQLでプログラミング

SQL再帰クエリーによって再帰が書けます。しかし、XSLTとは違い関数に対応させられるようなものが(SELECT文の範疇では)ありませんし、高階関数など夢のまた夢です。そのため、SQLでのプログラミングはXSLTよりも困難です。

ただ、再帰クエリーでも使うWITH を「入力固定の関数」のようなものとみなすことで、ある程度の構造化は可能です。

-- 最近PostgreSQLを使っているのでPostgreSQL想定WITH RECURSIVE range_ (n_)AS (SELECT1UNIONALLSELECT n_ +1FROM range_WHERE n_ <100), fizzbuzz_ (n_, result_)AS (SELECT      n_    ,CASEWHEN n_ %15 =0THEN'FizzBuzz'WHEN n_ %5 =0THEN'Buzz'WHEN n_ %3 =0THEN'Fizz'ELSECAST(n_ASvarchar)ENDFROM    range_)SELECT *FROM fizzbuzz_;

さらに複雑なことがしたい場合、空白区切りなどの文字列をリストと見立てて操作することでよりいろいろなことができるようになります*2

構文って大事

こんな感じで、XSLTでプログラミングしようとすると大量のノイズで本来書きたい処理はタグの中に埋もれてしまいますし、SQL(select)でプログラミングしようとするとそもそも関数からしてないので考え方からして変えないといけません(そのための例としてはFizzBuzzは小さすぎたかも)。SQLで複雑なやつだと、SQL で数式を評価 (完全版 + α) - ぐるぐる~ あたりがオススメです。数式評価だけど、演算子の優先順位を設定可能な完全に頭おかしいやつです。

ということで、他の人にはあまりオススメできない、オススメの構文のありがたみが体感できる方法でした。制約された環境であれこれ考えるのが好きな人であればあるいは・・・

*1:言語?ツール?

*2:配列型やJSONを使うという選択肢もあるけどそれだとツマラナイ

検索

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp