Banal-Role-Fallback

 view release on metacpan or  search on metacpan

lib/Banal/Role/Fallback/Tiny.pm  view on Meta::CPAN

#######################################
sub _resolve_href { # Explicitely asks for a hash reference
#######################################
  my  $self     = shift;
  my  $opt    = ( ref ($_[0]) =~ /HASH/ ) ? shift : {};
  $self->_resolve( {  %$opt, want_reftype => 'HASH' }, @_ );
}


# Practical method-helper for determining the effective value to be used for a given attribute for a given object.
# The object would need to satisfy several conditions, though
#######################################
sub _fallback   {
#######################################
  local $_;
  my ($o, %opt)     = &_normalize_fallback_opts;
  my  @keys         = tidy_arrayify( $opt{keys} );
  my  @blankers     = tidy_arrayify( $opt{blanker_token} );
  my  @mid          = tidy_arrayify( @opt{qw( via )});
      @mid          = tidy_arrayify( @opt{qw( mid nrm normally )}, \&_smart_lookup) unless !!@mid;
  my  @attempts     = tidy_arrayify(
                          @opt{qw( apriori primo )},
                          @mid,
                          @opt{qw( def last fin final finally )}
                        );
  my  @res;
  my  $debug         = $opt{debug};

  # say STDERR "Looking up keys : " . np @keys if $debug;
ATTEMPT:
  foreach my $item (@attempts) {
    next unless defined $item;
    my $v = (reftype($item) // '') eq 'CODE'
              ? eval { $item->($o, \%opt) }
              : $item;

    # say STDERR "Attempt died on us : $@"  if $@ && $debug;

    if (defined($v) && !$@) {
      push @res, $v;
      last ATTEMPT;
    }
    eval {; 1 }; # clear the last error
  }

  @res = tidy_arrayify(@res);

  # say STDERR "  Got (raw) : " . np @res if $debug;

  {
    no warnings qw(uninitialized);
    my  @greps   = tidy_arrayify( $opt{grep}, $opt{greps});
    push @greps, sub {; my @v=($_); !intersect(@blankers, @v) } if (@blankers);

    foreach my $f ( @greps ) {
        my  $rt = reftype($f) // '';
        @res =  grep {
                  my $gr = $_;
                  $rt eq 'CODE'   and   $gr  = $f->($_);
                  $rt eq 'REGEXP' and   $gr  = m/$f/;
                  !$rt            and   $gr  = looks_like_number($f) ? ($_ == $f) : ($_ eq "$f");
                  $gr
                }@res;
    }
    @res  = uniq(@res) unless $opt{no_uniq} && !$opt{uniq};
    @res  = sort @res  if $opt{sort};
  }

  # say STDERR "  Keys : " . np @keys if grep { m/install/ } @keys;
  # say STDERR "  Got  : " . np @res  if $debug;

  return [ @res ] if $opt{want_reftype}  eq 'ARRAY' ;
  return          unless @res;   # Got no results at all. Signal that.
  return $res[0]  if @res == 1;  # If we've got only one value, then there is no ambiguity. Just return that.

  if ( $opt{want_reftype}  eq 'HASH' ) {
      my %res = map {; ref ($_) =~ /HASH/ix ? ( %{$_} ) : ()  } reverse @res;      # effectively shallow-merge the resulting hashes
      return +{ %res };
  }

  # At this stage, even if we have more than one value, we only return the first found.
  # CONSIDER: raising an error, perhaps.
  return $res[0];
}

#
# #######################################
# around _fallback =>  sub { # DEBUG wrapper.
# #######################################
#   my  $orig         = shift;
#   my ($o, %opt)     = &_normalize_fallback_opts;
#   my  @keys         = tidy_arrayify( $opt{keys} );
#   my  $debug         = $opt{debug};
#   my  %info         = (keys => [@keys] );
#
#   if (wantarray) {
#     say STDERR "\n\nFallback in ARRAY context for keys [@keys] ... " if $debug;
#     my @r = $o->$orig($o, \%opt, @_);
#     $info{result} = [@r];
#     say STDERR "Fallback in ARRAY context. info : " . np %info if $debug;
#     return @r;
#   } else {
#     say STDERR "\n\nFallback in SCALAR context for keys [@keys] ... " if $debug;
#     my $r = scalar($o->$orig($o, \%opt, @_));
#     $info{result} = $r;
#     say STDERR "   Fallback result in SCALAR context. info : " . np %info if $debug;
#     return $r;
#   }
#
# };
#

#######################################
sub _smart_lookup  {
#######################################
# Returns the first found item (corresponding to any of the given keys) in any of the hash sources.
  local $_;
  my ($o, %opt)     = &_normalize_fallback_opts;
  my  @keys         = tidy_arrayify( $opt{keys} )
                      or   die "No keys given for us to lookup during staged fallback!";
  my  @res;



( run in 2.189 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )