Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to die on undefined values?

Tags:

raku

I am attempting to work with a hash in Raku, but when I put some fake values into it (intentionally) like

say %key<fake_key>;

I get

(Any)

but I want the program to die in such occurrences, as Perl does, because this implies that important data is missing.

For example,

#!/usr/bin/env perl

use strict;
use warnings 'FATAL' => 'all';
use autodie ':all';

my %hash;
print "$hash{y}\n";

as of 5.26.1 produces

Use of uninitialized value $hash{"y"} in concatenation (.) or string at undefined.pl line 8.
Command exited with non-zero status 255

How can I get the equivalent of use warnings 'FATAL' => 'all' and use autodie qw(:all) in Raku?

like image 615
con Avatar asked Jan 22 '19 16:01

con


2 Answers

Aiui your question is:

I'm looking for use autodie qw(:all) & use warnings 'FATAL' => 'all' in Raku

The equivalent of Perl's autodie in Raku

Aiui the equivalent of use autodie qw(:all) in Perl is use fatal; in Raku. This is a lexically scoped effect (at least it is in Raku).

The autodie section in the Perl-to-Raku nutshell guide explains that routines now return Failures to indicate errors.

The fatal pragma makes returning a Failure from a routine automatically throw an exception that contains the Failure. Unless you provide code that catches them, these exceptions that wrap Failures automatically die.

The equivalent of Perl's use warnings 'FATAL' in Raku

Aiui the equivalent of use warnings 'FATAL' => 'all' in Perl is CONTROL { when CX::Warn { note $_; exit 1 } } in Raku. This is a lexically scoped effect (at least it is in Raku).

CONTROL exceptions explains how these work.

CONTROL exceptions are a subset of all exceptions that are .resume'd by default -- the program stays alive by default when they're thrown.

The Raku code I've provided (which is lifted from How could I make all warnings fatal? which you linked to) instead makes CONTROL exceptions die (due to the exit routine).

Returning to your current question text:

say %key<fake_key>; # (Any)

I want the program to die in such occurrences ...

Use either Jonathan++'s answer (use put, which, unlike say, isn't trying to keep your program alive) or Scimon++'s KeyRequired answer which will make accessing of a non-existent key fatal.

... as Perl does ...

Only if you use use warnings 'FATAL' ..., just as Raku does if you use the equivalent.

... because this implies that important data is missing.

Often it implies unimportant data is missing, or even important data that you don't want defined some of the time you attempt to access it, so both Perls and Raku default to keeping your program alive and require that you tell it what you want if you want something different.

You can use the above constructs to get the precise result you want and they'll be limited to a given variable (if you use the KeyRequired role) or statement (using put instead of say) or lexical scope (using a pragma or the CONTROL block).

like image 77
raiph Avatar answered Sep 19 '22 13:09

raiph


You can create a role to do this. A simple version would be :

role KeyRequired { 
    method AT-KEY( \key ) { 
        die "Key {key} not found" unless self.EXISTS-KEY(key); 
        nextsame; 
    } 
};

Then you create your hash with : my %key does KeyRequired; and it will die if you request a non existent key.

like image 38
Scimon Proctor Avatar answered Sep 20 '22 13:09

Scimon Proctor