++ed by:
2 non-PAUSE users
Author image Alexbyk
and 1 contributors




version 0.0405



Return an array contains only uniq elements


Return an array contains only uniq elements

strict_opts($level, $hash, @keys)

  sub foo3(%opts) { strict_opts(\%opts, qw(foo bar)); }
  sub foo2(%opts) { strict_opts(\%opts, [qw(foo bar)], 1); }

Get a $hash and return values in order defined by @keys. If there are superfluous keys in hash, throw an error. This will help you to protect your functions from bugs "passing wrong keys"

$level (the last argument if the second is array ref) determines how many frames to skip. By default it's 1


The behaviour is just like JS's try catch finally with one exception: return statement in finally block doesn't matter, because in perl every subroutine returns something (and because it's more "as expected") and it't impossible to distinguish return/no return

  use Evo '-Lib try';

  # try + catch
  try { die "MyError" } sub($e) { say "Catched: $e" };

  # try + catch + finally
  try sub { die "MyError" }, sub($e) { say "Catched: $e" }, sub { say "Finally" };

Firstly "try_fn" will be executed. If it throws an error, "catch_fn" will be executed with that exception as an argument and perl won't die. "finally_fn", if exists, will be always executed but the return value of finally_fn will be ignored.


  # fin; result: ok
  my $res = try sub { return "ok" }, sub {...}, sub { print "fin; " };
  say "result: ", $res;

  # fin; result: catched
  $res = try sub { die "Error\n" }, sub { return "catched" }, sub { print "fin; " };
  say "result: ", $res;

"Catch" block can be skipped if we're interesting only in "finally"

  # print fin than dies with "Error" in $@
  $res = try sub { die "Error\n" }, undef, sub { print "fin\n" };

If "finally" fn throws an exception, it will be rethrown as expected

  # die in finally block with "FinError\n" in $@
  $res = try sub { 1 }, sub {...}, sub { die "FinError\n" };

Deals correctly with wantarray

  # 1;2;3
  local $, = ';';
  say try sub { wantarray ? (1, 2, 3) : 'One-Two-Three' }, sub {...};

  # One-Two-Three
  say scalar try sub { wantarray ? (1, 2, 3) : 'One-Two-Three' }, sub {...};

Also you should pay attention that it doesn't localize $@. That's intentionally


There is a similar and popular Try::Tiny, but it has a flaw: it can't catch errors in finally block. Which isn't unacceptable for module written for exception handling

  use Evo 'Try::Tiny; -Lib try:evo_try; Test::More';

  # try tiny can't catches errors here because of flaw in module design
  eval {
    try {} catch { } finally { die "foo\n" };
  is $@, "foo\n", "Try::Tiny";

  # Evo's try catches an error correctly
  eval {
    evo_try sub { }, sub { }, sub { die "foo\n" };
  is $@, "foo\n", "Evo";

Also this module is much faster (both PP and XS) and more tiny(~30 lines of code in PP). The only disadvantage is (is it?) it doesn't simulate "catch, finally" keyword. But for me it's not a problem


Invokes a last argument with the context of the first void: undef, scalar: '', list: 1, passing remaining arguments. If the function throws an error, returns nothing and sets <$@>. So returned value can answer the question was an invocation successfull or not

Mostly for internal purposes to deal correctly with wantarray and for creating a spy. Short: it allows to intercept execution flow without loosing a context

  use Evo '-Lib eval_want';

  sub add2($val) { $val + 2 }

  sub create_spy($fn) {
    sub {
      warn "[spy] context: ", wantarray,  "; args: ", join ';', @_;
      my $call = eval_want(wantarray, @_, $fn) or die $@;

  my $spy = create_spy(\&add2);
  say $spy->(10);

As you can se, we just pass given context wantarray to the eval_want




This software is copyright (c) 2016 by alexbyk.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.