クロージャによるクラスの代替

個人的にクロージャが使えればクラスの構文は要らないと思っている。例としてスタックを表すクラスをクロージャを使って定義してみる。

まず、D言語で。

import std.array;

template Stack(T)
{
  // Stackクラスに相当
  struct Stack
  {
    void delegate(T) push;  // 構造体メンバはpublicになる。
    T delegate() pop;       // 構造体メンバはpublicになる。
  }

  // Stack.new()に相当
  Stack create()
  {
    Stack obj;     // Stackオブジェクトに相当
    T[] arr = [];  // レキシカル変数のためprivateになる。

    // メソッドの定義(クロージャ)
    obj.push = (T n) {
      arr ~= n;
    };
    obj.pop = () {
      auto b = arr.back;
      arr.popBack;
      return b;
    };

    return obj;
  }
}

import std.stdio;

void main()
{
  auto a = Stack!(int).create();
  auto b = Stack!(int).create();

  a.push(0); b.push(5);
  a.push(1); b.push(6);
  a.push(2); b.push(7);
  a.push(3); b.push(8);
  a.push(4); b.push(9);

  writeln( "a:", a.pop(), " b:", b.pop() );  // a:4 b:9
  writeln( "a:", a.pop(), " b:", b.pop() );  // a:3 b:8
  writeln( "a:", a.pop(), " b:", b.pop() );  // a:2 b:7
  writeln( "a:", a.pop(), " b:", b.pop() );  // a:1 b:6
  writeln( "a:", a.pop(), " b:", b.pop() );  // a:0 b:5
}

そして、Perlでも。

#! /usr/bin/perl
use strict;
use warnings;

# Stack::new()に相当
sub Stack_create {
  my %Stack;             # Stackオブジェクトに相当
  my @arr = ();          # レキシカル変数のためprivateになる。
  
  # メソッドの定義(クロージャ)
  $Stack{"push"} = sub { # ハッシュメンバはpublicになる。
    my ($n) = @_;
    push @arr, $n;
  };
  $Stack{"pop"} = sub {  # ハッシュメンバはpublicになる。
    return pop @arr;
  };
  return \%Stack;
}

my $a = Stack_create();
my $b = Stack_create();

$a->{"push"}->(0); $b->{"push"}->(5);
$a->{"push"}->(1); $b->{"push"}->(6);
$a->{"push"}->(2); $b->{"push"}->(7);
$a->{"push"}->(3); $b->{"push"}->(8);
$a->{"push"}->(4); $b->{"push"}->(9);

print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n";  # a:4 b:9
print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n";  # a:3 b:8
print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n";  # a:2 b:7
print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n";  # a:1 b:6
print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n";  # a:0 b:5

クラスはクロージャと構造体の組み合わせ。