以下の内容はhttps://eel3.hatenablog.com/entry/2025/12/27/220000より取得しました。


失われたHELLO WORLDをたずねて三万海里

自宅のPCのディスクの奥底からHello Worldを発掘し始めて2週間経った。我ながら色々な言語でHello Worldを書いてきたものだと、つくづく呆れている。

多少なりとも本格的に言語に触れたいならFizzBuzzを書くべきだろう。プログラムの実行環境との関係性を探るならargsなども考えられる。

でも、ほんのちょっとだけ、気の迷いでも構わないなら、Hello Worldは悪くない題材だ。

正統派なHello World

Hello Worldの起源はBCPLらしいが、有名になったのはC言語のバージョンだろう。C99以降にて合法的な版はこんな感じだろうか?

#include <stdio.h>

int main(void)
{
    puts("hello, world");
}

良くも悪くもC言語の影響は大きい。C言語の後継を目指した言語は色々とあるが、割とどれもmain関数から処理が始まる。例えばD言語の場合:

import std.stdio;

void main()
{
    writeln("hello, world");
}

愚考するに、C言語では、プログラムは「関数の塊」として抽象化されている節がある。ごく一部の例外の除き、式や文は関数の中に書く。プログラムは関数の入れ子として階層化される。

ここで、入れ子のもっとも外側の関数について、ホスト環境では便宜上mainという名前を付けることにしよう――といった塩梅だろうか? 今では言語仕様にすらなっている名前である。

時が経ち、モジュール機構やオブジェクト指向プログラミングの機能が言語に組み込まれるようになっても、下記のC++版のように関数で始まるスタイルは続いたように思う。

#include <iostream>

int main()
{
    std::cout << "hello, world" << std::endl;
}

――が、そのうちに、今度はプログラムを「オブジェクトの塊」として抽象化する言語が出てきた。その起源は知らないのだが、有名なのはJavaだろう。

class Hello {
    public static void main(String[] args) {
        System.out.println("hello, world");
    }
}

Javaの後に出てきたC#もそうである。

namespace HelloWorld
{
    using System;

    class Hello
    {
        static void Main(string[] args)
        {
            Console.WriteLine("hello, world");
        }
    }
}

後知恵になるが、いちプログラマとしては、言語仕様のレベルで「オブジェクトの塊」として抽象化してしまうのは、ちょっとやりすぎだったように思う。

プログラムを「オブジェクトの塊」として抽象化する――というスタイルの一貫性の観点では、割とキレイな抽象化だと思うのだ。

が、しかし、そんな言語を使うのは、曖昧で一貫性のかけらもない、薄汚れた我らプログラマである。ちょっとしたスクリプトを書くなら関数化すら不要と嘘吹き、小ツールを実装するには関数による機能分割で十分と豪語する。要するに、作るものの大きさに合わせて、どのレベルで抽象化するのかを自分でコントロールしたいのだ。わがまま極まりない。

――そういう事情があったか否かは定かではないのだが、JavaC#よりも後に出てきた言語では、再びmain関数から始まるスタイルに回帰している。

Dartも:

void main() {
  print('hello, world');
}

Goも:

package main

func main() {
    println("hello, world")
}

Rustも:

fn main() {
    println!("hello, world");
}

全てはmain関数に始まり、main関数で終わる。

――と言いたいところだが、昨今はSwiftなどのようにmain関数すらない(少なくともコードの見た目としては存在しない)汎用のプログラミング言語もある。

print("hello, world")

シンプルかつ正統派なHello World

main関数のようなブツの有無に関して想像するに、スクリプト言語の系譜では「そんなものはない」スタイルが常なように感じる。

まず、言語ではなく、コマンドラインインタプリタの一種であるUnixシェルや:

#!/bin/sh

echo hello, world

Windowsのバッチファイル:

@echo off

echo hello, world

これらの原型というか先祖の世代のバッチ言語やらマクロ言語の潮流から、REXXみたいなスクリプト言語が出てきたのかなあ、と妄想している。REXXの時点でmain関数が無い。

#!/usr/bin/env rexx

say "hello, world"
exit 0

