Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PATCH] __SUB__ #10897

Closed
p5pRT opened this issue Dec 12, 2010 · 62 comments
Closed

[PATCH] __SUB__ #10897

p5pRT opened this issue Dec 12, 2010 · 62 comments
Labels

Comments

@p5pRT
Copy link

p5pRT commented Dec 12, 2010

Migrated from rt.perl.org#80628 (status was 'resolved')

Searchable as RT80628$

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @cpansprout

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

I first thought of adding this to make recursive lexicals subs easier to write (whenever they are added)​:

my sub foo { __SUB__->() }

my sub foo; # the alternative
my sub foo { foo() }

The really neat thing, which I realised only after writing it, is that it allows for recursive closures to be written much more simply​:

sub make_recursive_function {
  my $arg = shift;
  sub {
  print "$_[0]\n";
  __SUB__->($_[0] + 1) if $_[0] < $arg;
  }
}

as opposed to​:

use Scalar​::Util;
sub make_recursive_function {
  my $arg = shift;
  my $sub;
  my $life_raft = $sub = sub {
  print "$_[0]\n";
  &$sub($_[0] + 1) if $_[0] < $arg;
  }
  Scalar​::Util​::weaken($sub);
  $sub;
}

[Reminder to myself​: I need to add it to Opcode.pm as well.]


Flags​:
  category=core
  severity=wishlist


Site configuration information for perl 5.13.7​:

Configured by sprout at Thu Dec 9 14​:53​:58 PST 2010.

Summary of my perl5 (revision 5 version 13 subversion 7) configuration​:
  Snapshot of​: 9e9fdd5
  Platform​:
  osname=darwin, osvers=10.4.0, archname=darwin-2level
  uname='darwin pint.local 10.4.0 darwin kernel version 10.4.0​: fri apr 23 18​:28​:53 pdt 2010; root​:xnu-1504.7.4~1release_i386 i386 '
  config_args='-de -Dusedevel -DDEBUGGING'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=undef, use64bitall=undef, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
  optimize='-O3 -g',
  cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib
  libs=-ldbm -ldl -lm -lutil -lc
  perllibs=-ldl -lm -lutil -lc
  libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches​:
 


@​INC for perl 5.13.7​:
  /usr/local/lib/perl5/site_perl/5.13.7/darwin-2level
  /usr/local/lib/perl5/site_perl/5.13.7
  /usr/local/lib/perl5/5.13.7/darwin-2level
  /usr/local/lib/perl5/5.13.7
  /usr/local/lib/perl5/site_perl
  .


Environment for perl 5.13.7​:
  DYLD_LIBRARY_PATH (unset)
  HOME=/Users/sprout
  LANG=en_US.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/bin​:/bin​:/usr/sbin​:/sbin​:/usr/local/bin​:/usr/X11/bin​:/usr/local/bin
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @cpansprout

Inline Patch
diff --git a/embed.h b/embed.h
index 5f846f5..f511965 100644
--- a/embed.h
+++ b/embed.h
@@ -1363,6 +1363,7 @@
 #define pp_rindex()		Perl_pp_rindex(aTHX)
 #define pp_rkeys()		Perl_pp_rkeys(aTHX)
 #define pp_rmdir()		Perl_pp_rmdir(aTHX)
+#define pp_runcv()		Perl_pp_runcv(aTHX)
 #define pp_rv2av()		Perl_pp_rv2av(aTHX)
 #define pp_rv2cv()		Perl_pp_rv2cv(aTHX)
 #define pp_rv2gv()		Perl_pp_rv2gv(aTHX)
diff --git a/keywords.h b/keywords.h
index 526f3e4..1f63f06 100644
--- a/keywords.h
+++ b/keywords.h
@@ -16,254 +16,255 @@
 #define KEY___FILE__		1
 #define KEY___LINE__		2
 #define KEY___PACKAGE__		3
-#define KEY___DATA__		4
-#define KEY___END__		5
-#define KEY_AUTOLOAD		6
-#define KEY_BEGIN		7
-#define KEY_UNITCHECK		8
-#define KEY_CORE		9
-#define KEY_DESTROY		10
-#define KEY_END			11
-#define KEY_INIT		12
-#define KEY_CHECK		13
-#define KEY_abs			14
-#define KEY_accept		15
-#define KEY_alarm		16
-#define KEY_and			17
-#define KEY_atan2		18
-#define KEY_bind		19
-#define KEY_binmode		20
-#define KEY_bless		21
-#define KEY_break		22
-#define KEY_caller		23
-#define KEY_chdir		24
-#define KEY_chmod		25
-#define KEY_chomp		26
-#define KEY_chop		27
-#define KEY_chown		28
-#define KEY_chr			29
-#define KEY_chroot		30
-#define KEY_close		31
-#define KEY_closedir		32
-#define KEY_cmp			33
-#define KEY_connect		34
-#define KEY_continue		35
-#define KEY_cos			36
-#define KEY_crypt		37
-#define KEY_dbmclose		38
-#define KEY_dbmopen		39
-#define KEY_default		40
-#define KEY_defined		41
-#define KEY_delete		42
-#define KEY_die			43
-#define KEY_do			44
-#define KEY_dump		45
-#define KEY_each		46
-#define KEY_else		47
-#define KEY_elsif		48
-#define KEY_endgrent		49
-#define KEY_endhostent		50
-#define KEY_endnetent		51
-#define KEY_endprotoent		52
-#define KEY_endpwent		53
-#define KEY_endservent		54
-#define KEY_eof			55
-#define KEY_eq			56
-#define KEY_eval		57
-#define KEY_exec		58
-#define KEY_exists		59
-#define KEY_exit		60
-#define KEY_exp			61
-#define KEY_fcntl		62
-#define KEY_fileno		63
-#define KEY_flock		64
-#define KEY_for			65
-#define KEY_foreach		66
-#define KEY_fork		67
-#define KEY_format		68
-#define KEY_formline		69
-#define KEY_ge			70
-#define KEY_getc		71
-#define KEY_getgrent		72
-#define KEY_getgrgid		73
-#define KEY_getgrnam		74
-#define KEY_gethostbyaddr	75
-#define KEY_gethostbyname	76
-#define KEY_gethostent		77
-#define KEY_getlogin		78
-#define KEY_getnetbyaddr	79
-#define KEY_getnetbyname	80
-#define KEY_getnetent		81
-#define KEY_getpeername		82
-#define KEY_getpgrp		83
-#define KEY_getppid		84
-#define KEY_getpriority		85
-#define KEY_getprotobyname	86
-#define KEY_getprotobynumber	87
-#define KEY_getprotoent		88
-#define KEY_getpwent		89
-#define KEY_getpwnam		90
-#define KEY_getpwuid		91
-#define KEY_getservbyname	92
-#define KEY_getservbyport	93
-#define KEY_getservent		94
-#define KEY_getsockname		95
-#define KEY_getsockopt		96
-#define KEY_given		97
-#define KEY_glob		98
-#define KEY_gmtime		99
-#define KEY_goto		100
-#define KEY_grep		101
-#define KEY_gt			102
-#define KEY_hex			103
-#define KEY_if			104
-#define KEY_index		105
-#define KEY_int			106
-#define KEY_ioctl		107
-#define KEY_join		108
-#define KEY_keys		109
-#define KEY_kill		110
-#define KEY_last		111
-#define KEY_lc			112
-#define KEY_lcfirst		113
-#define KEY_le			114
-#define KEY_length		115
-#define KEY_link		116
-#define KEY_listen		117
-#define KEY_local		118
-#define KEY_localtime		119
-#define KEY_lock		120
-#define KEY_log			121
-#define KEY_lstat		122
-#define KEY_lt			123
-#define KEY_m			124
-#define KEY_map			125
-#define KEY_mkdir		126
-#define KEY_msgctl		127
-#define KEY_msgget		128
-#define KEY_msgrcv		129
-#define KEY_msgsnd		130
-#define KEY_my			131
-#define KEY_ne			132
-#define KEY_next		133
-#define KEY_no			134
-#define KEY_not			135
-#define KEY_oct			136
-#define KEY_open		137
-#define KEY_opendir		138
-#define KEY_or			139
-#define KEY_ord			140
-#define KEY_our			141
-#define KEY_pack		142
-#define KEY_package		143
-#define KEY_pipe		144
-#define KEY_pop			145
-#define KEY_pos			146
-#define KEY_print		147
-#define KEY_printf		148
-#define KEY_prototype		149
-#define KEY_push		150
-#define KEY_q			151
-#define KEY_qq			152
-#define KEY_qr			153
-#define KEY_quotemeta		154
-#define KEY_qw			155
-#define KEY_qx			156
-#define KEY_rand		157
-#define KEY_read		158
-#define KEY_readdir		159
-#define KEY_readline		160
-#define KEY_readlink		161
-#define KEY_readpipe		162
-#define KEY_recv		163
-#define KEY_redo		164
-#define KEY_ref			165
-#define KEY_rename		166
-#define KEY_require		167
-#define KEY_reset		168
-#define KEY_return		169
-#define KEY_reverse		170
-#define KEY_rewinddir		171
-#define KEY_rindex		172
-#define KEY_rmdir		173
-#define KEY_s			174
-#define KEY_say			175
-#define KEY_scalar		176
-#define KEY_seek		177
-#define KEY_seekdir		178
-#define KEY_select		179
-#define KEY_semctl		180
-#define KEY_semget		181
-#define KEY_semop		182
-#define KEY_send		183
-#define KEY_setgrent		184
-#define KEY_sethostent		185
-#define KEY_setnetent		186
-#define KEY_setpgrp		187
-#define KEY_setpriority		188
-#define KEY_setprotoent		189
-#define KEY_setpwent		190
-#define KEY_setservent		191
-#define KEY_setsockopt		192
-#define KEY_shift		193
-#define KEY_shmctl		194
-#define KEY_shmget		195
-#define KEY_shmread		196
-#define KEY_shmwrite		197
-#define KEY_shutdown		198
-#define KEY_sin			199
-#define KEY_sleep		200
-#define KEY_socket		201
-#define KEY_socketpair		202
-#define KEY_sort		203
-#define KEY_splice		204
-#define KEY_split		205
-#define KEY_sprintf		206
-#define KEY_sqrt		207
-#define KEY_srand		208
-#define KEY_stat		209
-#define KEY_state		210
-#define KEY_study		211
-#define KEY_sub			212
-#define KEY_substr		213
-#define KEY_symlink		214
-#define KEY_syscall		215
-#define KEY_sysopen		216
-#define KEY_sysread		217
-#define KEY_sysseek		218
-#define KEY_system		219
-#define KEY_syswrite		220
-#define KEY_tell		221
-#define KEY_telldir		222
-#define KEY_tie			223
-#define KEY_tied		224
-#define KEY_time		225
-#define KEY_times		226
-#define KEY_tr			227
-#define KEY_truncate		228
-#define KEY_uc			229
-#define KEY_ucfirst		230
-#define KEY_umask		231
-#define KEY_undef		232
-#define KEY_unless		233
-#define KEY_unlink		234
-#define KEY_unpack		235
-#define KEY_unshift		236
-#define KEY_untie		237
-#define KEY_until		238
-#define KEY_use			239
-#define KEY_utime		240
-#define KEY_values		241
-#define KEY_vec			242
-#define KEY_wait		243
-#define KEY_waitpid		244
-#define KEY_wantarray		245
-#define KEY_warn		246
-#define KEY_when		247
-#define KEY_while		248
-#define KEY_write		249
-#define KEY_x			250
-#define KEY_xor			251
-#define KEY_y			252
+#define KEY___SUB__		4
+#define KEY___DATA__		5
+#define KEY___END__		6
+#define KEY_AUTOLOAD		7
+#define KEY_BEGIN		8
+#define KEY_UNITCHECK		9
+#define KEY_CORE		10
+#define KEY_DESTROY		11
+#define KEY_END			12
+#define KEY_INIT		13
+#define KEY_CHECK		14
+#define KEY_abs			15
+#define KEY_accept		16
+#define KEY_alarm		17
+#define KEY_and			18
+#define KEY_atan2		19
+#define KEY_bind		20
+#define KEY_binmode		21
+#define KEY_bless		22
+#define KEY_break		23
+#define KEY_caller		24
+#define KEY_chdir		25
+#define KEY_chmod		26
+#define KEY_chomp		27
+#define KEY_chop		28
+#define KEY_chown		29
+#define KEY_chr			30
+#define KEY_chroot		31
+#define KEY_close		32
+#define KEY_closedir		33
+#define KEY_cmp			34
+#define KEY_connect		35
+#define KEY_continue		36
+#define KEY_cos			37
+#define KEY_crypt		38
+#define KEY_dbmclose		39
+#define KEY_dbmopen		40
+#define KEY_default		41
+#define KEY_defined		42
+#define KEY_delete		43
+#define KEY_die			44
+#define KEY_do			45
+#define KEY_dump		46
+#define KEY_each		47
+#define KEY_else		48
+#define KEY_elsif		49
+#define KEY_endgrent		50
+#define KEY_endhostent		51
+#define KEY_endnetent		52
+#define KEY_endprotoent		53
+#define KEY_endpwent		54
+#define KEY_endservent		55
+#define KEY_eof			56
+#define KEY_eq			57
+#define KEY_eval		58
+#define KEY_exec		59
+#define KEY_exists		60
+#define KEY_exit		61
+#define KEY_exp			62
+#define KEY_fcntl		63
+#define KEY_fileno		64
+#define KEY_flock		65
+#define KEY_for			66
+#define KEY_foreach		67
+#define KEY_fork		68
+#define KEY_format		69
+#define KEY_formline		70
+#define KEY_ge			71
+#define KEY_getc		72
+#define KEY_getgrent		73
+#define KEY_getgrgid		74
+#define KEY_getgrnam		75
+#define KEY_gethostbyaddr	76
+#define KEY_gethostbyname	77
+#define KEY_gethostent		78
+#define KEY_getlogin		79
+#define KEY_getnetbyaddr	80
+#define KEY_getnetbyname	81
+#define KEY_getnetent		82
+#define KEY_getpeername		83
+#define KEY_getpgrp		84
+#define KEY_getppid		85
+#define KEY_getpriority		86
+#define KEY_getprotobyname	87
+#define KEY_getprotobynumber	88
+#define KEY_getprotoent		89
+#define KEY_getpwent		90
+#define KEY_getpwnam		91
+#define KEY_getpwuid		92
+#define KEY_getservbyname	93
+#define KEY_getservbyport	94
+#define KEY_getservent		95
+#define KEY_getsockname		96
+#define KEY_getsockopt		97
+#define KEY_given		98
+#define KEY_glob		99
+#define KEY_gmtime		100
+#define KEY_goto		101
+#define KEY_grep		102
+#define KEY_gt			103
+#define KEY_hex			104
+#define KEY_if			105
+#define KEY_index		106
+#define KEY_int			107
+#define KEY_ioctl		108
+#define KEY_join		109
+#define KEY_keys		110
+#define KEY_kill		111
+#define KEY_last		112
+#define KEY_lc			113
+#define KEY_lcfirst		114
+#define KEY_le			115
+#define KEY_length		116
+#define KEY_link		117
+#define KEY_listen		118
+#define KEY_local		119
+#define KEY_localtime		120
+#define KEY_lock		121
+#define KEY_log			122
+#define KEY_lstat		123
+#define KEY_lt			124
+#define KEY_m			125
+#define KEY_map			126
+#define KEY_mkdir		127
+#define KEY_msgctl		128
+#define KEY_msgget		129
+#define KEY_msgrcv		130
+#define KEY_msgsnd		131
+#define KEY_my			132
+#define KEY_ne			133
+#define KEY_next		134
+#define KEY_no			135
+#define KEY_not			136
+#define KEY_oct			137
+#define KEY_open		138
+#define KEY_opendir		139
+#define KEY_or			140
+#define KEY_ord			141
+#define KEY_our			142
+#define KEY_pack		143
+#define KEY_package		144
+#define KEY_pipe		145
+#define KEY_pop			146
+#define KEY_pos			147
+#define KEY_print		148
+#define KEY_printf		149
+#define KEY_prototype		150
+#define KEY_push		151
+#define KEY_q			152
+#define KEY_qq			153
+#define KEY_qr			154
+#define KEY_quotemeta		155
+#define KEY_qw			156
+#define KEY_qx			157
+#define KEY_rand		158
+#define KEY_read		159
+#define KEY_readdir		160
+#define KEY_readline		161
+#define KEY_readlink		162
+#define KEY_readpipe		163
+#define KEY_recv		164
+#define KEY_redo		165
+#define KEY_ref			166
+#define KEY_rename		167
+#define KEY_require		168
+#define KEY_reset		169
+#define KEY_return		170
+#define KEY_reverse		171
+#define KEY_rewinddir		172
+#define KEY_rindex		173
+#define KEY_rmdir		174
+#define KEY_s			175
+#define KEY_say			176
+#define KEY_scalar		177
+#define KEY_seek		178
+#define KEY_seekdir		179
+#define KEY_select		180
+#define KEY_semctl		181
+#define KEY_semget		182
+#define KEY_semop		183
+#define KEY_send		184
+#define KEY_setgrent		185
+#define KEY_sethostent		186
+#define KEY_setnetent		187
+#define KEY_setpgrp		188
+#define KEY_setpriority		189
+#define KEY_setprotoent		190
+#define KEY_setpwent		191
+#define KEY_setservent		192
+#define KEY_setsockopt		193
+#define KEY_shift		194
+#define KEY_shmctl		195
+#define KEY_shmget		196
+#define KEY_shmread		197
+#define KEY_shmwrite		198
+#define KEY_shutdown		199
+#define KEY_sin			200
+#define KEY_sleep		201
+#define KEY_socket		202
+#define KEY_socketpair		203
+#define KEY_sort		204
+#define KEY_splice		205
+#define KEY_split		206
+#define KEY_sprintf		207
+#define KEY_sqrt		208
+#define KEY_srand		209
+#define KEY_stat		210
+#define KEY_state		211
+#define KEY_study		212
+#define KEY_sub			213
+#define KEY_substr		214
+#define KEY_symlink		215
+#define KEY_syscall		216
+#define KEY_sysopen		217
+#define KEY_sysread		218
+#define KEY_sysseek		219
+#define KEY_system		220
+#define KEY_syswrite		221
+#define KEY_tell		222
+#define KEY_telldir		223
+#define KEY_tie			224
+#define KEY_tied		225
+#define KEY_time		226
+#define KEY_times		227
+#define KEY_tr			228
+#define KEY_truncate		229
+#define KEY_uc			230
+#define KEY_ucfirst		231
+#define KEY_umask		232
+#define KEY_undef		233
+#define KEY_unless		234
+#define KEY_unlink		235
+#define KEY_unpack		236
+#define KEY_unshift		237
+#define KEY_untie		238
+#define KEY_until		239
+#define KEY_use			240
+#define KEY_utime		241
+#define KEY_values		242
+#define KEY_vec			243
+#define KEY_wait		244
+#define KEY_waitpid		245
+#define KEY_wantarray		246
+#define KEY_warn		247
+#define KEY_when		248
+#define KEY_while		249
+#define KEY_write		250
+#define KEY_x			251
+#define KEY_xor			252
+#define KEY_y			253
 
 /* ex: set ro: */
diff --git a/opcode.h b/opcode.h
index 122c67f..0a9f94d 100644
--- a/opcode.h
+++ b/opcode.h
@@ -398,6 +398,7 @@ EXTCONST char* const PL_op_name[] = {
 	"rkeys",
 	"rvalues",
 	"transr",
+	"runcv",
 };
 #endif
 
@@ -775,6 +776,7 @@ EXTCONST char* const PL_op_desc[] = {
 	"keys on reference",
 	"values on reference",
 	"transliteration (tr///)",
+	"__SUB__",
 };
 #endif
 
@@ -1166,6 +1168,7 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
 	Perl_pp_rkeys,
 	Perl_pp_rkeys,	/* Perl_pp_rvalues */
 	Perl_pp_trans,	/* Perl_pp_transr */
+	Perl_pp_runcv,
 }
 #endif
 #ifdef PERL_PPADDR_INITED
@@ -1554,6 +1557,7 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */
 	Perl_ck_each,		/* rkeys */
 	Perl_ck_each,		/* rvalues */
 	Perl_ck_match,		/* transr */
+	Perl_ck_null,		/* runcv */
 }
 #endif
 #ifdef PERL_CHECK_INITED
@@ -1936,6 +1940,7 @@ EXTCONST U32 PL_opargs[] = {
 	0x00001b08,	/* rkeys */
 	0x00001b08,	/* rvalues */
 	0x00001804,	/* transr */
+	0x00000004,	/* runcv */
 };
 #endif
 
diff --git a/opnames.h b/opnames.h
index 609c6e2..3e14f30 100644
--- a/opnames.h
+++ b/opnames.h
@@ -385,10 +385,11 @@ typedef enum opcode {
 	OP_RKEYS	 = 367,
 	OP_RVALUES	 = 368,
 	OP_TRANSR	 = 369,
+	OP_RUNCV	 = 370,
 	OP_max		
 } opcode;
 
-#define MAXO 370
+#define MAXO 371
 #define OP_phoney_INPUT_ONLY -1
 #define OP_phoney_OUTPUT_ONLY -2
 
diff --git a/perl_keyword.pl b/perl_keyword.pl
index 73128c3..9bea3e8 100644
--- a/perl_keyword.pl
+++ b/perl_keyword.pl
@@ -12,7 +12,8 @@ my @pos = qw(__DATA__ __END__ AUTOLOAD BEGIN CHECK DESTROY default defined
 	    split state study sub tr use undef UNITCHECK until
 	    unless when while y);
 
