Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Im looking for a way to encapsulate defaults with Type::Tiny types. #95

Closed
tomgreen98 opened this issue Aug 15, 2022 · 3 comments · Fixed by #103
Closed

Im looking for a way to encapsulate defaults with Type::Tiny types. #95

tomgreen98 opened this issue Aug 15, 2022 · 3 comments · Fixed by #103
Labels
enhancement implemented Implemented in repo, but not released yet
Milestone

Comments

@tomgreen98
Copy link

tomgreen98 commented Aug 15, 2022

I would like to do something like the following:

use strict;
use warnings;

package Types::Theme;

use strict;
use warnings;

use Types::Standard  qw(Str);
use Type::Tiny       ();

use Type::Library -base;

sub get_default_theme {
    # lets assume this is way more complex...
    return 'default';
}

__PACKAGE__->add_type(
    Type::Tiny->new(
        name       => 'Theme',
        parent     => Str,
        default => sub { get_default_theme() },
    )
);

1;

package Test::Object;
use Mouse;
use Types::Theme -mouse, qw(Theme);

has theme => ( is => 'rw', isa => Theme );

1;

package main;

use Test::Object;

my $obj = Test::Object->new();
say $obj->theme; # should return  `default`
$obj->theme("custom");
say $obj->theme; # should return `custom`

I know Moose, Mouse and Moo provide a default mechnism like:

package Test::Object;
use Mouse;
use Types::Theme -mouse, qw(Theme);

has theme => ( is => 'rw', isa => Theme, default => sub { ... );

1;

But this means that every place I defined a theme in my object model I need to also add the common default. If there was a way to bundle the default with the Type::Tiny, that would be amazing.

I wondered if I just missed such a mechanism in the current Type::Tiny or if this was a new idea that had merit to add to the library?

Please advise and thanks for an awesome tool

@tobyink
Copy link
Owner

tobyink commented Aug 16, 2022

I did work on a branch a while back with something along those lines. You'd do:

__PACKAGE__->add_type(
    Type::Tiny->new(
        name              => 'Theme',
        parent            => Str,
        default_generator => sub { get_default_theme() },
    )
);

Then:

has theme => ( is => 'rw', isa => Theme, default => Theme->default_generator );

Or:

has theme => Theme->spec( -rw, -default );

This providing a default would be impossible without altering how Moose/Mouse/Moo has keywords work:

has theme => ( is => 'rw', isa => Theme );

It's certainly possible, but it's maybe a little too magic. Someone looking at the code might be confused where the default is coming from!

The branch never went anywhere because I wasn't sure if it would be a feature people actually wanted or not.

Even with the current release, the following should work, even though it's a bit of a hack!

__PACKAGE__->add_type(
    Type::Tiny->new(
        name              => 'Theme',
        parent            => Str,
        default_generator => sub { get_default_theme() },
    )
);

...

has theme => ( is => 'rw', isa => Theme, default => Theme->{default_generator} );

For less of a hack, subclass Type::Tiny and add a default_generator accessor:

package Type::Tiny::WithDefault {
  use parent 'Type::Tiny';
  sub default_generator { $_[0]{default_generator} }
}

...

__PACKAGE__->add_type(
    Type::Tiny::WithDefault->new(
        name              => 'Theme',
        parent            => Str,
        default_generator => sub { get_default_theme() },
    )
);

...

has theme => ( is => 'rw', isa => Theme, default => Theme->default_generator );

@tobyink tobyink added this to the 2.0.0 milestone Aug 29, 2022
tobyink added a commit that referenced this issue Aug 30, 2022
@tobyink tobyink added the implemented Implemented in repo, but not released yet label Aug 30, 2022
@tobyink
Copy link
Owner

tobyink commented Aug 30, 2022

The next major release of Type::Tiny will include:

__PACKAGE__->add_type(
    Type::Tiny->new(
        name         => 'Theme',
        parent       => Str,
        type_default => sub { get_default_theme() },
    )
);

...

has theme => (
  is       => 'rw',
  isa      => Theme,
  default  => Theme->type_default,
);

And some of the builtin type constraints like ArrayRef, HashRef, Int, etc will have defaults supplied. (Usually something obvious like an empty array, empty hashref, empty string, zero, undef, etc.)

@tomgreen98
Copy link
Author

This is awesome. Thanks for adding it. Just want I was hoping for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement implemented Implemented in repo, but not released yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants