use warnings; use strict; sub myfunc(@) { my $default_subfunc = sub { local $"=','; return "my default code block: (@_)\n"; }; my $subfunc = ( 'CODE' eq ref $_[0] ) ? shift : $default_subfunc; return $subfunc->(@_); } #3: no CODEREF print myfunc 1, 2, 3; #2a: two-line version, with comma: my $alternate = sub { "alt: sizeof LIST = " . scalar(@_) . "\n" }; print myfunc $alternate, 1..10; #2b: one-line version, with comma: print myfunc sub { local $"=';'; return "oneliner: @_\n" }, qw/hello world/; #2fail: one-line version, no comma, no sub: eval qq| # this eval-wrapper prevents the compiler from crashing, so the previous examples will still run print myfunc { local $"=';'; return "oneliner: @_\n" } qw/hello world/; |; if($@) { my $x = $@; $x =~ s/^/\t/gm; print "ERROR:{\n$x\n}\n"; } # I assume you already knew the & prototype, to mimic _just_ #2's syntax sub otherfunc(&@) { my $subfunc = shift; return $subfunc->(@_); } print otherfunc { "otherfunc always needs a coderef: @_\n" } 5..7; print otherfunc sub { $alternate->(@_) }, 2,3,5,7,11; print "END\n";