-my @neg = qw(__FILE__ __LINE__ __PACKAGE__ and abs alarm atan2 accept bless
+my @neg = qw(__FILE__ __LINE__ __PACKAGE__ __SUB__
+	    and abs alarm atan2 accept bless
 	    break bind binmode CORE cmp chr cos chop close chdir chomp chmod
 	    chown crypt chroot caller connect closedir continue die dump
 	    dbmopen dbmclose eq eof exp exit exec each endgrent endpwent
diff --git a/pp.c b/pp.c
index 47cf756..0126061 100644
--- a/pp.c
+++ b/pp.c
@@ -6162,6 +6162,14 @@ PP(pp_boolkeys)
     RETURN;
 }
 
+PP(pp_runcv)
+{
+    dSP;
+    CV * const cv = find_runcv(NULL);
+    XPUSHs(CvUNIQUE(cv) ? &PL_sv_undef : sv_2mortal(newRV((SV *)cv)));
+    RETURN;
+}
+
 /*
  * Local variables:
  * c-indentation-style: bsd
diff --git a/pp.sym b/pp.sym
index 11e8f78..bdafb6e 100644
--- a/pp.sym
+++ b/pp.sym
@@ -414,5 +414,6 @@ Perl_pp_reach
 Perl_pp_rkeys
 Perl_pp_rvalues
 Perl_pp_transr
+Perl_pp_runcv
 
 # ex: set ro:
diff --git a/proto.h b/proto.h
index c4df3e2..b621af6 100644
--- a/proto.h
+++ b/proto.h
@@ -3147,6 +3147,7 @@ PERL_CALLCONV OP *	Perl_pp_right_shift(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rindex(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rkeys(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rmdir(pTHX);
+PERL_CALLCONV OP *	Perl_pp_runcv(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rv2av(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rv2cv(pTHX);
 PERL_CALLCONV OP *	Perl_pp_rv2gv(pTHX);
diff --git a/regen/keywords.pl b/regen/keywords.pl
index 381e098..b19f2b1 100755
--- a/regen/keywords.pl
+++ b/regen/keywords.pl
@@ -64,6 +64,7 @@ NULL
 __FILE__
 __LINE__
 __PACKAGE__
+__SUB__
 __DATA__
 __END__
 AUTOLOAD
diff --git a/regen/opcode.pl b/regen/opcode.pl
index bd3d55a..84d8b69 100755
--- a/regen/opcode.pl
+++ b/regen/opcode.pl
@@ -1106,3 +1106,5 @@ rvalues		values on reference			ck_each		t%	S
 
 # y///r
 transr		transliteration (tr///)	ck_match	is"	S
+
+runcv		__SUB__			ck_null		s0	
diff --git a/toke.c b/toke.c
index ef14c18..e750ee0 100644
--- a/toke.c
+++ b/toke.c
@@ -6898,6 +6898,10 @@ Perl_yylex(pTHX)
 					 : &PL_sv_undef));
 	    TERM(THING);
 
+	case KEY___SUB__:
+	    pl_yylval.opval = (OP*)newOP(OP_RUNCV, 0);
+	    TERM(THING);
+
 	case KEY___DATA__:
 	case KEY___END__: {
 	    GV *gv;
@@ -10289,7 +10293,7 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords)
           goto unknown;
       }
 
-    case 7: /* 29 tokens of length 7 */
+    case 7: /* 30 tokens of length 7 */
       switch (name[0])
       {
         case 'D':
@@ -10306,14 +10310,35 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords)
           goto unknown;
 
         case '_':
-          if (name[1] == '_' &&
-              name[2] == 'E' &&
-              name[3] == 'N' &&
-              name[4] == 'D' &&
-              name[5] == '_' &&
-              name[6] == '_')
-          {                                       /* __END__    */
-            return KEY___END__;
+          if (name[1] == '_')
+          {
+            switch (name[2])
+            {
+              case 'E':
+                if (name[3] == 'N' &&
+                    name[4] == 'D' &&
+                    name[5] == '_' &&
+                    name[6] == '_')
+                {                                 /* __END__          */
+                  return KEY___END__;
+                }
+
+                goto unknown;
+
+              case 'S':
+                if (name[3] == 'U' &&
+                    name[4] == 'B' &&
+                    name[5] == '_' &&
+                    name[6] == '_')
+                {                                 /* __SUB__          */
+                  return -KEY___SUB__;
+                }
+
+                goto unknown;
+
+              default:
+                goto unknown;
+            }
           }
 
           goto unknown;

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @Abigail

On Sun, Dec 12, 2010 at 12​:26​:07PM -0800, Father Chrysostomos wrote​:

# New Ticket Created by Father Chrysostomos
# Please include the string​: [perl #80628]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=80628 >

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

Technically, it could break programs, as in theory someone could have a sub
named '__SUB__'. It's not something I worry about though.

I think this is going to be very handy. I see opportunity for obfuscation
as well, but that's just my twisted mind.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @cpansprout

On Dec 12, 2010, at 12​:36 PM, Abigail via RT wrote​:

On Sun, Dec 12, 2010 at 12​:26​:07PM -0800, Father Chrysostomos wrote​:

# New Ticket Created by Father Chrysostomos
# Please include the string​: [perl #80628]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=80628 >

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

Technically, it could break programs, as in theory someone could have a sub
named '__SUB__'. It's not something I worry about though.

I thought such names were reserved.

I think this is going to be very handy. I see opportunity for obfuscation
as well, but that's just my twisted mind.

Twisted, eh? How about this?

()=@​==split" ","Just another Perl hacker,\n";
print reverse@​=

@​@​=("Perl hacker,\n",'Just another '),
, $@​=sub{print$@​[@​_]} ,
  , ()->$@​,$@​->() ,

use constant{Just=>another=>Perl=>hacker=>};$\=",\n";
print join" ",map eval"sort $_,$_",qw! Just Perl!

perl -e 'print do{{&{sub{"Just another Perl hacker,\n"}},last}}'

perl5.12.2 -e '$_{0+\$_}="Just another Perl hacker,\n";@​INC=sub{\\$_};print$_{require _};sub SCALAR{$_[0]};'

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @Abigail

On Sun, Dec 12, 2010 at 12​:52​:08PM -0800, Father Chrysostomos wrote​:

On Dec 12, 2010, at 12​:36 PM, Abigail via RT wrote​:

On Sun, Dec 12, 2010 at 12​:26​:07PM -0800, Father Chrysostomos wrote​:

# New Ticket Created by Father Chrysostomos
# Please include the string​: [perl #80628]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=80628 >

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

Technically, it could break programs, as in theory someone could have a sub
named '__SUB__'. It's not something I worry about though.

I thought such names were reserved.

If it is, it's neither enforced, or even protected by a warning​:

  $ perl -wE 'sub __SUB__ {sub {say "Foo"}} __SUB__ -> ()'
  Foo
  $

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2010

From @rafl

Father Chrysostomos (via RT) <perlbug-followup@​perl.org> writes​:

This patch adds a __SUB__ keyword that returns the current subroutine,
or undef for the main program, a special block, or an eval.

Using '__SUB__' made me think it was a compile-time constant such as
__FILE__ and __LINE__. It isn't, so I think it's not very good naming.

Why not make it look like a regular function or keyword, such as

  sub {
  print "$_[0]\n";
  caller_cv(0)->($_[0] + 1) if $_[0] < $arg;
  }

In fact this is already available on CPAN as Devel​::Caller. Is this
something common and useful enough to make it part of the core language?
I'm not really convinced of that.

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @sciurius

Abigail <abigail@​abigail.be> writes​:

Technically, it could break programs, as in theory someone could have a sub
named '__SUB__'. It's not something I worry about though.

I thought such names were reserved.

If it is, it's neither enforced, or even protected by a warning​:

Neither are subroutines/variable names with all UPPERCASE.

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @ikegami

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @sciurius

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 12 December 2010 21​:26, Father Chrysostomos
<perlbug-followup@​perl.org> wrote​:

# New Ticket Created by  Father Chrysostomos
# Please include the string​:  [perl #80628]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=80628 >

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

I first thought of adding this to make recursive lexicals subs easier to write (whenever they are added)​:

my sub foo { __SUB__->() }

my sub foo;  # the alternative
my sub foo { foo() }

The really neat thing, which I realised only after writing it, is that it allows for recursive closures to be written much more simply​:

sub make_recursive_function {
 my $arg = shift;
 sub {
   print "$_[0]\n";
   __SUB__->($_[0] + 1) if $_[0] < $arg;
 }
}

as opposed to​:

use Scalar​::Util;
sub make_recursive_function {
 my $arg = shift;
 my $sub;
 my $life_raft = $sub = sub {
   print "$_[0]\n";
   &$sub($_[0] + 1) if $_[0] < $arg;
 }
 Scalar​::Util​::weaken($sub);
 $sub;
}

[Reminder to myself​: I need to add it to Opcode.pm as well.]

---
Flags​:
   category=core
   severity=wishlist
---
Site configuration information for perl 5.13.7​:

Configured by sprout at Thu Dec  9 14​:53​:58 PST 2010.

Summary of my perl5 (revision 5 version 13 subversion 7) configuration​:
 Snapshot of​: 9e9fdd5
 Platform​:
   osname=darwin, osvers=10.4.0, archname=darwin-2level
   uname='darwin pint.local 10.4.0 darwin kernel version 10.4.0​: fri apr 23 18​:28​:53 pdt 2010; root​:xnu-1504.7.4~1release_i386 i386 '
   config_args='-de -Dusedevel -DDEBUGGING'
   hint=recommended, useposix=true, d_sigaction=define
   useithreads=undef, usemultiplicity=undef
   useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
   use64bitint=undef, use64bitall=undef, uselongdouble=undef
   usemymalloc=n, bincompat5005=undef
 Compiler​:
   cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
   optimize='-O3 -g',
   cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
   ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
   intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
   d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
   ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
   alignbytes=8, prototype=define
 Linker and Libraries​:
   ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
   libpth=/usr/local/lib /usr/lib
   libs=-ldbm -ldl -lm -lutil -lc
   perllibs=-ldl -lm -lutil -lc
   libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
   gnulibc_version=''
 Dynamic Linking​:
   dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
   cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches​:

---
@​INC for perl 5.13.7​:
   /usr/local/lib/perl5/site_perl/5.13.7/darwin-2level
   /usr/local/lib/perl5/site_perl/5.13.7
   /usr/local/lib/perl5/5.13.7/darwin-2level
   /usr/local/lib/perl5/5.13.7
   /usr/local/lib/perl5/site_perl
   .

---
Environment for perl 5.13.7​:
   DYLD_LIBRARY_PATH (unset)
   HOME=/Users/sprout
   LANG=en_US.UTF-8
   LANGUAGE (unset)
   LD_LIBRARY_PATH (unset)
   LOGDIR (unset)
   PATH=/usr/bin​:/bin​:/usr/sbin​:/sbin​:/usr/local/bin​:/usr/X11/bin​:/usr/local/bin
   PERL_BADLANG (unset)
   SHELL=/bin/bash

diff --git a/embed.h b/embed.h
index 5f846f5..f511965 100644
--- a/embed.h
+++ b/embed.h
@​@​ -1363,6 +1363,7 @​@​
 #define pp_rindex()            Perl_pp_rindex(aTHX)
 #define pp_rkeys()             Perl_pp_rkeys(aTHX)
 #define pp_rmdir()             Perl_pp_rmdir(aTHX)
+#define pp_runcv()             Perl_pp_runcv(aTHX)
 #define pp_rv2av()             Perl_pp_rv2av(aTHX)
 #define pp_rv2cv()             Perl_pp_rv2cv(aTHX)
 #define pp_rv2gv()             Perl_pp_rv2gv(aTHX)
diff --git a/keywords.h b/keywords.h
index 526f3e4..1f63f06 100644
--- a/keywords.h
+++ b/keywords.h
@​@​ -16,254 +16,255 @​@​
 #define KEY___FILE__           1
 #define KEY___LINE__           2
 #define KEY___PACKAGE__                3
-#define KEY___DATA__           4
-#define KEY___END__            5
-#define KEY_AUTOLOAD           6
-#define KEY_BEGIN              7
-#define KEY_UNITCHECK          8
-#define KEY_CORE               9
-#define KEY_DESTROY            10
-#define KEY_END                        11
-#define KEY_INIT               12
-#define KEY_CHECK              13
-#define KEY_abs                        14
-#define KEY_accept             15
-#define KEY_alarm              16
-#define KEY_and                        17
-#define KEY_atan2              18
-#define KEY_bind               19
-#define KEY_binmode            20
-#define KEY_bless              21
-#define KEY_break              22
-#define KEY_caller             23
-#define KEY_chdir              24
-#define KEY_chmod              25
-#define KEY_chomp              26
-#define KEY_chop               27
-#define KEY_chown              28
-#define KEY_chr                        29
-#define KEY_chroot             30
-#define KEY_close              31
-#define KEY_closedir           32
-#define KEY_cmp                        33
-#define KEY_connect            34
-#define KEY_continue           35
-#define KEY_cos                        36
-#define KEY_crypt              37
-#define KEY_dbmclose           38
-#define KEY_dbmopen            39
-#define KEY_default            40
-#define KEY_defined            41
-#define KEY_delete             42
-#define KEY_die                        43
-#define KEY_do                 44
-#define KEY_dump               45
-#define KEY_each               46
-#define KEY_else               47
-#define KEY_elsif              48
-#define KEY_endgrent           49
-#define KEY_endhostent         50
-#define KEY_endnetent          51
-#define KEY_endprotoent                52
-#define KEY_endpwent           53
-#define KEY_endservent         54
-#define KEY_eof                        55
-#define KEY_eq                 56
-#define KEY_eval               57
-#define KEY_exec               58
-#define KEY_exists             59
-#define KEY_exit               60
-#define KEY_exp                        61
-#define KEY_fcntl              62
-#define KEY_fileno             63
-#define KEY_flock              64
-#define KEY_for                        65
-#define KEY_foreach            66
-#define KEY_fork               67
-#define KEY_format             68
-#define KEY_formline           69
-#define KEY_ge                 70
-#define KEY_getc               71
-#define KEY_getgrent           72
-#define KEY_getgrgid           73
-#define KEY_getgrnam           74
-#define KEY_gethostbyaddr      75
-#define KEY_gethostbyname      76
-#define KEY_gethostent         77
-#define KEY_getlogin           78
-#define KEY_getnetbyaddr       79
-#define KEY_getnetbyname       80
-#define KEY_getnetent          81
-#define KEY_getpeername                82
-#define KEY_getpgrp            83
-#define KEY_getppid            84
-#define KEY_getpriority                85
-#define KEY_getprotobyname     86
-#define KEY_getprotobynumber   87
-#define KEY_getprotoent                88
-#define KEY_getpwent           89
-#define KEY_getpwnam           90
-#define KEY_getpwuid           91
-#define KEY_getservbyname      92
-#define KEY_getservbyport      93
-#define KEY_getservent         94
-#define KEY_getsockname                95
-#define KEY_getsockopt         96
-#define KEY_given              97
-#define KEY_glob               98
-#define KEY_gmtime             99
-#define KEY_goto               100
-#define KEY_grep               101
-#define KEY_gt                 102
-#define KEY_hex                        103
-#define KEY_if                 104
-#define KEY_index              105
-#define KEY_int                        106
-#define KEY_ioctl              107
-#define KEY_join               108
-#define KEY_keys               109
-#define KEY_kill               110
-#define KEY_last               111
-#define KEY_lc                 112
-#define KEY_lcfirst            113
-#define KEY_le                 114
-#define KEY_length             115
-#define KEY_link               116
-#define KEY_listen             117
-#define KEY_local              118
-#define KEY_localtime          119
-#define KEY_lock               120
-#define KEY_log                        121
-#define KEY_lstat              122
-#define KEY_lt                 123
-#define KEY_m                  124
-#define KEY_map                        125
-#define KEY_mkdir              126
-#define KEY_msgctl             127
-#define KEY_msgget             128
-#define KEY_msgrcv             129
-#define KEY_msgsnd             130
-#define KEY_my                 131
-#define KEY_ne                 132
-#define KEY_next               133
-#define KEY_no                 134
-#define KEY_not                        135
-#define KEY_oct                        136
-#define KEY_open               137
-#define KEY_opendir            138
-#define KEY_or                 139
-#define KEY_ord                        140
-#define KEY_our                        141
-#define KEY_pack               142
-#define KEY_package            143
-#define KEY_pipe               144
-#define KEY_pop                        145
-#define KEY_pos                        146
-#define KEY_print              147
-#define KEY_printf             148
-#define KEY_prototype          149
-#define KEY_push               150
-#define KEY_q                  151
-#define KEY_qq                 152
-#define KEY_qr                 153
-#define KEY_quotemeta          154
-#define KEY_qw                 155
-#define KEY_qx                 156
-#define KEY_rand               157
-#define KEY_read               158
-#define KEY_readdir            159
-#define KEY_readline           160
-#define KEY_readlink           161
-#define KEY_readpipe           162
-#define KEY_recv               163
-#define KEY_redo               164
-#define KEY_ref                        165
-#define KEY_rename             166
-#define KEY_require            167
-#define KEY_reset              168
-#define KEY_return             169
-#define KEY_reverse            170
-#define KEY_rewinddir          171
-#define KEY_rindex             172
-#define KEY_rmdir              173
-#define KEY_s                  174
-#define KEY_say                        175
-#define KEY_scalar             176
-#define KEY_seek               177
-#define KEY_seekdir            178
-#define KEY_select             179
-#define KEY_semctl             180
-#define KEY_semget             181
-#define KEY_semop              182
-#define KEY_send               183
-#define KEY_setgrent           184
-#define KEY_sethostent         185
-#define KEY_setnetent          186
-#define KEY_setpgrp            187
-#define KEY_setpriority                188
-#define KEY_setprotoent                189
-#define KEY_setpwent           190
-#define KEY_setservent         191
-#define KEY_setsockopt         192
-#define KEY_shift              193
-#define KEY_shmctl             194
-#define KEY_shmget             195
-#define KEY_shmread            196
-#define KEY_shmwrite           197
-#define KEY_shutdown           198
-#define KEY_sin                        199
-#define KEY_sleep              200
-#define KEY_socket             201
-#define KEY_socketpair         202
-#define KEY_sort               203
-#define KEY_splice             204
-#define KEY_split              205
-#define KEY_sprintf            206
-#define KEY_sqrt               207
-#define KEY_srand              208
-#define KEY_stat               209
-#define KEY_state              210
-#define KEY_study              211
-#define KEY_sub                        212
-#define KEY_substr             213
-#define KEY_symlink            214
-#define KEY_syscall            215
-#define KEY_sysopen            216
-#define KEY_sysread            217
-#define KEY_sysseek            218
-#define KEY_system             219
-#define KEY_syswrite           220
-#define KEY_tell               221
-#define KEY_telldir            222
-#define KEY_tie                        223
-#define KEY_tied               224
-#define KEY_time               225
-#define KEY_times              226
-#define KEY_tr                 227
-#define KEY_truncate           228
-#define KEY_uc                 229
-#define KEY_ucfirst            230
-#define KEY_umask              231
-#define KEY_undef              232
-#define KEY_unless             233
-#define KEY_unlink             234
-#define KEY_unpack             235
-#define KEY_unshift            236
-#define KEY_untie              237
-#define KEY_until              238
-#define KEY_use                        239
-#define KEY_utime              240
-#define KEY_values             241
-#define KEY_vec                        242
-#define KEY_wait               243
-#define KEY_waitpid            244
-#define KEY_wantarray          245
-#define KEY_warn               246
-#define KEY_when               247
-#define KEY_while              248
-#define KEY_write              249
-#define KEY_x                  250
-#define KEY_xor                        251
-#define KEY_y                  252
+#define KEY___SUB__            4
+#define KEY___DATA__           5
+#define KEY___END__            6
+#define KEY_AUTOLOAD           7
+#define KEY_BEGIN              8
+#define KEY_UNITCHECK          9
+#define KEY_CORE               10
+#define KEY_DESTROY            11
+#define KEY_END                        12
+#define KEY_INIT               13
+#define KEY_CHECK              14
+#define KEY_abs                        15
+#define KEY_accept             16
+#define KEY_alarm              17
+#define KEY_and                        18
+#define KEY_atan2              19
+#define KEY_bind               20
+#define KEY_binmode            21
+#define KEY_bless              22
+#define KEY_break              23
+#define KEY_caller             24
+#define KEY_chdir              25
+#define KEY_chmod              26
+#define KEY_chomp              27
+#define KEY_chop               28
+#define KEY_chown              29
+#define KEY_chr                        30
+#define KEY_chroot             31
+#define KEY_close              32
+#define KEY_closedir           33
+#define KEY_cmp                        34
+#define KEY_connect            35
+#define KEY_continue           36
+#define KEY_cos                        37
+#define KEY_crypt              38
+#define KEY_dbmclose           39
+#define KEY_dbmopen            40
+#define KEY_default            41
+#define KEY_defined            42
+#define KEY_delete             43
+#define KEY_die                        44
+#define KEY_do                 45
+#define KEY_dump               46
+#define KEY_each               47
+#define KEY_else               48
+#define KEY_elsif              49
+#define KEY_endgrent           50
+#define KEY_endhostent         51
+#define KEY_endnetent          52
+#define KEY_endprotoent                53
+#define KEY_endpwent           54
+#define KEY_endservent         55
+#define KEY_eof                        56
+#define KEY_eq                 57
+#define KEY_eval               58
+#define KEY_exec               59
+#define KEY_exists             60
+#define KEY_exit               61
+#define KEY_exp                        62
+#define KEY_fcntl              63
+#define KEY_fileno             64
+#define KEY_flock              65
+#define KEY_for                        66
+#define KEY_foreach            67
+#define KEY_fork               68
+#define KEY_format             69
+#define KEY_formline           70
+#define KEY_ge                 71
+#define KEY_getc               72
+#define KEY_getgrent           73
+#define KEY_getgrgid           74
+#define KEY_getgrnam           75
+#define KEY_gethostbyaddr      76
+#define KEY_gethostbyname      77
+#define KEY_gethostent         78
+#define KEY_getlogin           79
+#define KEY_getnetbyaddr       80
+#define KEY_getnetbyname       81
+#define KEY_getnetent          82
+#define KEY_getpeername                83
+#define KEY_getpgrp            84
+#define KEY_getppid            85
+#define KEY_getpriority                86
+#define KEY_getprotobyname     87
+#define KEY_getprotobynumber   88
+#define KEY_getprotoent                89
+#define KEY_getpwent           90
+#define KEY_getpwnam           91
+#define KEY_getpwuid           92
+#define KEY_getservbyname      93
+#define KEY_getservbyport      94
+#define KEY_getservent         95
+#define KEY_getsockname                96
+#define KEY_getsockopt         97
+#define KEY_given              98
+#define KEY_glob               99
+#define KEY_gmtime             100
+#define KEY_goto               101
+#define KEY_grep               102
+#define KEY_gt                 103
+#define KEY_hex                        104
+#define KEY_if                 105
+#define KEY_index              106
+#define KEY_int                        107
+#define KEY_ioctl              108
+#define KEY_join               109
+#define KEY_keys               110
+#define KEY_kill               111
+#define KEY_last               112
+#define KEY_lc                 113
+#define KEY_lcfirst            114
+#define KEY_le                 115
+#define KEY_length             116
+#define KEY_link               117
+#define KEY_listen             118
+#define KEY_local              119
+#define KEY_localtime          120
+#define KEY_lock               121
+#define KEY_log                        122
+#define KEY_lstat              123
+#define KEY_lt                 124
+#define KEY_m                  125
+#define KEY_map                        126
+#define KEY_mkdir              127
+#define KEY_msgctl             128
+#define KEY_msgget             129
+#define KEY_msgrcv             130
+#define KEY_msgsnd             131
+#define KEY_my                 132
+#define KEY_ne                 133
+#define KEY_next               134
+#define KEY_no                 135
+#define KEY_not                        136
+#define KEY_oct                        137
+#define KEY_open               138
+#define KEY_opendir            139
+#define KEY_or                 140
+#define KEY_ord                        141
+#define KEY_our                        142
+#define KEY_pack               143
+#define KEY_package            144
+#define KEY_pipe               145
+#define KEY_pop                        146
+#define KEY_pos                        147
+#define KEY_print              148
+#define KEY_printf             149
+#define KEY_prototype          150
+#define KEY_push               151
+#define KEY_q                  152
+#define KEY_qq                 153
+#define KEY_qr                 154
+#define KEY_quotemeta          155
+#define KEY_qw                 156
+#define KEY_qx                 157
+#define KEY_rand               158
+#define KEY_read               159
+#define KEY_readdir            160
+#define KEY_readline           161
+#define KEY_readlink           162
+#define KEY_readpipe           163
+#define KEY_recv               164
+#define KEY_redo               165
+#define KEY_ref                        166
+#define KEY_rename             167
+#define KEY_require            168
+#define KEY_reset              169
+#define KEY_return             170
+#define KEY_reverse            171
+#define KEY_rewinddir          172
+#define KEY_rindex             173
+#define KEY_rmdir              174
+#define KEY_s                  175
+#define KEY_say                        176
+#define KEY_scalar             177
+#define KEY_seek               178
+#define KEY_seekdir            179
+#define KEY_select             180
+#define KEY_semctl             181
+#define KEY_semget             182
+#define KEY_semop              183
+#define KEY_send               184
+#define KEY_setgrent           185
+#define KEY_sethostent         186
+#define KEY_setnetent          187
+#define KEY_setpgrp            188
+#define KEY_setpriority                189
+#define KEY_setprotoent                190
+#define KEY_setpwent           191
+#define KEY_setservent         192
+#define KEY_setsockopt         193
+#define KEY_shift              194
+#define KEY_shmctl             195
+#define KEY_shmget             196
+#define KEY_shmread            197
+#define KEY_shmwrite           198
+#define KEY_shutdown           199
+#define KEY_sin                        200
+#define KEY_sleep              201
+#define KEY_socket             202
+#define KEY_socketpair         203
+#define KEY_sort               204
+#define KEY_splice             205
+#define KEY_split              206
+#define KEY_sprintf            207
+#define KEY_sqrt               208
+#define KEY_srand              209
+#define KEY_stat               210
+#define KEY_state              211
+#define KEY_study              212
+#define KEY_sub                        213
+#define KEY_substr             214
+#define KEY_symlink            215
+#define KEY_syscall            216
+#define KEY_sysopen            217
+#define KEY_sysread            218
+#define KEY_sysseek            219
+#define KEY_system             220
+#define KEY_syswrite           221
+#define KEY_tell               222
+#define KEY_telldir            223
+#define KEY_tie                        224
+#define KEY_tied               225
+#define KEY_time               226
+#define KEY_times              227
+#define KEY_tr                 228
+#define KEY_truncate           229
+#define KEY_uc                 230
+#define KEY_ucfirst            231
+#define KEY_umask              232
+#define KEY_undef              233
+#define KEY_unless             234
+#define KEY_unlink             235
+#define KEY_unpack             236
+#define KEY_unshift            237
+#define KEY_untie              238
+#define KEY_until              239
+#define KEY_use                        240
+#define KEY_utime              241
+#define KEY_values             242
+#define KEY_vec                        243
+#define KEY_wait               244
+#define KEY_waitpid            245
+#define KEY_wantarray          246
+#define KEY_warn               247
+#define KEY_when               248
+#define KEY_while              249
+#define KEY_write              250
+#define KEY_x                  251
+#define KEY_xor                        252
+#define KEY_y                  253

 /* ex​: set ro​: */
diff --git a/opcode.h b/opcode.h
index 122c67f..0a9f94d 100644
--- a/opcode.h
+++ b/opcode.h
@​@​ -398,6 +398,7 @​@​ EXTCONST char* const PL_op_name[] = {
       "rkeys",
       "rvalues",
       "transr",
+       "runcv",
 };
 #endif

@​@​ -775,6 +776,7 @​@​ EXTCONST char* const PL_op_desc[] = {
       "keys on reference",
       "values on reference",
       "transliteration (tr///)",
+       "__SUB__",
 };
 #endif

@​@​ -1166,6 +1168,7 @​@​ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
       Perl_pp_rkeys,
       Perl_pp_rkeys,  /* Perl_pp_rvalues */
       Perl_pp_trans,  /* Perl_pp_transr */
+       Perl_pp_runcv,
 }
 #endif
 #ifdef PERL_PPADDR_INITED
@​@​ -1554,6 +1557,7 @​@​ EXT Perl_check_t PL_check[] /* or perlvars.h */
       Perl_ck_each,           /* rkeys */
       Perl_ck_each,           /* rvalues */
       Perl_ck_match,          /* transr */
+       Perl_ck_null,           /* runcv */
 }
 #endif
 #ifdef PERL_CHECK_INITED
