Bod has asked for the wisdom of the Perl Monks concerning the following question:

This may be better in Meditations - if you have the power to move it and think it should be moved...go ahead!

I've lost count of how many times I've created a module and got this error...

Radar/API.pm did not return a true value at index.pl line 14.
I know exactly how to solve it - simply ensure that there is a true value, usually 1 as the last line of code in the module.

I suspect that almost everyone who has written more than a couple of modules has forgotten this line and got this error.

So why is it part of Perl?

I've been doing some digging and found that it's not just me that finds it frustrating but I have not found an explanation as to why Perl was created like this. Surely there must be a reason for it...

So it got me thinking...
Is there ever a time when one might read the true value and see what it is - i.e 1, 6 or 10?
Is there ever a time when one might want it to return false? I can't imagine this as it's a vague and drastic error. If for some reason, the module cannot be used on the architecture or in the environment then surely a nicer error would be more appropriate.

Replies are listed 'Best First'.
Re: Modules return value
by kcott (Archbishop) on Jan 14, 2023 at 02:39 UTC

      No, I can't think of any reason why you'd want to return a false value.

      I can. Say you write a Parser to handle XML files. You might check during a BEGIN() if there is any functioning backend you can use. Yes, your module probably did some kind of test during install time, but that doesn't mean that those external libraries are still available and still functioning.

      Now, why would you not want to just crash-and-burn or die()? Maybe your library is used from another module that's also dynamically searching for usable XML backends. There are many ways to load a ".pm" file (require, eval, probably Inline::Perl, ...), not just "use", and the easiest way to check if the operation worked is if you get a true value back. TIMTOWTDI, and yes that probably includes all the stuff that source code filters could do for (or "to") you ;-)

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

        G'day cavac,

        While I don't necessarily disagree with anything you wrote there, I'm wondering if we're talking at cross-purposes.

        In the past, I've certainly written modules which, as part of loading, attempt to include some other module whose name is determined dynamically (perhaps based on environment, config, or similar). I would expect failure to be handled a little more elegantly:

        Some/Module.pm failed to load because ...

        Rather than what you refer to as "crash-and-burn":

        Some/Module.pm did not return a true value ...

        Could you provide some skeleton code that clarifies the scenario you're describing? Thankyou.

        — Ken

      Thanks Ken

      I did read that it was an RFC but hadn't picked up that it was going into v5.37.6. Let's hope it lives to go into v5.38...

Re: Modules return value
by haukex (Archbishop) on Jan 14, 2023 at 12:26 UTC
    I have not found an explanation as to why Perl was created like this. Surely there must be a reason for it...

    I think this is due to the relationship between use being like a require in a BEGIN, which in turn is like a do FILE, which in turn is like an eval. eval returns undef when its code fails, and do also has slightly more complex error cases:

    unless ($return = do $file) { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; }

    As a side note: Acme::ReturnValue

Re: Modules return value
by choroba (Cardinal) on Jan 14, 2023 at 12:04 UTC
    I don't have to remember to put 1; at the end of every new module I write, as my editor is configured to do it for me:
    (defun perl-boilerplate () "Basic perl template." (interactive) (if (or (not (file-exists-p (buffer-file-name (current-buffer)))) (= 0 (buffer-size))) (let ((strictures "use warnings;\nuse strict;\n\n#use Data::Dump +er;\n\n")) (cond ((string-match "\\([^/]*\\)\.pm$" buffer-file-name) (let* ((case-fold-search nil) (package-name (replace-regexp-in-string "/" "::" (replace-regexp-in-string "^.*/[^[:upper:]][^/]*/\\|\\.pm$" "" buffer-file-name)))) (insert (concat "package " package-name ";\n" "\n=head1 " package-name "\n\n=cut\n\n" strictures "\n__PACKAGE__\n")) (backward-char 14))) ((string-match "\\(?:\.\\(?:p\\(?:er\\)?l\\|t\\)$\\)\\|^[^. +]+$" buffer-file-name) (insert (concat "#!/usr/bin/perl\n" strictures))))))) (add-hook 'cperl-mode-hook 'perl-boilerplate)

    Opening a new .pm file creates this:

    package My; =head1 My =cut use warnings; use strict; #use Data::Dumper; __PACKAGE__

    while opening a new .pl script creates this:

    #!/usr/bin/perl use warnings; use strict; #use Data::Dumper;

    YMMV.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Modules return value
