I/O

say#

Print a list of values followed by a newline.

say is print with the output record separator forced to "\n" for that one call. It stringifies each item in LIST, joins them with $, (output field separator, usually empty), writes them to FILEHANDLE, and appends a literal "\n"not the value of $\. If FILEHANDLE is omitted, output goes to the currently selected handle (see select), which defaults to STDOUT. If LIST is omitted, $_ is printed.

say is a feature-gated built-in. It is available only when the "say" feature is enabled — automatic under use v5.10 or higher, or explicit with use feature 'say' — or when called as CORE::say.

Synopsis#

say LIST
say FILEHANDLE LIST
say {EXPR} LIST
say

What you get back#

1 on success, undef on failure (with $! set). As with print, the return value is rarely checked for STDOUT or STDERR. Check it when writing to a file, pipe, or socket where a write failure is a recoverable condition:

say $fh $record
    or die "write to $path failed: $!";

Default filehandle, default separators#

say reads the same global state as print, with one deliberate exception:

  • The currently selected filehandle, changed with select. say LIST writes there when no filehandle is given. Defaults to STDOUT.

  • $,output field separator, inserted between list items. Defaults to the empty string, so say 1, 2, 3 produces "123\n", not "1 2 3\n".

  • $\output record separator. say ignores $\ entirely and appends a literal "\n" instead. Setting $\ has no effect on say.

That last point is the whole reason say exists: one record, one newline, no fiddling with $\.

Examples#

Basic write to STDOUT:

use feature 'say';
say "hello, world";                 # "hello, world\n"

Write to a filehandle. Same indirect-object form as printno comma between the filehandle and the list:

open my $fh, ">", "out.txt" or die $!;
say $fh "line 1";
say $fh "line 2";
close $fh;

Write to a filehandle held in an expression. Any filehandle more complex than a bareword or a plain scalar needs the {EXPR} block form:

my @logs = (\*STDOUT, \*STDERR);
say { $logs[$level] } "message";

say joins list items with $, and then appends "\n" regardless of $\:

local $, = ", ";
local $\ = ".\n";                   # ignored by say
say "apples", "pears", "plums";     # "apples, pears, plums\n"

No arguments — print $_ plus a newline. The filehandle must be a bareword in this form; say $fh; would parse $fh as the content, not as the target:

for (qw(alpha beta gamma)) {
    say;                            # "alpha\n", "beta\n", "gamma\n"
}

List context applies to every argument:

my @arr = (10, 20, 30);
say @arr;                           # "102030\n"
say scalar @arr;                    # "3\n"

Edge cases#

  • Feature gate: without use feature 'say' or use v5.10, say is parsed as an ordinary subroutine call and will fail at compile time if no such sub is in scope. Use CORE::say(...) to call it unconditionally.

  • No arguments with an explicit filehandle: say FH; prints $_ to FH, but only for bareword filehandles. say $fh; parses $fh as the content, not the target — write say $fh $_; if you mean that. This matches print.

  • $\ is ignored, not overridden: say does not set or localise $\. Other code that reads $\ (including nested print calls) sees whatever value was already there.

  • Filehandle-or-first-arg ambiguity: same rule as print. A bareword or a simple scalar immediately followed by a term (no comma) is taken as the filehandle. An expression returning a filehandle needs the block form: say { $handles[0] } "x";.

  • say (…) parses as a function call. say (2+3)*4 prints 5 then discards *4. Parenthesise the whole argument list, or prefix with +:

    say((2+3)*4);                     # "20\n"
    say +(2+3)*4;                     # "20\n"
    
  • Closed filehandle: returns undef and sets $! to "Bad file descriptor". Under use warnings a say() on closed filehandle warning is emitted.

  • Encoding layers: say writes through the handle’s PerlIO stack exactly like print. A handle with a :utf8 or :encoding(...) layer encodes on the way out; the appended newline is a single "\n" byte and is encoded by the same layer. A wide-character string written to a bytes-mode handle triggers a Wide character in say warning.

  • Autoflush: say buffers through PerlIO like print. Set $| on the selected handle for line-buffered output.

  • SIGPIPE: writing to a closed pipe or socket raises SIGPIPE. The default action terminates the process; install a handler to convert it into a normal write failure.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • print — same targeting and separator rules, but appends $\ (empty by default) instead of a forced newline

  • printf — formatted output; does not append a newline, you put one in the format string

  • select — change which filehandle the no-argument form of say writes to

  • $, — output field separator inserted between list items; say honours it

  • $\ — output record separator; say ignores it and appends "\n" instead

  • $| — autoflush flag for the currently selected handle