Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an unknown method in Perl

Tags:

prototype

perl

I have trouble understanding, why Perl executes the code in curly braces in programs like this one:

unknown_method {
    # some code
};

My program:

file Transaction.pm:

package Transaction;
use strict;
use warnings;
use feature qw/ say /;

sub transaction(&) {
    say 'BEGIN TRANSACTION';
    eval {
        shift->()
    };
    if ( $@ ) {
        say 'ROLLBACK TRANSACTION';
        die($@);  # reraise error
    } else {
        say 'COMMIT TRANSACTION';
    }
}
1;

file run_properly.pl:

use feature qw/ say /;
use Transaction;
eval {
    Transaction::transaction {
        say "insert some data to DB";
        die("KnownException")
    }
};
warn $@;

file run_wrong.pl:

use feature qw/ say /;
# I forgot to import Transaction
eval {
    Transaction::transaction {
        say "insert some data to DB";
        die("KnownException")
    }
};
warn $@;

Execution:

$ perl run_properly.pl 
BEGIN TRANSACTION
insert some data to DB
ROLLBACK TRANSACTION
KnownException at run_properly.pl line 6.

and

$ perl run_wrong.pl 
insert some data to DB
KnownException at run_wrong.pl line 6.

Why Perl allows such a thing?

like image 404
Stach Jankowski Avatar asked Jun 08 '13 20:06

Stach Jankowski


People also ask

What is $@ in Perl?

$@ The Perl syntax error or routine error message from the last eval, do-FILE, or require command. If set, either the compilation failed, or the die function was executed within the code of the eval.

How do I catch an exception in Perl?

Catch the exception using evalIf we wrap a piece of code in an eval block, the eval will capture any exception that might happen within that block, and it will assign the error message to the $@ variable of Perl. The simple way to do this looks like this: (please note, there is a ; after the eval block.)

Does Perl have try catch?

The try and catch block of code is used for error handling in Perl, similar to other languages such as Java and Python. The try and catch block tries the code meant to be executed in the try block, and if an error occurs, the program does not crash. Instead, the error is caught and printed by the catch block.

What does use strict do in Perl?

use strict; The use strict pragma forces the developer to code in a manner that enables the code to execute correctly, and it makes the program less error-prone. As an example, the use strict pragma forces the developer to declare variables before using them. We can declare variables with the keyword my in Perl.


1 Answers

Perl is syntactically flexible, and often has more than one syntax do do things. For example, calling methods. This is regular and recommended syntax:

  Foo  ->  new       (1, 2, 3);
# ^-object ^- method ^- arguments

This is the indirect syntax:

  new       Foo       1, 2, 3;
# ^- method ^- object ^- arguments, parens are optional

This is all fine and well, but what happens when we want to use the result of a complex computation as object with indirect object notation?

# set up some constructors for demonstration purposes
*Foo::new = *Bar::new = sub {say "@_"};

# This obviously fails
# new (rand > .5 ? "Foo" : "Bar") 1, 2, 3;

The solution is a dative block:

new {rand > .5 ? "Foo" : "Bar"} 1, 2, 3;

You probably already know dative blocks from filehandles: print {$handles[-1]} $_.

The dative block is executed before method resolution, as method resolution generally (but not in your case) depends on the type of the object. However, no methods are resolved if the block dies.


Indirect notation is still quite popular for constructors, as it makes Perl look like C++. However, Perl (unlike C++) has no new operator: it's just a regular method. This flexibility may have been a bad idea, so you can “fix” it by using no indirect if you feel strongly about this.

like image 52
amon Avatar answered Sep 28 '22 02:09

amon