use 5.014;

use strict;
use warnings;
use routines;

use Test::Auto;
use Test::More;

=name

Pluto

=cut

=tagline

Functional Programming

=cut

=abstract

Functional Scripting for Perl 5

=cut

=synopsis

  package Cosmos;

  use Pluto;

  call(string('hello world'), 'titlecase');

  # Hello World

=cut

=libraries

Types::Standard

=cut

=description

This package enables functional programming for Perl 5 via indirect routine
dispatching and dependency injection, operating in a way that plays nicely with
third-party libraries without having to switch over to object-oriented
programming.

+=head1 WHY

Perl is a multi-paradigm programming language that supports functional
programming, but, Perl has an intentionally limited standard library with an
emphasis on providing library support via the CPAN which is overwhelmingly
object-oriented. This makes developing in a functional style difficult as
you'll eventually need to rely on a CPAN library that requires you to switch
over to object-oriented programming.

=cut

=scenario array

This package supports making the C<array> function available in the calling
package if it doesn't exist already. This function creates a
L<Data::Object::Array> object.

=example array

  # given: synopsis

  array;

=cut

=scenario bool

This package supports making the C<bool> function available in the calling
package if it doesn't exist already. This function creates a
L<Data::Object::Boolean> object.

=example bool

  # given: synopsis

  bool;

=cut

=scenario call

This package supports making the C<call> function available in the calling
package. This function dispatches function and method calls to a package.

=example call

  # given: synopsis

  call('Test', 'ok');

=cut

=scenario code

This package supports making the C<code> function available in the calling
package if it doesn't exist already. This function creates a
L<Data::Object::Code> object.

=example code

  # given: synopsis

  code;

=cut

=scenario false

This package supports making the C<false> function available in the calling
package if it doesn't exist already. This function creates a
L<Data::Object::Boolean> object.

=example false

  # given: synopsis

  false;

=cut

=scenario float

This package supports making the C<float> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Float> object.

=example float

  # given: synopsis

  float;

=cut

=scenario hash

This package supports making the C<hash> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Hash> object.

=example hash

  # given: synopsis

  hash;

=cut

=scenario number

This package supports making the C<number> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Number> object.

=example number

  # given: synopsis

  number;

=cut

=scenario regexp

This package supports making the C<regexp> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Regexp> object.

=example regexp

  # given: synopsis

  regexp;

=cut

=scenario space

This package supports making the C<space> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Space> object.

=example space

  # given: synopsis

  space;

=cut

=scenario string

This package supports making the C<string> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::String> object.

=example string

  # given: synopsis

  string;

=cut

=scenario true

This package supports making the C<true> function available in the)calling
package if it doesn't exist already. This function creates a
L<Data::Object::Boolean> object.

=example true

  # given: synopsis

  true;

=cut

package main;

my $test = testauto(__FILE__);

my $subs = $test->standard;

$subs->synopsis(fun($tryable) {
  ok my $result = $tryable->result;
  is $result, 'Hello World';

  $result
});

$subs->scenario('array', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Array');

  $result;
});

$subs->scenario('bool', fun($tryable) {
  ok !(my $result = $tryable->result);
  ok $result->isa('Data::Object::Boolean');

  $result;
});

$subs->scenario('code', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Code');

  $result;
});

$subs->scenario('false', fun($tryable) {
  ok !(my $result = $tryable->result);
  ok $result->isa('Data::Object::Boolean');

  $result;
});

$subs->scenario('float', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Float');

  $result;
});

$subs->scenario('hash', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Hash');

  $result;
});

$subs->scenario('number', fun($tryable) {
  ok !(my $result = $tryable->result);
  ok $result->isa('Data::Object::Number');

  $result;
});

$subs->scenario('regexp', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Regexp');

  $result;
});

$subs->scenario('space', fun($tryable) {
  ok my $result = $tryable->result;
  ok $result->isa('Data::Object::Space');

  $result;
});

$subs->scenario('string', fun($tryable) {
  ok !(my $result = $tryable->result);
  ok $result->isa('Data::Object::String');

  $result;
});

$subs->scenario('true', fun($tryable) {
  my $result = $tryable->result;
  ok $result->isa('Data::Object::Boolean');

  $result;
});

ok 1 and done_testing;
