--- name: do signature: |- do BLOCK do EXPR status: documented categories: ["Control flow", "Modules"] --- ```{index} single: do; Perl built-in ``` *[Control flow](../perlfunc-by-category) · [Modules](../perlfunc-by-category)* # do Execute a block of code or run a Perl source file as if it were part of the current program. `do` wears two unrelated hats that share only a keyword. `do BLOCK` groups statements into a single expression and returns the value of the last one — a syntactic tool, not a function. `do EXPR` treats the string as a filename and compiles-and-runs the file at runtime. Read whichever section matches the form you see; mixing them up is the most common source of confusion around this keyword. ## Synopsis ```perl do BLOCK # group statements, yield last value do EXPR # load and run a Perl file do { ... } while CONDITION; # post-test loop idiom ``` ## What you get back - `do BLOCK` — the value of the last expression evaluated in the block, in whatever context the surrounding expression imposes. - `do EXPR` — the value of the last expression evaluated in the file on success; [`undef`](undef) on failure, with [`$@`](../perlvar) set to the compile error or [`$!`](../perlvar) set to the I/O error. ## do BLOCK — group statements into one expression `do BLOCK` is not a function. It is a syntactic construct that turns a brace-delimited sequence of statements into a single term whose value is the value of the last statement. Reach for it when the language wants an expression but you have several statements to run: ```perl my $x = do { my $tmp = fetch_raw(); $tmp =~ s/\s+\z//; lc $tmp; }; # $x = cleaned, lower-cased value ``` When `do BLOCK` is modified by a trailing `while` or `until`, the block runs **once before** the condition is tested — this is the standard post-test loop idiom: ```perl do { $line = <$fh>; } while defined $line && $line !~ /^END\b/; ``` On any other statement, `while` and `until` as statement modifiers test the condition first. `do` is the exception. ### [`next`](next), [`last`](last), [`redo`](redo) do not work inside `do BLOCK` A `do BLOCK` is **not** a loop, even when trailed by `while` or `until`. Loop-control keywords do not see it: ```perl do { last if $done; # WRONG — not a loop } while $more; ``` If you need loop control, wrap the body in a bare block, which *is* a loopable scope: ```perl { last if $done; redo if $retry; } ``` Or use an explicit `while` loop. ### [`return`](return) inside a bare `do BLOCK` [`return`](return) in a `do BLOCK` returns from the **enclosing subroutine**, not from the block itself. That is occasionally what you want and occasionally a bug — either way, know which one you are writing: ```perl sub classify { my $n = shift; my $kind = do { return "zero" if $n == 0; # returns from classify(), not the do $n > 0 ? "pos" : "neg"; }; "$kind ($n)"; } ``` To yield a value from the block without returning from the sub, just let the last expression be the value — that is the whole point of `do BLOCK`. ## do EXPR — load and run a Perl source file `do EXPR` evaluates `EXPR`, treats the result as a filename, reads the file, compiles it, and runs it in the current package. It is similar to, but not quite the same as, ```perl eval `cat stat.pl`; ``` The `do` form runs no external process, keeps the original filename for error messages, and **cannot see lexicals in the enclosing scope** — which `eval STRING` can. Like `eval STRING`, the file is reparsed on every call, so `do FILE` inside a loop is almost always wrong. ### Path resolution and `@INC` The filename is interpreted like this: - Absolute paths (`/foo/stat.pl`), paths beginning with `./`, and paths beginning with `../` are used as-is. - Any other relative path is searched along `@INC`, and on success the found path is recorded in `%INC` under the key you passed. ```perl do '/etc/myapp/stat.pl'; # exact file do './stat.pl'; # exact file, current directory do 'stat.pl'; # search @INC do 'MyApp/config.pl'; # search @INC ``` Since Perl 5.26 `.` is not in `@INC` by default, so a bare `do 'stat.pl'` no longer falls back to the current directory. If the file is not found, Perl emits the hint: ```text do "stat.pl" failed, '.' is no longer in @INC; did you mean do "./stat.pl"? ``` Pass `./stat.pl` when you mean the current directory. ### Return value and error reporting `do EXPR` has three outcomes you must distinguish: | Outcome | Return | [`$@`](../perlvar) | [`$!`](../perlvar) | |---|---|---|---| | File compiled and ran | value of last expression | `""` | unchanged | | File read but did not compile | [`undef`](undef) | compile error | may also be set | | File could not be read | [`undef`](undef) | `""` | I/O error | Because compilation failure can incidentally set [`$!`](../perlvar) as well, **always check [`$@`](../perlvar) first**: ```perl my $return; for my $file ("/etc/myapp.rc", "$ENV{HOME}/.myapprc") { 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; } } ``` The three [`warn`](warn)s correspond to the three failure shapes above plus the fourth case — the file ran but its last expression was false. ### Why not use `do FILE` for modules For loading library code, use [`require`](require) or [`use`](use) instead of `do EXPR`. [`require`](require) caches through `%INC` (so a file is loaded at most once), raises an exception on failure instead of returning [`undef`](undef), and integrates with `@INC` hooks. [`use`](use) adds compile-time loading and import handling on top. `do EXPR` exists for configuration files and ad-hoc script inclusion — not for libraries. ## Examples Group statements into an expression: ```perl my $config = do { open my $fh, "<", $path or die $!; local $/; <$fh>; }; # $config = whole file as one string ``` Post-test loop with `do … while`: ```perl my $n; do { print "enter a positive number: "; chomp($n = ); } until defined $n && $n =~ /\A\d+\z/ && $n > 0; ``` Read a Perl-syntax configuration file, with full three-way error handling: ```perl my $cfg = do '/etc/myapp/config.pl'; if (!defined $cfg) { die $@ ? "config parse error: $@" : "config read error: $!"; } die "config did not return a true value" unless $cfg; ``` Conditional value selection where each branch is several statements: ```perl my $greeting = do { if ($user) { my $name = $user->display_name; "hello, $name"; } else { "hello, stranger"; } }; ``` Temporary localisation that must span several statements and still yield a value: ```perl my $dump = do { local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Indent = 1; Data::Dumper::Dumper(\%state); }; ``` ## Global state it touches - `@INC` — searched when `do EXPR` is called with a relative path other than `./…` or `../…`. - `%INC` — updated with the resolved path when `do EXPR` succeeds on an `@INC` search. - [`$@`](../perlvar) — set by `do EXPR` on compile failure; cleared on success. - [`$!`](../perlvar) — set by `do EXPR` on I/O failure (file could not be read). - [`$0`](../perlvar), `__FILE__`, `__LINE__` — the currently compiling filename is set to the file being loaded while `do EXPR` parses it, so warnings and [`die`](die) messages point at the right file. `do BLOCK` touches no globals; it is a pure syntactic construct. ## Edge cases - **`do BLOCK` is not a loop.** [`next`](next), [`last`](last), and [`redo`](redo) inside a `do … while` do not apply to the block. Use a bare block or a real `while` loop. - **[`return`](return) in `do BLOCK` returns from the enclosing sub.** Not from the block. There is no way to return a value from a `do BLOCK` other than making it the last expression evaluated. - **Statement modifiers are pre-test everywhere else.** `STATEMENT while COND` tests first; `do BLOCK while COND` tests after the first run. This is a deliberate language exception. - **Relative paths without `./` search `@INC`.** Since 5.26, `.` is not in `@INC`, so `do 'stat.pl'` does not mean "current directory file" any more; pass `./stat.pl` if that was the intent. - **`do EXPR` cannot see enclosing lexicals.** The file is parsed as if at the top level. If you need access to lexicals, use `eval STRING` — with the usual taint and injection caveats. - **The file is re-parsed every call.** `do EXPR` is not cached via `%INC` the way [`require`](require) is. Calling it in a loop re-reads and re-compiles the file each iteration. - **Check [`$@`](../perlvar) before [`$!`](../perlvar).** A compilation failure can also set [`$!`](../perlvar) as a side effect; the compile error in [`$@`](../perlvar) is the one you actually want to report. - **A file that compiles but returns a false value is ambiguous.** `unless ($ret = do $file) { … }` fires for both "file failed" and "file ran and returned `0`". If your config file is allowed to end in a false value, use [`defined`](defined) and [`$@`](../perlvar) explicitly instead of truth-testing the return. - **`do` with no argument is a syntax error.** Both forms require a term: a block or an expression. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`eval`](eval) — `eval BLOCK` traps exceptions without reading a file; `eval STRING` parses arbitrary code and **can** see enclosing lexicals, unlike `do EXPR` - [`require`](require) — load a library file with `%INC` caching and automatic exception on failure; the right tool for modules - [`return`](return) — note that [`return`](return) inside `do BLOCK` returns from the enclosing subroutine, not from the block - [`@INC`](../perlvar) — module search path consulted by `do EXPR` on relative filenames - [`%INC`](../perlvar) — records the resolved path after a successful `@INC`-searched `do EXPR` - [`$@`](../perlvar) — compile-time error from `do EXPR` - [`$!`](../perlvar) — I/O error from `do EXPR` when the file cannot be read