@​@​ -1936,6 +1940,7 @​@​ EXTCONST U32 PL_opargs[] = {
       0x00001b08,     /* rkeys */
       0x00001b08,     /* rvalues */
       0x00001804,     /* transr */
+       0x00000004,     /* runcv */
 };
 #endif

diff --git a/opnames.h b/opnames.h
index 609c6e2..3e14f30 100644
--- a/opnames.h
+++ b/opnames.h
@​@​ -385,10 +385,11 @​@​ typedef enum opcode {
       OP_RKEYS         = 367,
       OP_RVALUES       = 368,
       OP_TRANSR        = 369,
+       OP_RUNCV         = 370,
       OP_max
 } opcode;

-#define MAXO 370
+#define MAXO 371
 #define OP_phoney_INPUT_ONLY -1
 #define OP_phoney_OUTPUT_ONLY -2

diff --git a/perl_keyword.pl b/perl_keyword.pl
index 73128c3..9bea3e8 100644
--- a/perl_keyword.pl
+++ b/perl_keyword.pl
@​@​ -12,7 +12,8 @​@​ my @​pos = qw(__DATA__ __END__ AUTOLOAD BEGIN CHECK DESTROY default defined
           split state study sub tr use undef UNITCHECK until
           unless when while y);

-my @​neg = qw(__FILE__ __LINE__ __PACKAGE__ and abs alarm atan2 accept bless
+my @​neg = qw(__FILE__ __LINE__ __PACKAGE__ __SUB__
+           and abs alarm atan2 accept bless
           break bind binmode CORE cmp chr cos chop close chdir chomp chmod
           chown crypt chroot caller connect closedir continue die dump
           dbmopen dbmclose eq eof exp exit exec each endgrent endpwent
diff --git a/pp.c b/pp.c
index 47cf756..0126061 100644
--- a/pp.c
+++ b/pp.c
@​@​ -6162,6 +6162,14 @​@​ PP(pp_boolkeys)
    RETURN;
 }

+PP(pp_runcv)
+{
+    dSP;
+    CV * const cv = find_runcv(NULL);
+    XPUSHs(CvUNIQUE(cv) ? &PL_sv_undef : sv_2mortal(newRV((SV *)cv)));
+    RETURN;
+}
+
 /*
 * Local variables​:
 * c-indentation-style​: bsd
diff --git a/pp.sym b/pp.sym
index 11e8f78..bdafb6e 100644
--- a/pp.sym
+++ b/pp.sym
@​@​ -414,5 +414,6 @​@​ Perl_pp_reach
 Perl_pp_rkeys
 Perl_pp_rvalues
 Perl_pp_transr
+Perl_pp_runcv

 # ex​: set ro​:
diff --git a/proto.h b/proto.h
index c4df3e2..b621af6 100644
--- a/proto.h
+++ b/proto.h
@​@​ -3147,6 +3147,7 @​@​ PERL_CALLCONV OP *        Perl_pp_right_shift(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rindex(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rkeys(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rmdir(pTHX);
+PERL_CALLCONV OP *     Perl_pp_runcv(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rv2av(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rv2cv(pTHX);
 PERL_CALLCONV OP *     Perl_pp_rv2gv(pTHX);
diff --git a/regen/keywords.pl b/regen/keywords.pl
index 381e098..b19f2b1 100755
--- a/regen/keywords.pl
+++ b/regen/keywords.pl
@​@​ -64,6 +64,7 @​@​ NULL
 __FILE__
 __LINE__
 __PACKAGE__
+__SUB__
 __DATA__
 __END__
 AUTOLOAD
diff --git a/regen/opcode.pl b/regen/opcode.pl
index bd3d55a..84d8b69 100755
--- a/regen/opcode.pl
+++ b/regen/opcode.pl
@​@​ -1106,3 +1106,5 @​@​ rvalues           values on reference                     ck_each         t%      S

 # y///r
 transr         transliteration (tr///) ck_match        is"     S
+
+runcv          __SUB__                 ck_null         s0
diff --git a/toke.c b/toke.c
index ef14c18..e750ee0 100644
--- a/toke.c
+++ b/toke.c
@​@​ -6898,6 +6898,10 @​@​ Perl_yylex(pTHX)
                                        : &PL_sv_undef));
           TERM(THING);

+       case KEY___SUB__​:
+           pl_yylval.opval = (OP*)newOP(OP_RUNCV, 0);
+           TERM(THING);
+
       case KEY___DATA__​:
       case KEY___END__​: {
           GV *gv;
@​@​ -10289,7 +10293,7 @​@​ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords)
          goto unknown;
      }

-    case 7​: /* 29 tokens of length 7 */
+    case 7​: /* 30 tokens of length 7 */
      switch (name[0])
      {
        case 'D'​:
@​@​ -10306,14 +10310,35 @​@​ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords)
          goto unknown;

        case '_'​:
-          if (name[1] == '_' &&
-              name[2] == 'E' &&
-              name[3] == 'N' &&
-              name[4] == 'D' &&
-              name[5] == '_' &&
-              name[6] == '_')
-          {                                       /* __END__    */
-            return KEY___END__;
+          if (name[1] == '_')
+          {
+            switch (name[2])
+            {
+              case 'E'​:
+                if (name[3] == 'N' &&
+                    name[4] == 'D' &&
+                    name[5] == '_' &&
+                    name[6] == '_')
+                {                                 /* __END__          */
+                  return KEY___END__;
+                }
+
+                goto unknown;
+
+              case 'S'​:
+                if (name[3] == 'U' &&
+                    name[4] == 'B' &&
+                    name[5] == '_' &&
+                    name[6] == '_')
+                {                                 /* __SUB__          */
+                  return -KEY___SUB__;
+                }
+
+                goto unknown;
+
+              default​:
+                goto unknown;
+            }
          }

          goto unknown;

I long ago suggested this, but recommended it be associated to a variable​: $^SUB

And in fact rafael put a nearly complete module on cpan for this.

But i would love to see this added to the language.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 10​:26, demerphq <demerphq@​gmail.com> wrote​:

On 12 December 2010 21​:26, Father Chrysostomos
[snip]

The really neat thing, which I realised only after writing it, is that it allows for recursive closures to be written much more simply​:

And this was exactly the reason i recommended a $^SUB "tied" variable
for this purpose. Again, great idea. ++ to you.

Perhaps if the back compat police dislike __SUB__ you can make it work
with $^SUB.

cheers,
Yves

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 10​:29, demerphq <demerphq@​gmail.com> wrote​:

On 13 December 2010 10​:26, demerphq <demerphq@​gmail.com> wrote​:

On 12 December 2010 21​:26, Father Chrysostomos
[snip]

The really neat thing, which I realised only after writing it, is that it allows for recursive closures to be written much more simply​:

And this was exactly the reason i recommended a $^SUB "tied" variable
for this purpose. Again, great idea. ++ to you.

Perhaps if the back compat police dislike __SUB__ you can make it work
with $^SUB.

For the record​: I originally proposed it be called ${^THIS_SUB} (which
IS reserved - and special by nature iirc) in

Message-ID​: <9b18b3110706261235y5ea26d9w516e8444b293c32d@​mail.gmail.com>
Date​: Tue, 26 Jun 2007 21​:35​:26 +0200
From​: demerphq <demerphq@​gmail.com>
To​: p5p <perl5-porters@​perl.org>
Subject​: What about a ${^THIS_SUB} variable?

In that thread Rafael replied with the module Sub​::Current on cpan
where it is exported as ROUTINE()

http​://search.cpan.org/~rgarcia/Sub-Current-0.02/lib/Sub/Current.pm

It was also discussed in a number or other threads.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @Abigail

On Mon, Dec 13, 2010 at 09​:07​:00AM +0100, Johan Vromans wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

Because the latter doesn't work?

  $ perl -wE '$f = sub {say "Hello"; (caller (0)) [3] -> () if @​_}; $f -> (1)'
  Hello
  Undefined subroutine &main​::__ANON__ called at -e line 1.
  $

(caller (0)) [3] requires an entry in the symbol table - which not every
sub has.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 10​:42, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 09​:07​:00AM +0100, Johan Vromans wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

Because the latter doesn't work?

 $ perl -wE '$f = sub {say "Hello"; (caller (0)) [3] -> () if @​_}; $f -> (1)'
 Hello
 Undefined subroutine &main​::__ANON__ called at -e line 1.
 $

(caller (0)) [3] requires an entry in the symbol table - which not every
sub has.

Right. __SUB__ would have to resolve as a coderef, otherwise the point
FC made about recursive closures would be lost.

The whole idea is to have a non-refcount incremented identifier that
resolves to a reference to the currently executing subroutine.

Its principle advantage would be that it would allow us to have
recursive closures without the incredibly ugly hack workaround that is
required to use such a thing without memory leaks, and which almost
nobody knows how to do right.

Johan​: do *you* know how to create a recursive closure that does not
involve a memory leak or flushing the subname/method cache? Even if
you do, how many other programmers do you think know the recipe?

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 09​:07, Johan Vromans <jvromans@​squirrel.nl> wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @sciurius

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @Abigail

On Mon, Dec 13, 2010 at 11​:32​:45AM +0100, Johan Vromans wrote​:

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

I wouldn't say __END__ and __DATA__ (probably the most well-known, and
certainly the most used __XXX__ thingies) are "compile-time constants".

So, I don't really buy the "__SUB__ confuses me, because it isn't a
compile-time constant" argument.

__XXX__ things I know about, in order how often I see it used in code​:

__END__​: Special token
__DATA__​: Special token
__WARN__​: Special literal for %SIG
__DIE__​: Special literal for %SIG

<huge gap>

__FILE__​: Compile-time constant
__LINE__​: Compile-time constant

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me. But __SUB__ doesn't shout "compile-time constant"
to me. (What constant should it possibly be?)

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 11​:42, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 11​:32​:45AM +0100, Johan Vromans wrote​:

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

I wouldn't say __END__ and __DATA__ (probably the most well-known, and
certainly the most used __XXX__ thingies) are "compile-time constants".