スクリプト言語と言えば、私の世代ではPerl/Python/Rubyの三銃士の印象が強い。なぜか一括りにされているのだが、しかしよく見てみると、Perlと:

#!/usr/bin/env perl

use 5.030;
use strict;
use warnings;

say "hello, world";

Pythonと:

#!/usr/bin/env python3
"""hello, world
"""

print('hello, world')

Ruby

#!/usr/bin/env ruby

puts "hello, world"

Hello World程度ではまだ分からないが、もう少し手の込んだ小スクリプトを書こうとすると、どれも似てない。みんな違って、みんないい。でもmain関数が無いのは共通している。

Webクライアント開発の言語であるJavaScriptや:

#!/usr/bin/env node

console.log('hello, world');

TypeScriptのようなaltJSとして出てきた言語の大半:

#!/usr/bin/env -S deno run

console.log('hello, world');

これらもmain関数が無い。こう考えると、割とWeb開発系はフロントエンドもバックエンドもmain関数が無い言語の割合が多いのかもしれない。

いろんな言語のHello World

C言語の影響でmain関数のフォロワーが続出したと仮定するなら、では、同世代や前世代を起源とする言語はどうだろうか?

例えばPascal――は世代ではないし、Object Pascal(原典の方)も掠ってすらないので、Free Pascalで書いてみた版:

{$CODEPAGE UTF8}
{$MODE OBJFPC}
{$LONGSTRINGS ON}

program Hello;

begin
  WriteLn('hello, world');
end.

programで始まるスタイル。元ネタはFortranだろうか? Fortran 90版もprogramで始まる。

program hello
  print *, 'hello, world'
end program hello

FortranといえばCobolだが(偏見が過ぎる)、Cobolのコードは素人目にも異彩を放っているように感じられる。

       IDENTIFICATION   DIVISION.
       PROGRAM-ID.      HELLO.
       AUTHOR.          EEL3.
       DATE-WRITTEN.    2010-06-29.
      *
       ENVIRONMENT      DIVISION.
       CONFIGURATION    SECTION.
       SOURCE-COMPUTER. PC.
       OBJECT-COMPUTER. PC.
      *
      *DATA             DIVISION.
      *
       PROCEDURE        DIVISION.
       MAIN.
           DISPLAY "hello, world"
           STOP RUN.

Pascalは元々教育用途メインで開発されたらしいが、同じく教育分野で古典的な言語であるLOGOはどうだろうか?

; Worked on UCBLogo (Berkeley Logo)

print [hello, world]

シンプルに1行だけ。スクリプト言語っぽいスタイルである。元々インタプリタ的というかREPLで対話的というか、そういう感じだからなのかなあ?

そして古典の中でも異彩を放つ文法のLisp。今の時代でもCommon Lispや:

#!/usr/bin/env clisp

(format t "hello, world~%")
(quit)

もしくはSchemeの処理系は手に入りやすい。

#!/usr/bin/env gosh

(begin (display "hello, world")
       (newline))

言語処理系じゃないけどHello World

Lispといえば、汎用の処理系ではないが、Emacs Lispも一大勢力を築いている。

; emacs --batch -l hello.el

(message "hello, world")

なぜかよく対比されるviについても、Vimならスクリプトを記述できる。

" vim --cmd ':source hello.vim'

echo "hello, world"
quit!

秀丸エディタもそうだが、テキストエディタスクリプト機能を組み込むスタイルの起源はどこにあるのだろうか?

// https://hide.maruo.co.jp/software/hidemaru.html
insert "hello, world\n";

テキストエディタ以外にも、Hello Worldを書けるツールは色々ある。例えばmake(1)とか:

.PHONY: hello

hello:
	# hello, world

GDBのようなデバッガも、スクリプト機能を使えばOK。

#!/usr/bin/env -S gdb --batch -x

echo hello, world\n
quit

そして、一応計算機という立て付けのbc(1)でも:

/* bc -q -s hello.bc */

"hello, world
"
quit

計算機のハードの上でOSを動かし、その上で動作する計算機を作っておいて、なお計算機らしくない使い方をする。何とも度し難い。

身も蓋もないHello World

