私はここにいる(I'm here)。そう書いてある

おまとめ三行

ながーい文章をコードの中に埋め込みたい
ALI PROJECTの歌のタイトルみたいな字面だな
私はここにいる(I'm here)
プログラミングをしていると、ながーい文章をコードの中に埋め込みたいことがたまにあります。長い文字列ってだけなら何も考えず変数に突っ込めば良いんですが、例えばHTMLを変数に入れたい、しかもある程度見やすい状態でコードに入れたい、みたいな時。一行にまとめてしまうと可読性が悪くなるので、通常のHTMLを書く時のように改行したりネストした状態でコードの中に入れたい。

そんな時はヒアドキュメントってのを使うと良いです。

ちょっと前まではPHPしか触ってなかった僕ですが、ここ最近、仕事やプライベートで他の言語も触る機会が増えたので、そのいくつかの言語でヒアドキュメントの書き方の違いを見てみたいと思います。



PHPのヒアドキュメント

まずは僕が一番よく知ってるPHPから。

<?php
$var = '変数';
$text = <<<EOF
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{$var}も使用できます。
EOF;

PHPの場合は「<<<」と不等号を三つ並べてヒアドキュメントを開始します。あとは「EOF」という文字で囲った範囲が全部ヒアドキュメントになる。EOFと書くのが一般的なようですが、必ずしもこの三文字である必要はないみたいなので、同じ文字で囲いさえすれば「FOE」とか「KOF」とか「STREETFIGHTER」とかでも動作します。ドキュメントの中でPHPの変数を使うこともできます。



Pythonのヒアドキュメント

Pythonの場合はコーテーションを三つ連続でつなげたもので囲った範囲がヒアドキュメントになります。

text = '''
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
'''

コーテーションはシングルでもダブルでもオッケーです。書き方自体はPHPの時とほぼ同じですね。

ただしPythonのヒアドキュメントの中で変数を使いたい場合はPHPみたいに変数を入れるだけでは上手く動かないので、変数展開という方法を使います。

var = '変数'
text = """
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{var}も使用できます。
""".format(var = var)

Pythonの変数展開については以前書いたこともあるので、よかったらこちらも。

変数展開

そういやSlackでコードを記述する時にもコーテーション三つで囲いますよね。このPythonのヒアドキュメントから着想を得たりしてるんですかね?



C#のヒアドキュメント

最近Unityでゲーム制作をしてるのでC#もちょくちょく触っているんですが、そのC#でのヒアドキュメントはこうです。

string text = @"
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
";

先頭にアットマークをつけると文字列がヒアドキュメント扱いになります。正確にはヒアドキュメントではなく「逐語的リテラル文字列」とか「逐語的文字列リテラル」とか言うらしいです。ALI PROJECTの歌のタイトルみたいな字面だな。

C#で先頭に「$」をつけると文字列の中で変数を使うことができます。

string var = "変数";
string text = $"{var}";

コーテーションの中ではなく外に$をつける。これを応用すれば逐語的文字列リテラルの時も変数が使えます。

string var = "変数";
string text = $@"
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{var}も使用できます。
";

「$@」の順番で書きます。「@$」だと動かない。

ちなみにこれはC#のバージョンが6.0から有効になった機能らしいです。僕が使っているC#はまだバージョンが4.0だったので、この書き方だと動きませんでした。

バージョンが古い場合は「string.Format()」を使うと良いです。Pythonの変数展開と似たやり方ですね。

string var = "変数";
string text = string.Format(@"
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{0}も使用できます。
", var);



javascriptのヒアドキュメント

厳密に言うとjavascriptにはヒアドキュメントという概念がありません。なのでヒアドキュメントっぽく書く方法というのを試してみたいと思います。

let text = function(){/*
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{var}も使用できます。
*/}.toString().split("\n").slice(1, -1).join("\n");

ざっくり処理の内容を説明すると、まず無名関数の中にヒアドキュメントとして記述したい内容をコメントとして書きます。これを文字列として取得し、改行コードで配列に分割し、最初と最後の要素を除去した後、もう一度改行コードで連結することでヒアドキュメントと同様の処理が可能になる感じです。

上記の書き方の場合、split()を使って改行コードで分割すると中身がこんな風になります。

["function(){/*", "これはヒアドキュメントです。", "改行コードがなくても改行つきの文章を表示できます。", "*/}"]

なのでこの配列の最初と最後の要素を取り除けば、残りはコメントアウトされている中身のテキストだけになるので、それを再度改行コードで連結すれば望むテキストが得られるってすんぽうです。

中身がコメントアウトされているテキストなので変数を埋め込むことはできませんが、自分で置換処理を入れれば同等の動きは実現できます。

let var = '変数'
let text = function(){/*
これはヒアドキュメントです。
改行コードがなくても改行つきの文章を表示できます。
{var}も使用できます。
*/}.toString().split("\n").slice(1, -1).join("\n").replace(/{var}/, var);

replaceを使って自分で定義した変数用の文字列を置き換えています。






他にもいろんな言語があり、それぞれにヒアドキュメントがあったりなかったりしますが、僕が普段使っている言語はこんなところです。

PHPやPythonはともかくjavascriptは元からヒアドキュメントが用意されているわけではないので、こんな書き方を知っておけば何かあった時に役立つかもしれません。