So, I don't really buy the "__SUB__ confuses me, because it isn't a
compile-time constant" argument.

__XXX__ things I know about, in order how often I see it used in code​:

__END__​:   Special token
__DATA__​:  Special token
__WARN__​:  Special literal for %SIG
__DIE__​:   Special literal for %SIG

<huge gap>

__FILE__​:  Compile-time constant
__LINE__​:  Compile-time constant

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me. But __SUB__ doesn't shout "compile-time constant"
to me. (What constant should it possibly be?)

I think johan meant it in the sense that you dont expect to be able to
localize, or assign to an __IDENTIFIER__, which fits the use case for
this feature.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @sciurius

[Quoting demerphq, on December 13 2010, 12​:33, in "Re​: [perl #80628] [P"]

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me.

I tend to agree, even with $SUB (cf. $ARGV), but $^SUB has the correct
amount of magic smell.

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @Abigail

On Mon, Dec 13, 2010 at 12​:33​:24PM +0100, demerphq wrote​:

On 13 December 2010 11​:42, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 11​:32​:45AM +0100, Johan Vromans wrote​:

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

I wouldn't say __END__ and __DATA__ (probably the most well-known, and
certainly the most used __XXX__ thingies) are "compile-time constants".

So, I don't really buy the "__SUB__ confuses me, because it isn't a
compile-time constant" argument.

