Control flow

evalbytes#

Compile and run a string of Perl source, forcing the source to be interpreted as bytes rather than characters.

evalbytes is the byte-oriented twin of string eval. It takes an EXPR (or $_ when EXPR is omitted), treats the string as a raw byte stream, and parses it as Perl source. The parse is insulated from the caller’s use utf8 pragma: whatever encoding rules the string itself declares win. Reach for it when the code you are about to compile was read from disk, the wire, or a build step, and you need the parser to see exactly the bytes you handed it.

Synopsis#

evalbytes EXPR
evalbytes
CORE::evalbytes EXPR    # when the feature is not enabled

What you get back#

In scalar context, the value of the last expression evaluated; in list context, a list. On a compile or run-time error, undef (or an empty list) and $@ is set to the error message; $@ is the empty string on success. Return shape matches string eval exactly — the only difference is how the source text itself is decoded.

my $result = evalbytes $source;
die $@ if $@;

How it differs from string eval#

Two concrete behaviours distinguish evalbytes from eval EXPR:

  • The source is parsed as bytes. Every octet in the string is a separate input character to the lexer, regardless of whether the string is internally marked as utf8. A multi-byte UTF-8 sequence in the source shows up to the parser as the individual bytes, not as the decoded code point.

  • Code points above 255 are a hard error. If the string contains any character whose ordinal exceeds 0xFF, it cannot be a byte stream and the compile fails with Wide character in eval stored in $@. Downgrade with utf8::encode first if the source currently holds decoded text.

use utf8 and no utf8 inside the evaluated code have their usual effect: the pragma switches on once the parser reaches it and affects the remainder of that compilation. It is the source’s outer framing that is fixed to bytes, not what the source itself declares.

Enabling the name without CORE::#

evalbytes is feature-gated. To call it as a bareword:

use feature 'evalbytes';

A use v5.16 (or higher) declaration enables the evalbytes feature automatically, along with the rest of the :5.16 feature bundle. Without either, the unqualified name is not recognised and you must write CORE::evalbytes explicitly — useful inside generated code or one-liners that do not carry a version declaration.

use v5.16;
my $n = evalbytes '1 + 2';        # 3
# no feature, no version bundle:
my $n = CORE::evalbytes '1 + 2';  # 3

Global state it touches#

  • $@ — cleared before the compile, then set to the error message on failure or the empty string on success. Same contract as eval.

  • $_ — read as the source text when EXPR is omitted.

Source filters activated inside the evaluated code apply to the code itself, exactly as they would inside a string eval. The filter sees the same bytes the parser sees.

Examples#

Evaluate a literal byte string — no surprises, no encoding choices to make:

use feature 'evalbytes';
my $n = evalbytes 'my $x = 40; $x + 2';   # 42

Evaluate source read from a file that is known to be UTF-8 encoded but whose declared pragma inside the source is what should govern parsing:

use feature 'evalbytes';
open my $fh, '<:raw', 'script.pl' or die $!;
my $src = do { local $/; <$fh> };
my @values = evalbytes $src;
die "compile failed: $@" if $@;

Reading with :raw keeps $src a byte string. evalbytes then feeds those bytes to the parser verbatim; a use utf8; line at the top of the script will do its own work once the parser reaches it.

Compare with string eval when the caller has use utf8:

use utf8;
use feature 'evalbytes';

my $src = "length('caf\xc3\xa9')";   # bytes for 'café' in UTF-8

print eval $src;         # 3  (characters: c, a, f, é)
print "\n";
print evalbytes $src;    # 5  (bytes:     c, a, f, 0xC3, 0xA9)
print "\n";

Under use utf8 the caller’s own literal "length('caf\xc3\xa9')" is a character string to eval, so length inside the evaluated code sees one é character. evalbytes forces the same source to be parsed as the byte sequence c a f 0xC3 0xA9, so length reports the byte count.

Catching a wide-character error:

use feature 'evalbytes';
my $src = "print \x{2603}";          # contains U+2603 SNOWMAN
evalbytes $src;
warn "rejected: $@" if $@;           # "Wide character in eval ..."

Omitting EXPR — source comes from $_:

use feature 'evalbytes';
for ('1+1', '2*3', '10-7') {
    my $r = evalbytes;
    print "$_ = $r\n";
}

Edge cases#

  • Wide character in source: any code point above 0xFF aborts the compile and leaves Wide character in eval in $@. Run utf8::encode on the source (or read the file in :raw) before calling.

  • use utf8 is local to the evaluated code. It affects string literals and identifiers inside the evaluated text once the parser reaches the pragma line. It does not change how evalbytes frames the outer source — that framing is always “bytes”.

  • Feature not enabled: without use feature 'evalbytes' and without a use v5.16+ bundle, the bareword is unrecognised. Write CORE::evalbytes to bypass the feature gate.

  • evalbytes with no argument and $_ undef: compiles an empty string, which succeeds and returns undef in scalar context, the empty list in list context, with $@ empty.

  • Source filters inside the evaluated code see the byte stream. A filter that expects decoded characters will misbehave; write filters for evalbytes in terms of bytes.

  • Lexicals and package state: same rules as string eval. The evaluated code shares the caller’s current package and sees the caller’s in-scope lexicals; its own my variables vanish when the eval finishes.

  • die inside evalbytes: caught the same way as for eval. The thrown value lands in $@; execution continues after the evalbytes call.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • eval — the character-mode counterpart; parses EXPR according to the caller’s Unicode framing, so use utf8 in the caller changes how the source is interpreted

  • die — throw an exception from within evaluated code; sets $@ just like any other run-time error

  • do — compile and run a file; takes its source from disk rather than a string, and is not affected by the caller’s utf8 framing

  • require — load and compile a file once; the standard tool when the source lives on disk and should only run on first reference

  • utf8 — the pragma controlling character vs byte semantics of string literals; evalbytes exists precisely to pin the outer framing to bytes regardless of this pragma

  • $@ — the error slot populated on evalbytes failure, cleared on success