📜

Julia言語での複数行文字列のインデントの扱い

2022/07/22に公開

導入

Pythonでは"""内の空白文字はそのまま入ります。

>>> def g():
...     s = """
...     hoge
...     """
...     print(repr(s))
... 
>>> g()
'\n    hoge\n    '

一方、Juliaではインデントを検出していい感じに空白文字を除去してくれます。

julia> function g()
           s = """
           hoge
           """
           display(s)
       end
g (generic function with 1 method)

julia> g()
"hoge\n"

Juliaの方が可読性良いと思いますが、どのように処理されているのでしょうか?文字列内のインデントが狂った場合など、イレギュラーなケースをどのように処理するのか気になったので少し実験してみました。

実験

すこし長いですが:

function check_string_indent()
    s1 = """
    hoge
    """

    s2 = """hoge
    """

    s3 = """

    hoge
    """

    s4 = """ 
    hoge
    """

    s5 = """hoge
    fuga"""

    s6 = """
    hoge
  fuga
    piyo
    """

    s7 = """
    hoge\
    fuga\
    piyo
  """

    s8 =
  """
    hoge
      fuga
        piyo
          """

    s9 = """
    """

    s10 = """
      hoge
      fuga
      """

    s11 = """  hoge
               fuga
               """

    s12 = """
      hoge
      fuga
    $("  ")"""

    s13 = """
      hoge
      fuga
    """ * "  "

    s14 = "  hoge
  fuga
  "

    @show s1
    @show s2
    @show s3
    @show s4
    @show s5
    @show s6
    @show s7
    @show s8
    @show s9
    @show s10
    @show s11
    @show s12
    @show s13
    @show s14
    nothing
end

check_string_indent()

を実行すると

s1 = "hoge\n"
s2 = "hoge\n"
s3 = "\nhoge\n"
s4 = " \nhoge\n"
s5 = "hoge\nfuga"
s6 = "  hoge\nfuga\n  piyo\n  "
s7 = "  hogefugapiyo\n"
s8 = "hoge\n  fuga\n    piyo\n      "
s9 = ""
s10 = "hoge\nfuga\n"
s11 = "  hoge\nfuga\n"
s12 = "  hoge\n  fuga\n  "
s13 = "  hoge\n  fuga\n  "
s14 = "  hoge\n  fuga\n  "

の出力が得られます。

ルール

  1. はじまりの"""直後の改行文字は1つまで無視される。 (s1, s2, s3)
  2. おわりの"""直前の改行文字は無視されない。 (s5)
  3. インデント位置は「文字列本文の最前位置」と「おわりの"""の位置」のうちインデントが浅い方が採用される。はじまりの"""の位置は影響しない (s6, s7, s8)
  4. 行末の\は改行なしとして扱われる。 (s7)
  5. 行末のスペースには注意が必要。 (s4)
  6. ルール1とルール2ではルール1の方が有線される。 (s9)
  7. インデントを考慮した代償として、すべての行にインデントが含まれると少し面倒。 (s10, s11, s12, s13, s14)[1]

タブ文字(U+0009)や特殊な空白文字(U+00A0etc.)などが混在した場合は…面倒なので調べていません。

公式ドキュメントではこちら(↓)に記載されています。[2]
https://docs.julialang.org/en/v1/manual/strings/#Triple-Quoted-String-Literals

感想

初めて複数行文字列内でインデントできることを知ったときは少し面食らいましたが、Juliaの方がPythonに比べて読みやすいですね。Pythonは構文でインデントを強制する割に複数行文字列で可読性落ちてしまいますが、破壊的変更を避けるためにJuliaの方式を導入できないのでしょう。この点に関して後発の言語の方が有利だったと思います。

Julia以外の言語でインデントに考慮した複数行文字列が扱えるものは知らないので、コメントで教えてもらえると嬉しいです。

脚注
  1. Discourseで質問したスレッドはこちら ↩︎

  2. 公式ドキュメントの焼き直しの記事を書くのは少し躊躇われましたが、実験の記録として書いてしまいました。 ↩︎

GitHubで編集を提案

Discussion