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

package _FizzBuzz;
use overload (
	'""' => sub{ $_[0]->string || $_[0]->number },
	'0+' => sub{ $_[0]->number },
	fallback => 1
);

sub new { bless [ @_[1, 2] ], (ref $_[0] || $_[0]) }
sub number { $_[0]->[0] }
sub string { $_[0]->[1] }

package main;

sub _fizz_buzz {
	my ($o, $n, $s) = @_;

	return (
		(ref $o eq '_FizzBuzz') ?
			$o->new($o->number, $o->string . ($o->number % $n ? '' : $s)) :
			_fizz_buzz(_FizzBuzz->new($o, ''), $n, $s)
	);
}

sub fizz { _fizz_buzz($_[0], 3, 'Fizz') }
sub buzz { _fizz_buzz($_[0], 5, 'Buzz') }
sub gizz { _fizz_buzz($_[0], 7, 'Gizz') }

say buzz fizz 1;
say buzz fizz 3;
say buzz fizz 5;
say buzz fizz 15;
say buzz fizz 998;

say gizz buzz fizz 7;
say gizz buzz fizz 21;
say gizz buzz fizz 35;
say gizz buzz fizz 105;
say buzz gizz fizz 105;

say buzz(fizz(1)) + 2;
say fizz(buzz(fizz(1)) + buzz(2));
say gizz(buzz(fizz(15))) . "XXX";