__XXX__ things I know about, in order how often I see it used in code​:

__END__​:   Special token
__DATA__​:  Special token
__WARN__​:  Special literal for %SIG
__DIE__​:   Special literal for %SIG

<huge gap>

__FILE__​:  Compile-time constant
__LINE__​:  Compile-time constant

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me. But __SUB__ doesn't shout "compile-time constant"
to me. (What constant should it possibly be?)

I think johan meant it in the sense that you dont expect to be able to
localize, or assign to an __IDENTIFIER__, which fits the use case for
this feature.

Good point.

But that, IMO, would favour __SUB__ over $^SUB. The latter may give the
suggestion you can assign to it, or localize, while "the current sub"
isn't something I associate with as assignable from Perl land.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 13​:04, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 12​:33​:24PM +0100, demerphq wrote​:

On 13 December 2010 11​:42, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 11​:32​:45AM +0100, Johan Vromans wrote​:

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

I wouldn't say __END__ and __DATA__ (probably the most well-known, and
certainly the most used __XXX__ thingies) are "compile-time constants".

So, I don't really buy the "__SUB__ confuses me, because it isn't a
compile-time constant" argument.

__XXX__ things I know about, in order how often I see it used in code​:

__END__​:   Special token
__DATA__​:  Special token
__WARN__​:  Special literal for %SIG
__DIE__​:   Special literal for %SIG

<huge gap>

__FILE__​:  Compile-time constant
__LINE__​:  Compile-time constant

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me. But __SUB__ doesn't shout "compile-time constant"
to me. (What constant should it possibly be?)

I think johan meant it in the sense that you dont expect to be able to
localize, or assign to an __IDENTIFIER__, which fits the use case for
this feature.

Good point.

But that, IMO, would favour __SUB__ over $^SUB. The latter may give the
suggestion you can assign to it, or localize, while "the current sub"
isn't something I associate with as assignable from Perl land.

Yes right. I'm happy with FC's patch, and would like to see it go in.

The only that might be odd with it is that it would return a ref, and
the other things return simple scalar values.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From zefram@fysh.org

demerphq wrote​:

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

A variable is a poor model for this. I think it's best accessed via
something that looks like a function call. __SUB__ would be fine,
except for the convention of __FOO__ denoting a compile-time constant.
A current_sub() function interface would be my preference. This can
be very easily implemented in an XS module, generating a custom op.
Something like​:

  static OP *
  pp_current_sub(pTHX)
  {
  dSP;
  XPUSHs(cxstack[cxstack_ix].blk_sub.cv);
  RETURN;
  }

  static OP *
  THX_ck_entersub_current_sub(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
  {
  OP *o;
  ck_entersub_args_proto(entersubop, namegv, ckobj);
  op_free(entersubop);
  /* I haven't learned how to use the new custom-op stuff yet */
  o = newOP(OP_PUSHMARK, 0);
  o->op_type = OP_RAND;
  o->op_ppaddr = pp_current_sub;
  return o;
  }

  BOOT​:
  {
  CV *cscv = get_cv("Acme​::CurrentSub​::current_sub", 0);
  cv_set_call_checker(cscv, THX_ck_entersub_current_sub, (SV*)cscv);
  }

  void
  current_sub(...)
  PROTOTYPE​:
  CODE​:
  PERL_UNUSED_VAR(items);
  croak("current_sub called as a function");

With a little more work, this can be backported to older Perl versions
that don't have cv_set_call_checker().

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From zefram@fysh.org

I wrote​:

XPUSHs(cxstack[cxstack_ix].blk_sub.cv);

Trying again​:

  XPUSHs(sv_2mortal(newRV_noinc((SV*)cxstack[cxstack_ix].blk_sub.cv)));

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @Abigail

On Mon, Dec 13, 2010 at 01​:38​:02PM +0100, demerphq wrote​:

On 13 December 2010 13​:04, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 12​:33​:24PM +0100, demerphq wrote​:

On 13 December 2010 11​:42, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 11​:32​:45AM +0100, Johan Vromans wrote​:

[Quoting demerphq, on December 13 2010, 10​:48, in "Re​: [perl #80628] [P"]

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

Sounds like a very good idea to me.

My main objection against __SUB__ is that __XXX__ things are currently
compile time constants, hence we must avoid introducing __XXX__ things
that are not. It doesn't contribute to Perl's popularity.

I wouldn't say __END__ and __DATA__ (probably the most well-known, and
certainly the most used __XXX__ thingies) are "compile-time constants".

So, I don't really buy the "__SUB__ confuses me, because it isn't a
compile-time constant" argument.

__XXX__ things I know about, in order how often I see it used in code​:

__END__​:   Special token
__DATA__​:  Special token
__WARN__​:  Special literal for %SIG
__DIE__​:   Special literal for %SIG

<huge gap>

I forgot one here​:

  __PACKAGE__​: Compile-time constant

__FILE__​:  Compile-time constant
__LINE__​:  Compile-time constant

Now, I'd prefer a short token, and I certainly don't mind having a variable,
so $^SUB now wins for me. But __SUB__ doesn't shout "compile-time constant"
to me. (What constant should it possibly be?)

I think johan meant it in the sense that you dont expect to be able to
localize, or assign to an __IDENTIFIER__, which fits the use case for
this feature.

Good point.

But that, IMO, would favour __SUB__ over $^SUB. The latter may give the
suggestion you can assign to it, or localize, while "the current sub"
isn't something I associate with as assignable from Perl land.

Yes right. I'm happy with FC's patch, and would like to see it go in.

The only that might be odd with it is that it would return a ref, and
the other things return simple scalar values.

Yes, but people do write "__PACKAGE__ -> ... ()" without being freaked
out. "__SUB__ -> ()" isn't visually that much different, even if one
returns a string, the other a code ref. For a typical use, the user
does not have to care.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 13​:59, Zefram <zefram@​fysh.org> wrote​:

demerphq wrote​:

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

A variable is a poor model for this.  I think it's best accessed via
something that looks like a function call.  __SUB__ would be fine,
except for the convention of __FOO__ denoting a compile-time constant.

Yes. But I think people can deal with that, it isnt much different
from __PACKAGE__.

A current_sub() function interface would be my preference.  This can
be very easily implemented in an XS module, generating a custom op.
Something like​:

That is done by Rafael in Sub​::Current. He uses ROUTINE() for this purpose.

Yves.

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @lizmat

On Dec 13, 2010, at 5​:05 PM, demerphq wrote​:

On 13 December 2010 13​:59, Zefram <zefram@​fysh.org> wrote​:

demerphq wrote​:

This is why i proposed using a $^THIS_SUB "magic tied var" for the purpose.

A variable is a poor model for this. I think it's best accessed via
something that looks like a function call. __SUB__ would be fine,
except for the convention of __FOO__ denoting a compile-time constant.

Yes. But I think people can deal with that, it isnt much different
from __PACKAGE__.

Please note that __PACKAGE__ and __LINE__ are settable nonetheless, using #line and -package- .

A current_sub() function interface would be my preference. This can
be very easily implemented in an XS module, generating a custom op.
Something like​:
That is done by Rafael in Sub​::Current. He uses ROUTINE() for this purpose.

FWIW, $^SUB feels more natural to me.

Liz

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @ikegami

On Mon, Dec 13, 2010 at 3​:07 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl>
wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

caller[3] doesn't work for anon subs.

perl -E"sub { say( (caller(0))[3] ) }->()"
main​::__ANON__

It was specifically proposed that __SUB__ would return a reference in at
least that case.

It's more like SUPER than __FILE__ in a sense. Maybe something without
dashes would be more appropriate.

- Eric

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 17​:09, Eric Brine <ikegami@​adaelis.com> wrote​:

On Mon, Dec 13, 2010 at 3​:07 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl>
wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

caller[3] doesn't work for anon subs.

perl -E"sub { say( (caller(0))[3] ) }->()"
main​::__ANON__

It was specifically proposed that __SUB__ would return a reference in at
least that case.

It seen's to me that it MUST return a reference in ALL situations.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 12 December 2010 21​:26, Father Chrysostomos
<perlbug-followup@​perl.org> wrote​:

