Is there a way to force an empty context in Perl?

This question may seem useless to someone, but please come with me. I am only interested in this out of curiosity geek on the way Perl works and how far you can go with such things.

There are some functions that are written in order to act differently in each of the three contexts.

Using the following code as a very simple example:

use 5.012;

say context();
say scalar context();

sub context {
    if (wantarray) {
        return 'list';
    } elsif (defined wantarray) {
        return 'scalar';
    } else {
        return 'void'; # Destined to be discarded
    }
}

CONCLUSION:

list
scalar

Can you come up with a way to provoke the third sayone that issues voidafter the call context()?

, , , , , / -. , , , Perl, , , .

, : force void- , , ?

+4
3
sub void(&) { $_[0]->(); () }

say        context();
say scalar context();
say void { context() };

:

use syntax qw( void );

say        context();
say scalar context();
say void   context();

, scalar , :

$ diff -u0 \
   <( perl -MO=Concise,-exec -Msyntax=void -E'say        f()' 2>&1 ) \
   <( perl -MO=Concise,-exec -Msyntax=void -E'say scalar f()' 2>&1 )
--- /dev/fd/63  2014-08-17 12:34:29.124827443 -0700
+++ /dev/fd/62  2014-08-17 12:34:29.128827401 -0700
@@ -7 +7 @@
-6  <1> entersub[t6] lKS/TARG    <-- "l" for list context
+6  <1> entersub[t7] sKS/TARG    <-- "s" for scalar context

use syntax qw( void ) void:

$ diff -u0 \
   <( perl -MO=Concise,-exec -Msyntax=void -E'say        f()' 2>&1 ) \
   <( perl -MO=Concise,-exec -Msyntax=void -E'say void   f()' 2>&1 )
--- /dev/fd/63  2014-08-17 12:34:41.952692723 -0700
+++ /dev/fd/62  2014-08-17 12:34:41.952692723 -0700
@@ -7 +7 @@
-6  <1> entersub[t6] lKS/TARG    <-- "l" for list context
+6  <1> entersub[t6] vKS/TARG    <-- "v" for void context

use syntax qw( void );

Syntax::Feature::Void Void.xs, :

STATIC OP* parse_void(pTHX_ GV* namegv, SV* psobj, U32* flagsp) {
    return op_contextualize(parse_termexpr(0), G_VOID);
}

STATIC OP* ck_void(pTHX_ OP* o, GV* namegv, SV* ckobj) {
    return remove_sub_call(o);
}

BOOT: {
    const char voidname[] = "Syntax::Feature::Void::void";
    CV* const voidcv = get_cvn_flags(voidname, sizeof(voidname)-1, GV_ADD);
    cv_set_call_parser(voidcv, parse_void, &PL_sv_undef);
    cv_set_call_checker(voidcv, ck_void, &PL_sv_undef);
}
  • sub void get_cvn. (Sub .) Void.pm sub .

  • Perl, void cv_set_call_parser.

  • Perl, void cv_set_call_checker.

  • Perl void, , parse_termexpr, void op_contextualize.

  • void , () .

+9

, , .

context();
1;

, , return 'void', return (!defined wantarray), .

+2

man perldata:

use warnings pragma Perl -w, "void context". Void , , , , "fred"; getpwuid(0);. - , , .

, void, scalar list. . , , . . wantarray , .

, , , .

!

, void. : "" . man perlop . man perlfunc. , , perldoc -f scalar .

. , , ( 0), , . - , . (, .)

sub test_context() {
    wantarray and die "list\n";
    defined wantarray and die "scalar\n";
    die "void\n";
}
$\ = "\n"; # to make output prettier
### Uncomment the one you want to test.
# -- Somewhat canonical examples of contexts
#[test_context]; # list (+ warning of class 'void')
#print test_context; # list
#scalar(test_context); # scalar (forces scalar context anywhere)
#my $x = test_context; # scalar
#test_context; # void
#
# -- Examples of forcing void context
# Replace test_context with a fixed scalar and try again to see that even if
# the function returned a value, it would get discarded. Ignore the 'void' warning.
#print my $x = (test_context, 42);
#print '^', () x (test_context, 0), '$';

: no void()

void, scalar.

sub void {
    ();
}
print void(test_context);

test , , prototype. .

​​, Perls, , .

, Perl , ikegamis.

?

, , , . -, . perldoc -f wantarray , undefined, void, , . , .

return unless defined wantarray; # don't bother doing more
my @a = complex_calculation();
return wantarray ? @a : "@a";
+1

All Articles