by SankoR (Prior) on Jan 14, 2023 at 01:19 UTC
Re: Modules return value
by karlgoethebier (Abbot) on Jan 15, 2023 at 12:10 UTC

    That's kind of funny - or weird, depending on your point of view. From do:

    «If do can read the file but cannot compile it, it returns undef and sets an error message in $@. If do cannot read the file, it returns undef and sets $! to the error. Always check $@ first, as compilation could fail in a way that also sets $!. If the file is successfully compiled, do returns the value of the last expression evaluated.

    Inclusion of library modules is better done with the use and require operators, which also do automatic error checking and raise an exception if there's a problem.»

    From require:

    «The file must return true as the last statement to indicate successful execution of any initialization code, so it's customary to end such a file with 1; unless you're sure it'll return true otherwise. But it's better just to put the 1;, in case you add more statements.»

    And the inevitable sources:

    sub require { my ($filename) = @_; if ( my $version = eval { version->parse($filename) } ) { if ( $version > $^V ) { my $vn = $version->normal; croak "Perl $vn required--this is only $^V, stopped"; } return 1; } if (exists $INC{$filename}) { return 1 if $INC{$filename}; croak "Compilation failed in require"; } foreach $prefix (@INC) { if (ref($prefix)) { #... do other stuff - see text below .... } # (see text below about possible appending of .pmc # suffix to $filename) my $realfilename = "$prefix/$filename"; next if ! -e $realfilename || -d _ || -b _; $INC{$filename} = $realfilename; my $result = do($realfilename); # but run in caller's namespace if (!defined $result) { $INC{$filename} = undef; croak $@ ? "$@Compilation failed in require" : "Can't locate $filename: $!\n"; } if (!$result) { delete $INC{$filename}; croak "$filename did not return true value"; } $! = 0; return $result; } croak "Can't locate $filename in \@INC ..."; }

    And I had to remind myself that do 'file.pl'; is almost the same as the notorious eval `cat file.pl`;

    I'm not really sure if things are any clearer now. Maybe we also consider this modest contribution as a meditation.

    Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

Re: Modules return value
by Anonymous Monk on Jan 14, 2023 at 01:48 UTC
    From perldoc -f require:
    The file must return true as the last statement to indicate
    successful execution of any initialization code, so it's customary
    to end such a file with "1;" unless you're sure it'll return true
    otherwise. But it's better just to put the "1;", in case you add
    more statements.
    
Re: Modules return value
by Anonymous Monk on Jan 14, 2023 at 20:23 UTC

    I actually did write a module once (twice, max) that returned metadata about itself when it was loaded. I never made a practice of it, and the module was never published, but yes, there is a potential use for the value.

    Of course, a more "normal" implementation would be to implement static method metadata(), or some such.

Re: Modules return value
by LanX (Saint) on Jan 17, 2023 at 18:09 UTC
    > Is there ever a time when one might want it to return false?

    let's suppose the module compiles fine but won't work because of other unmet requirements...

    ... like the right operation system: E.g it's meant to run on Win only, but was installed on Linux.

    Keep in mind that bare code in modules can be executed at compile-time when used, it's essentially an eval in a BEGIN after all.

    Other examples are INC-hooks which are pseudo modules used for more esoteric things which might fail. (I need to check if the rest of @INC is searched in case of false then...)

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

Re: Modules return value (So why is it part of Perl? To confuse
by Anonymous Monk on Jan 17, 2023 at 15:15 UTC