# New Ticket Created by  Father Chrysostomos
# Please include the string​:  [perl #80628]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=80628 >

This patch adds a __SUB__ keyword that returns the current subroutine, or undef for the main program, a special block, or an eval.

If there are no objections, I will add docs and push this shortly before 5.13.8.

I first thought of adding this to make recursive lexicals subs easier to write (whenever they are added)​:

my sub foo { __SUB__->() }

my sub foo;  # the alternative
my sub foo { foo() }

The really neat thing, which I realised only after writing it, is that it allows for recursive closures to be written much more simply​:

sub make_recursive_function {
 my $arg = shift;
 sub {
   print "$_[0]\n";
   __SUB__->($_[0] + 1) if $_[0] < $arg;
 }
}

as opposed to​:

use Scalar​::Util;
sub make_recursive_function {
 my $arg = shift;
 my $sub;
 my $life_raft = $sub = sub {
   print "$_[0]\n";
   &$sub($_[0] + 1) if $_[0] < $arg;
 }
 Scalar​::Util​::weaken($sub);
 $sub;
}

And this demonstrates why the patch would be useful.

Even FC got the recipe wrong. :-)

It should return $life_raft, not $sub, otherwise $sub will be a "dead
weakref", and the sub freed by the time this code exits.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 17​:33, Zefram <zefram@​fysh.org> wrote​:

Given that (a) there are already multiple versions of this on CPAN,
(b) there are competing versions of the semantics, and (c) it's easy
to implement a new version on CPAN where the existing versions don't
provide the desired semantics, it seems to me that the right place for
this isn't the core, it's CPAN.

Personally I think that Scalar​::Util, Data​::Alias and friends taught
us the lesson that the above are poor justifications to argue that
something should be on CPAN or be part of core.

The reasons I see for putting it in core are​: a) it needs XS to be
implemented, b) the XS would be maintained by the core dev team, c) by
putting it in core we guarantee to our users that a very useful
feature will always be available in perls following it, d) it replaces
an extremely awkward recipe that involves a module (Scalar​::Util) that
after much debate and gnashing of teeth pretty much all agreed should
have been in core in the first place - repeating such an error with a
replacement for one of Scalar​::Utils routines seems most illogical.

With a CPAN module there is no contract between Perl and the community
that something will be reliably available.

A CPAN module on the other may fall out of sync with perl and be
abandoned by its author or otherwise go unsupported. We have seen this
with Data​::Alias.

We have also seen that in many environments it is anywhere from nearly
impossible to quite difficult to get non-standard modules installed at
all, let alone ones that require compiling XS code. We have seen both
of these problems with Scalar​::Util. (I have personal experience of
this one.)

This is a language feature that allows us to do something that is
definitely non-trivial, useful, and likely to be widely adopted. It
should BE part of the language, not a nice-to-have after market
bolt-on.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 17​:47, Abigail <abigail@​abigail.be> wrote​:

On Mon, Dec 13, 2010 at 05​:26​:29PM +0100, demerphq wrote​:

On 13 December 2010 17​:09, Eric Brine <ikegami@​adaelis.com> wrote​:

On Mon, Dec 13, 2010 at 3​:07 AM, Johan Vromans <jvromans@​squirrel.nl> wrote​:

[Quoting Eric Brine, on December 13 2010, 02​:51, in "Re​: [perl #80628] [P"]

On Mon, Dec 13, 2010 at 2​:09 AM, Johan Vromans <jvromans@​squirrel.nl>
wrote​:

More important is whether it is a keyword, or a compile time constant
like __FILE__ and __LINE__.

-- Johan

As proposed, it's not constant.

Then please do not call it __SUB__.

What would be the difference with (caller(0))[3] ?

caller[3] doesn't work for anon subs.

perl -E"sub { say( (caller(0))[3] ) }->()"
main​::__ANON__

It was specifically proposed that __SUB__ would return a reference in at
least that case.

It seen's to me that it MUST return a reference in ALL situations.

I agree. Do one thing in one case, and another in another case doesn't seem
like a win situation to me. At least, not here. You certainly shouldn't
have to change the body of a sub if you change it from an anon sub to a
named one.

And the fact that it not returning a reference would almost certainly
lead to bugs.

For instance the same kind of problem we see here​:

$ perl -MCarp -le'sub foo { confess "foo" } sub baz { confess "baz" }
*bar=&foo; *foo=&baz; bar()'
foo at -e line 1
  main​::foo called at -e line 1

If we returned anything but a code reference I reckon one could cook
up something like this to cause a bunch of edge-case insanity.
(Consider how much worse it gets when you add localized subroutines to
the mix...)

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @obra

I'd rather this functionality live on CPAN until there's a clear consensus that it
should be in core and about what it should be named.

On Mon, Dec 13, 2010 at 05​:35​:45PM +0100, Florian Ragwitz wrote​:

Zefram <zefram@​fysh.org> writes​:

Given that (a) there are already multiple versions of this on CPAN,
(b) there are competing versions of the semantics, and (c) it's easy
to implement a new version on CPAN where the existing versions don't
provide the desired semantics, it seems to me that the right place for
this isn't the core, it's CPAN.

+1

--

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @demerphq

On 13 December 2010 21​:17, Jesse Vincent <jesse@​fsck.com> wrote​:

I'd rather this functionality live on CPAN until there's a clear consensus that it
should be in core and about what it should be named.

Jesse noted to me in IRC that this is due to the upcoming code freeze,
which makes a lot of sense.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2010

From @obra

On Mon, Dec 13, 2010 at 03​:17​:11PM -0500, Jesse Vincent wrote​:

I'd rather this functionality live on CPAN until there's a clear consensus that it
should be in core and about what it should be named.

I somewhat misphrased this - We're very close to the
contentious-feature-freeze for 5.14. And this is clearly contentious.
I'd much rather it get better sorted out before we take it into blead.
To me, it makes sense that it get beaten around a bit before we think
about the eventual result for 5.16.

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2010

From @nwc10

On Mon, Dec 13, 2010 at 07​:03​:32PM +0100, demerphq wrote​:

We have also seen that in many environments it is anywhere from nearly
impossible to quite difficult to get non-standard modules installed at
all, let alone ones that require compiling XS code. We have seen both
of these problems with Scalar​::Util. (I have personal experience of
this one.)

You're proposing a technical fix to a political problem.

We can't include all of CPAN in the core just because other people wish
to externalize the costs of resolve their issues.

This is one of my hot buttons and I will argue against it until I am driven
away from Perl 5.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2010

From @demerphq

On 14 December 2010 18​:10, Nicholas Clark <nick@​ccl4.org> wrote​:

On Mon, Dec 13, 2010 at 07​:03​:32PM +0100, demerphq wrote​:

We have also seen that in many environments it is anywhere from nearly
impossible to quite difficult to get non-standard modules installed at
all, let alone ones that require compiling XS code. We have seen both
of these problems with Scalar​::Util. (I have personal experience of
this one.)

You're proposing a technical fix to a political problem.

On one level yes, on another level no. Its a technical problem that it
is quite difficult to make recursive closures. The existing technical
solution for doing so is pretty sad. The proiposed solution is vaslty
superior. So why should Perl essentially endorse the shit one and then
say "but the best way you need to install extra modules"

On the other hand yes, we have devs in our community who work in
environments that can be quite restrictive. Your position basically
amounts to saying that you don't care about their opinion or needs. I
dont think that is the way our community should work and I definitely
dont think it is a productive attitude.

We can't include all of CPAN in the core just because other people wish
to externalize the costs of resolve their issues.

This is a straw man argument. Nobody is arguing about including all of CPAN.

We are arguing about including critical XS code that cannot reasonably
be simulated in Perl code and which serves a function which
essentially cannot be implemented without XS.

This doesn't apply to pure perl as there is always a workaround in
that a user can always just C&P the code into their own code base if
necessary -- effectively fork the perl code.

This DOES NOT apply to XS code. And even with XS code its not like
anyone is arguing that this applies to a lot code, but rather to a
critical select few pieces that arguably should have been in perl from
the beginning.

This is one of my hot buttons and I will argue against it until I am driven
away from Perl 5.

I don't really like the threat here Nicholas, especially given it is
in regard to a position that nobody has taken.

If you really have a good argument for why this idea shouldn't move
forward then post it, but this line about including all of cpan is
just bogus. Bring it up when somebody actually makes that argument ok?

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 15, 2010

From @leonerd

On Mon, Dec 13, 2010 at 10​:47​:01AM +0100, demerphq wrote​:

The whole idea is to have a non-refcount incremented identifier that
resolves to a reference to the currently executing subroutine.

use CPS qw( kwhile );

kwhile(
  sub { my ( $knext ) = @​_;
  .....

  $knext->()
  }
);

HTH,

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http​://www.leonerd.org.uk/

@p5pRT
Copy link
Author

p5pRT commented Dec 15, 2010

From @leonerd

On Mon, Dec 13, 2010 at 04​:33​:19PM +0000, Zefram wrote​:

Given that (a) there are already multiple versions of this on CPAN,
(b) there are competing versions of the semantics, and (c) it's easy
to implement a new version on CPAN where the existing versions don't
provide the desired semantics, it seems to me that the right place for
this isn't the core, it's CPAN.

+1

First off, there's callee

  http​://search.cpan.org/~marcel/callee-1.100820/lib/callee.pm

Secondly, if you want it for the purpose of recursive functions, try CPS

  http​://search.cpan.org/~pevans/CPS-0.10/lib/CPS.pm

  use CPS qw( kwhile );

  kwhile(
  sub { my ( $knext ) = @​_;
  ....

  $knext->();
  }
  );

It also includes some added magic to not blow up the stack if you call
it "synchronously", it turns into a real tailcall implemented by a while
loop, so the stack doesn't get consumed. Ofcourse you can also store the
$knext closure somewhere else to invoke later.

CPS is pure-perl.

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http​://www.leonerd.org.uk/

@p5pRT
Copy link
Author

p5pRT commented Dec 15, 2010

From zefram@fysh.org

demerphq wrote​:

The whole idea is to have a non-refcount incremented identifier that
resolves to a reference to the currently executing subroutine.

This can actually be achieved without either a statically self-referential
function definition (requiring weak refs) or grubbing around in the
runtime stack. Behold, the non-recursive definition of the recursive
implementation of factorial​:

  my $w = sub { my($v, $x) = @​_;
  sub { $x->(sub { $v->($v, $x)->(@​_) }, @​_) } };
  my $y = sub { $w->($w, $_[0]) };

  my $factorial =
  $y->(sub { $_[1] == 0 ? 1 : $_[1] * $_[0]->($_[1] - 1) });

  print $factorial->(5), "\n";

This technique can be extended to arbitrarily many mutually-recursive
functions, an area where __SUB__/${^SUB} falls down.

(Thanks to LeoNerd for inspiring me to go in a theoretical direction.)

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @cpansprout

On Mon Dec 13 13​:35​:19 2010, jesse wrote​:

On Mon, Dec 13, 2010 at 03​:17​:11PM -0500, Jesse Vincent wrote​:

I'd rather this functionality live on CPAN until there's a clear
consensus that it
should be in core and about what it should be named.

I somewhat misphrased this - We're very close to the
contentious-feature-freeze for 5.14. And this is clearly contentious.
I'd much rather it get better sorted out before we take it into blead.
To me, it makes sense that it get beaten around a bit before we think
about the eventual result for 5.16.

OK, now that we’re past that, let me address some objections that came up​:

1) That __SUB__ is not a compile-time constant like its predecessors.

That __PACKAGE__ and __LINE__ are compile-time constants is an
implementation detail.
__PACKAGE__’s being a compile-time directive actually causes a bug in
some edge cases, so that is not set in stone.
__SUB__ *can* be a compile-time constant in subroutines that do not
close over variables. That optimisation just hasn’t been written yet.