ここまで見てきたHello Worldの大半は式や文(命令?)をともなうものだったが、それすら省いたパターンもある。

モダンかつ一応言語っぽいところだとPowerShellだろうか?

<#
.SYNOPSIS
Hello world.

.INPUTS
None.

.OUTPUTS
hello, world

.EXAMPLE
C:\PS> .\hello.ps1
 #>
Set-StrictMode -Version Latest

'hello, world'

色々と余分なものを書いているが、肝の部分は'hello, world'だけである。

マクロプロセッサの類を含めると、事態は悪化する。例えばm4の版:

hello, world

これだと身も蓋もなさすぎるので、もう少し小細工を労してみると、こんな感じだろうか?

define(`HELLO', `hello,')dnl
define(`WORLD', `world')dnl
HELLO WORLD

m4ほとではないが、T4(Visual Studio付属のテキストテンプレート変換)の版も身も蓋もない:

<#@ template language="C#" #>
<#@ output extension=".txt" #>
hello, world

もうちょっとだけ特別感を出したいなら、こんな感じだろうか?

<#@ template language="C#" #>
<#@ output extension=".txt" #>
<#= "hello, world" #>

変わり種Hello World

身も蓋もないといえば、私は暇を持て余すあまりに「cat(1)用のHello World」というもはやHello Worldなのかすら怪しい代物を考え出したことがある。

hello, world

あまりに身も蓋もなさすぎて、さすがにrev(1)の方がマシだろうと考えたのだが……:

dlrow ,olleh

この手の一発ネタは、なかなか思いつかない。どうしても手を加えすぎてダメになってしまう。

paste(1)を使う版も割と失敗作である。

#!/bin/sh

paste -d '' - - - <<'END'
hello
, 
world
END

paste(1)版には元ネタがある。元々はxargs(1)とprintf(1)を使った版を考えていたのだが、うまくいかなくてpaste(1)版を作成したのである。

その後にxargs(1)とprintf(1)を使う版を完成させた。

#!/bin/sh

xargs printf %s%s%s\\n <<'END'
hello
', '
world
END

肝は', 'である。xargs(1)の仕様を調べていて「へーそうなんだ」と思った次第である。

思わぬ類似系Hello World

Hello Worldは時に既視感をもたらす。

スタック指向の言語、例えばForthとか:

( https://github.com/philburk/pforth )

s" hello, world"
type

あるいは、特にPostScriptとか:

%!
% ps2txt hello.ps

(hello, world\n) print
quit

この辺のHello Worldを書いた後に、オブジェクト指向言語のIoと:

#!/usr/bin/env io

"hello, world" println

GNU Smalltalkの版を見てみると:

#!/usr/bin/env -S gst -f

'hello, world' displayNl.

……どれも「テキスト → 命令」の順序になっている。だからと言って、特に何もないのだが。

未完のHello World

うまくいかなかったHello Worldも多い。

例えば、sed(1)を使うHello Worldを考えてみたのだが、どう頑張っても何かしらの入力が必要だった。

#!/usr/bin/env -S sed -f

s/^.*$/hello, world/
1q

echo '' | ./hello.sedなら動作するがecho -n '' | ./hello.sedだとダメなのだ。

XSL版も考えたが、こちらもやはり入力が必要だ。何かしらのXMLファイルを与えなくてはならない。

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="utf-8" />
  <xsl:template match="/">
    <xsl:text>hello, world&#x0A;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

まあ、Hello Worldを書いたXSL自体(つまり自分自身)を入力とすることで何とかなるのだが……。

もう少し未完成度が高いのはProlog版だろう。B-Prologで動かす前提で書いてみたのだが、規則の部分はファイルに記述できるものの、質問は別である。対話的に実行するか、もしくはコマンド引数などで与える必要がある。

% bp -g "consult('hello.pl'),hello,halt."

hello :- write('hello, world'),nl.

まとめ

2025年はHello Worldで締めたいと思う。2026年がHello Worldで始まるか否かは定かではない。ワイは鬼に笑われたくないんや……。




以上の内容はhttps://eel3.hatenablog.com/entry/2025/12/27/220000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14