2) That this should be a CPAN module, not part of core.

One reason I think we should have this in core is that JavaScript
supports it (arguments.callee), which makes Perl look bad.

And the symmetry with package/__PACKAGE__ is nice​:
package foo { ... my $pack = __PACKAGE__ ... }
sub foo { ... my $sub = __SUB__ ... }

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @sciurius

"Father Chrysostomos via RT" <perlbug-followup@​perl.org> writes​:

1) That __SUB__ is not a compile-time constant like its predecessors.
...
And the symmetry with package/__PACKAGE__ is nice​:
package foo { ... my $pack = __PACKAGE__ ... }
sub foo { ... my $sub = __SUB__ ... }

I revert my former objections. You have my blessing.

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @sciurius

"Father Chrysostomos via RT" <perlbug-followup@​perl.org> writes​:

2) That this should be a CPAN module, not part of core.

Some finetuning.

1. CPAN module means​: a bunch of Perl and XS (if necessary) that can be
  added to a suitable Perl distribution. Note that building and
  installing modules, especially if they involve XS code, is not always
  trivial.

  Programs need to 'use' Some​::Thing to use it.

2. Core means​: it's there and works with this and all future Perl
  distributions.

2a. It can still be a module; 'use' Some​::Thing is required.
  Always safe.

2b. It can be a feature; 'use feature' or equivalent is required.
  If it could break existing code.

2c. It can be built-in. It's just there.
  Only if it cannot break existing code.

Technically, anything new can be implemented in any of the above ways.
Which of the ways it will end up is sometimes technical (e.g., another
piece of Core wants to use it) but mostly political (i.e., the powers in
charge like it).

Considering all this, I'd vote for __SUB__ to fall in category 2c.

-- Johan

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @xdg

On Mon, Dec 13, 2010 at 7​:04 AM, Abigail <abigail@​abigail.be> wrote​:

But that, IMO, would favour __SUB__ over $^SUB. The latter may give the
suggestion you can assign to it, or localize, while "the current sub"
isn't something I associate with as assignable from Perl land.

+1

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From zefram@fysh.org

Since a satisfactorily functional version of __SUB__ already exists
on CPAN, in the form of Sub​::Current, it appears to me that we should
be thinking in terms of developing Sub​::Current, rather than building
something new in the core. Sub​::Current provides an established interface
for invoking this feature, and it is an interface that causes absolutely
no complication around feature flags and Perl-version portability.

The specific name "__SUB__" can easily be added to Sub​::Current alongside
its existing "ROUTINE" (*__SUB__ = \&ROUTINE). Its performance can
also be improved within the confines of the module format​: it can use
cv_set_call_checker and a custom op, along the lines of the rough version
that I posted upthread, to reduce the cost of __SUB__ execution from a
sub call to a single op.

If this feature is important enough that it ought to be available to
users who don't have a compiler, or if we really need to be able to tick
a box on a comparison chart that says this feature is "included in Perl",
then we should dual-life Sub​::Current. We can thus get the installation
and maintenance characteristics of the core without requiring a new
interface or any of the other complications of a true built-in.

I'm happy to help tweak the Sub​::Current implementation. I'm neutral
on whether it should be dual-lifed. I'm -1 on turning any equivalent
of it into a core built-in.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @ap

* Zefram <zefram@​fysh.org> [2011-06-13 21​:25]​:

I'm happy to help tweak the Sub​::Current implementation. I'm
neutral on whether it should be dual-lifed. I'm -1 on turning
any equivalent of it into a core built-in.

I’d prefer any solution that doesn’t require `use Sub​::Current`
any time a user wants to employ the functionality. If you have
a proposal for doing so within the confines of Sub​::Current, then
we agree.

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From zefram@fysh.org

Aristotle Pagaltzis wrote​:

I???d prefer any solution that doesn???t require `use Sub​::Current`
any time a user wants to employ the functionality.

You just need to write this package once to define your preferred
feature mix​:

  package BeLike​::Aristotle;
  sub import {
  require 5.008;
  require strict;
  "strict"->import;
  require warnings;
  "warnings"->import;
  require feature;
  "feature"->import("switch");
  require Sub​::Current;
  *{caller."​::__SUB__"} = \&Sub​::Current​::ROUTINE;
  # et cetera
  }

Then you can get all the features you like in one declaration​:

  use BeLike​::Aristotle;

  sub factorial { $_[0] == 0 ? 1 : $_[0] * __SUB__->($_[0] - 1) }

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From @xdg

On Mon, Jun 13, 2011 at 3​:24 PM, Zefram <zefram@​fysh.org> wrote​:

The specific name "__SUB__" can easily be added to Sub​::Current alongside
its existing "ROUTINE" (*__SUB__ = \&ROUTINE).  Its performance can
also be improved within the confines of the module format​: it can use
cv_set_call_checker and a custom op, along the lines of the rough version
that I posted upthread, to reduce the cost of __SUB__ execution from a
sub call to a single op.

One thing i like about a built-in __SUB__ is that it doesn't pollute
the current package namespace.

If this feature is important enough that it ought to be available to
users who don't have a compiler, or if we really need to be able to tick
a box on a comparison chart that says this feature is "included in Perl",
then we should dual-life Sub​::Current.  We can thus get the installation
and maintenance characteristics of the core without requiring a new
interface or any of the other complications of a true built-in.

What do you see as the "complications"?

-- David

@p5pRT
Copy link
Author

p5pRT commented Jun 13, 2011

From zefram@fysh.org

David Golden wrote​:

One thing i like about a built-in __SUB__ is that it doesn't pollute
the current package namespace.

I like that too, so much that I modularised it​:

  use Sub​::Current ();
  use Lexical​::Sub __SUB__ => \&Sub​::Current​::ROUTINE;

or, if the name supplied by the module is OK​:

  use Lexical​::Import "Sub​::Current";

or combining it with Aristotle's issue​:

  sub BeLike​::Aristotle​::import {
  # ...
  require Lexical​::Import;
  Lexical​::Import->import("Sub​::Current");
  }

What do you see as the "complications"?

Version portability is a biggie​: Sub​::Current is available on any Perl
from 5.8.1 onwards, in principle available on any Perl where the core
can actually support it, but a new builtin would be by its nature
only available from when we decided to core it. (Lexical​::Import
only works from 5.11.2, but that's still better than a new keyword.)
Keyword features also don't play nicely with namespaces​: I've shown
that Sub​::Current's ROUTINE can be easily renamed to __SUB__ if we
want, but you can't similarly rename __PACKAGE__ to PARCEL. Generally
keyword-based builtins lose a bit from not being reified, which in time
I'd like to rectify.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2011

From @tsee

Hi Zefram, hi all,

On 06/13/2011 10​:54 PM, Zefram wrote​:

David Golden wrote​:

One thing i like about a built-in __SUB__ is that it doesn't pollute
the current package namespace.

I like that too, so much that I modularised it​:

use Sub&#8203;::Current \(\);
use Lexical&#8203;::Sub \_\_SUB\_\_ =>  \\&Sub&#8203;::Current&#8203;::ROUTINE;

or, if the name supplied by the module is OK​:

use Lexical&#8203;::Import "Sub&#8203;::Current";

or combining it with Aristotle's issue​:

sub BeLike&#8203;::Aristotle&#8203;::import \{
    \# \.\.\.
    require Lexical&#8203;::Import;
    Lexical&#8203;::Import\->import\("Sub&#8203;::Current"\);
\}

What do you see as the "complications"?

Version portability is a biggie​:
[...]

I strongly disagree. Adding new features to new versions of software is
very much common practice. Why backporting functionality isn't entirely
discouraged. It bothers me very much that it can possibly stand in the
way of progress in the core language.

__SUB__ should be part of the core (and NOT require a module load) as
far as I am concerned.

By the way​: Those loader bundles are a nightmare in practice. Quite
frankly, I'm surprised that isn't obvious to you. Consider what happens
in an environment of many developers cooperating. There lies madness.

Best regards,
Steffen

@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2011

From @Tux

On Tue, 14 Jun 2011 08​:15​:39 +0200, Steffen Mueller <smueller@​cpan.org>
wrote​:

I strongly disagree. Adding new features to new versions of software is
very much common practice. Why backporting functionality isn't entirely
discouraged. It bothers me very much that it can possibly stand in the
way of progress in the core language.

__SUB__ should be part of the core (and NOT require a module load) as
far as I am concerned.

+1

--
H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/
using 5.00307 through 5.14 and porting perl5.15.x on HP-UX 10.20, 11.00,
11.11, 11.23 and 11.31, OpenSuSE 10.1, 11.0 .. 11.4 and AIX 5.2 and 5.3.
http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/
http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2011

From @khwilliamson

On 06/14/2011 01​:26 AM, H.Merijn Brand wrote​:

On Tue, 14 Jun 2011 08​:15​:39 +0200, Steffen Mueller<smueller@​cpan.org>
wrote​:

I strongly disagree. Adding new features to new versions of software is
very much common practice. Why backporting functionality isn't entirely
discouraged. It bothers me very much that it can possibly stand in the
way of progress in the core language.

__SUB__ should be part of the core (and NOT require a module load) as
far as I am concerned.

+1

+1

@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2011

From @xdg

On Tue, Jun 14, 2011 at 10​:57 AM, Karl Williamson
<public@​khwilliamson.com> wrote​:

On 06/14/2011 01​:26 AM, H.Merijn Brand wrote​:

On Tue, 14 Jun 2011 08​:15​:39 +0200, Steffen Mueller<smueller@​cpan.org>
wrote​:

I strongly disagree. Adding new features to new versions of software is
very much common practice. Why backporting functionality isn't entirely
discouraged. It bothers me very much that it can possibly stand in the
way of progress in the core language.

__SUB__ should be part of the core (and NOT require a module load) as
far as I am concerned.

+1

+1

+1

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2011

From @cpansprout

On Mon Jun 13 13​:55​:12 2011, zefram@​fysh.org wrote​:

Version portability is a biggie​: Sub​::Current is available on any Perl
from 5.8.1 onwards, in principle available on any Perl where the core
can actually support it, but a new builtin would be by its nature
only available from when we decided to core it. (Lexical​::Import
only works from 5.11.2, but that's still better than a new keyword.)
Keyword features also don't play nicely with namespaces​: I've shown
that Sub​::Current's ROUTINE can be easily renamed to __SUB__ if we
want, but you can't similarly rename __PACKAGE__ to PARCEL. Generally
keyword-based builtins lose a bit from not being reified, which in time
I'd like to rectify.

I’m already working on that. Is that sufficient to address your concern?

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2011

From [Unknown Contact. See original ticket]

On Mon Jun 13 13​:55​:12 2011, zefram@​fysh.org wrote​:

Version portability is a biggie​: Sub​::Current is available on any Perl
from 5.8.1 onwards, in principle available on any Perl where the core
can actually support it, but a new builtin would be by its nature
only available from when we decided to core it. (Lexical​::Import
only works from 5.11.2, but that's still better than a new keyword.)
Keyword features also don't play nicely with namespaces​: I've shown
that Sub​::Current's ROUTINE can be easily renamed to __SUB__ if we
want, but you can't similarly rename __PACKAGE__ to PARCEL. Generally
keyword-based builtins lose a bit from not being reified, which in time
I'd like to rectify.

I’m already working on that. Is that sufficient to address your concern?

@p5pRT
Copy link
Author

p5pRT commented Nov 22, 2011

From @cpansprout

Now in blead as 84ed010, but the final patch looks quite different.

@p5pRT
Copy link
Author

p5pRT commented Nov 22, 2011

@cpansprout - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant