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
sv_does is broken #10551
Comments
From ben@morrow.me.ukThe API function sv_does is broken, and has been since it was first The logic currently in Perl_sv_does for checking ->isa should be moved It might be useful to add a sv_perl_isa API, which does a proper Ben |
From @doyThe correct way to test for DOES (or isa, or can) is to just call the That said, I am kind of curious what the actual use for making sv_does a |
The RT System itself - Status changed from 'new' to 'open' |
From @demerphqOn 24 June 2012 03:22, Jesse Luehrs via RT <perlbug-followup@perl.org> wrote:
When does was introduced there was a lot of debate about whether it Now that is has been available in the wild for some time I it is clear Maybe I should get my patches together and we can get a DOES that does. Yves -- |
From chromatic@wgz.orgOn Saturday, June 23, 2012 06:22:34 PM Jesse Luehrs via RT wrote:
That seems sanest to me.
If I recall correctly, it only exists and is public because sv_isa exists and -- c |
From @cpansproutOn Sun Jun 24 09:50:04 2012, chromatic@wgz.org wrote:
UNIVERSAL::DOES is implemented in terms of sv_does, so we can’t ‘just’ -- Father Chrysostomos |
From @doyOn Sun, Jun 24, 2012 at 11:06:09AM -0700, Father Chrysostomos via RT wrote:
Yes, the implementation of UNIVERSAL::DOES is fine, the only confusing -doy |
From @tseeOn 06/24/2012 08:06 PM, Father Chrysostomos via RT wrote:
But we can move them to a section "for back-compat only" in perlapi.pod --Steffen |
From @sciuriusJesse Luehrs <doy@tozt.net> writes:
Last year we had a discussion about this. DOES, as it is implemented right now, is bogus and wrong. The "Perl does not have any built-in way to express roles. So there are no roles in Perl, but there are some CPAN modules that if (Role::Tiny::does_role($foo, 'Some::Role')) { And: if ($foo->does('Some::Role')) { So it does not even use, or advise to use, DOES. Neither does Moo. In I repeat from <m2mxiy48bv.fsf@phoenix.squirrel.nl> : [...] But since there's no documentation about roles people may use -- Johan |
From @demerphqOn 24 June 2012 21:57, Johan Vromans <jvromans@squirrel.nl> wrote:
It is savable IMO. I posted a patch at the time to make it useful. Thread is available here: http://www.nntp.perl.org/group/perl.perl5.porters/2007/03/msg122105.html cheers, -- |
From @demerphquniversal_does.patchIndex: embed.fnc
===================================================================
--- embed.fnc (revision 1199)
+++ embed.fnc (working copy)
@@ -829,7 +829,7 @@
Apd |void |sv_dec |NN SV* sv
Ap |void |sv_dump |NN SV* sv
ApdR |bool |sv_derived_from|NN SV* sv|NN const char* name
-ApdR |bool |sv_does |NN SV* sv|NN const char* name
+ApdR |bool |sv_does |NN SV* sv|NN const char* name|STRLEN namelen|U32 flags
Apd |I32 |sv_eq |NULLOK SV* sv1|NULLOK SV* sv2
Apd |void |sv_free |NULLOK SV* sv
poMX |void |sv_free2 |NN SV* sv
Index: lib/UNIVERSAL.pm
===================================================================
--- lib/UNIVERSAL.pm (revision 1199)
+++ lib/UNIVERSAL.pm (working copy)
@@ -32,6 +32,8 @@
$does_log = $obj->DOES("Logger");
$does_log = Class->DOES("Logger");
+ $does_log = UNIVERSAL::DOES($obj,"Logger");
+ $does_array = UNIVERSAL::DOES($obj,'@{}');
$sub = $obj->can("print");
$sub = Class->can("print");
@@ -105,6 +107,8 @@
=item C<< CLASS->DOES( ROLE ) >>
+=item C<< UNIVERSAL::DOES( $obj, ROLE ) >>
+
C<DOES> checks if the object or class performs the role C<ROLE>. A role is a
named group of specific behavior (often methods of particular names and
signatures), similar to a class, but not necessarily a complete class by
@@ -117,17 +121,44 @@
mandates an inheritance relationship. Other relationships include aggregation,
delegation, and mocking.)
-By default, classes in Perl only perform the C<UNIVERSAL> role. To mark that
-your own classes perform other roles, override C<DOES> appropriately.
+In addition to named classes that C<isa> support C<DOES> also provides a safe
+way to query whether an object can be used in certain ways. The special roles
+C<'${}'>, C<'%{}'>, C<'@{}'>, C<'&{}'> and C<'*{}'> can be used to safely
+determine if an object can be dereferenced in a given way, and the role
+C<'qr//'> can be used to check if the object will have special behaviour
+when used in a regex.
There is a relationship between roles and classes, as each class implies the
existence of a role of the same name. There is also a relationship between
inheritance and roles, in that a subclass that inherits from an ancestor class
implicitly performs any roles its parent performs. Thus you can use C<DOES> in
-place of C<isa> safely, as it will return true in all places where C<isa> will
-return true (provided that any overridden C<DOES> I<and> C<isa> methods behave
-appropriately).
+place of C<isa> on objects safely, as it will return true in all places where
+C<isa> will return true (provided that any overridden C<DOES> I<and> C<isa>
+methods behave appropriately).
+By default, classes in Perl perform the C<UNIVERSAL> role, objects are similar
+but additionally support the role associated to their implementations
+underlying type. To mark that your own classes perform other roles, override
+C<DOES> appropriately (keeping in mind the warning below). This is safe to do
+as even when UNIVERSAL::DOES() is called in subroutine form, and therefore
+bypassing inheritance, it will still delegate to the overriden method.
+
+B<WARNING:> the delegation behaviour of UNIVERSAL::DOES() means that if a
+custom DOES() method wishes to call the default method provided by UNIVERSAL,
+such as via C<$self->SUPER::DOES($role)> then it B<MUST> provide an additional
+true argument to the call to prevent infinite recursion, and even possibly
+crash perl. For instance the following is safe.
+
+ package Some::Class;
+ sub DOES {
+ my ($self,$role) = @_;
+ return 1 if $role=~/Foo|Bar/i;
+ return $self->SUPER::DOES($role,'no-delegate')
+ # or
+ #return UNIVERSAL::DOES($self,$role,$true_value)
+ }
+
+
=item C<< $obj->can( METHOD ) >>
=item C<< CLASS->can( METHOD ) >>
Index: t/op/universal.t
===================================================================
--- t/op/universal.t (revision 1199)
+++ t/op/universal.t (working copy)
@@ -10,7 +10,7 @@
require "./test.pl";
}
-plan tests => 110;
+plan tests => 130;
$a = {};
bless $a, "Bob";
@@ -210,13 +210,49 @@
package Baz;
+{
+ package OL;
+ use overload '@{}'=>sub{return []};
+ sub new { return bless {hahah=>1},shift @_ }
+}
+package Not::Deadly;
+# make sure that the no-delegate option to UNIVERSAL::ISA() works
+sub DOES { $_[0]->SUPER::DOES($_[1],'no-delegate') }
+package Really::Deadly;
+# this will go boom if its used, but we want to test that
+# the no-delegate option to UNIVERSAL::ISA() works.
+sub DOES { $_[0]->SUPER::DOES($_[1]) }
+
package main;
ok( Foo->DOES( 'bar' ), 'DOES() should call DOES() on class' );
ok( Bar->DOES( 'Bar' ), '... and should fall back to isa()' );
ok( Bar->DOES( 'Foo' ), '... even when inherited' );
ok( Baz->DOES( 'Baz' ), '... even without inheriting any other DOES()' );
ok( ! Baz->DOES( 'Foo' ), '... returning true or false appropriately' );
-
+{
+ my @bad=(bless(qr//,'CODE'),bless(sub{},'ARRAY'),
+ OL->new());
+ ok( UNIVERSAL::DOES($bad[0],'qr//'), 'DOES() can handle "qr//"');
+ ok( !UNIVERSAL::DOES($bad[1],'qr//'), 'DOES() can handle "qr//"');
+ ok( !UNIVERSAL::DOES($bad[0],'&{}'), 'DOES() can handle "&{}"');
+ ok( UNIVERSAL::DOES($bad[1],'&{}'), 'DOES() can handle "&{}"');
+ ok( !UNIVERSAL::DOES($bad[1],'@{}'), 'DOES() can handle "@{}"');
+ ok( UNIVERSAL::DOES($bad[0],'${}'), 'DOES() can handle "${}"');
+ ok( UNIVERSAL::DOES([],'@{}'), 'DOES() can handle "@{}"');
+ ok( UNIVERSAL::DOES([],'ARRAY'), 'DOES() can handle "ARRAY"');
+ ok( UNIVERSAL::DOES([],'ARRAY'), 'DOES() can handle "ARRAY"');
+ ok( UNIVERSAL::DOES($bad[2],'%{}'), 'DOES() can handle overload');
+ ok( UNIVERSAL::DOES($bad[2],'@{}'), 'DOES() can handle overload');
+ ok( UNIVERSAL::DOES(\*_,'*{}'),'DOES() can handle *{}');
+ ok( UNIVERSAL::DOES({},'%{}'),'DOES() can handle %{}');
+}
+ok( UNIVERSAL::DOES('Foo', 'bar' ), 'UNIVERSAL::DOES() should call DOES() on class' );
+ok( UNIVERSAL::DOES('Bar', 'Bar' ), '...... and should fall back to isa()' );
+ok( UNIVERSAL::DOES('Bar', 'Foo' ), '...... even when inherited' );
+ok( UNIVERSAL::DOES('Baz', 'Baz' ), '...... even without inheriting any other DOES()' );
+ok( ! UNIVERSAL::DOES('Baz', 'Foo' ), '...... returning true or false appropriately' );
+ok( ! Not::Deadly->DOES('Baz'), '...possible infinite loop');
+ok( !UNIVERSAL::DOES('Really::Deadly','Baz','no-delegate'), '...possible infinite loop');
package Pig;
package Bodine;
Bodine->isa('Pig');
Index: universal.c
===================================================================
--- universal.c (revision 1199)
+++ universal.c (working copy)
@@ -169,56 +169,198 @@
}
+
+
+#include "XSUB.h"
+
+/*
+CHECK_IF_SUB_USED_ON_OBJECT(ITEM,SV_CV)
+
+ utility define for checking to see if UNIVERSAL::DOES() has been
+ called as a subroutine on a class or object that overrides DOES.
+ If it does then we set SV_CV to hold the method which will
+ mean later on it will get called.
+ ITEM holds the code required to find the stash of the thing we are
+ looking up.
+*/
+
+#define CHECK_IF_SUB_USED_ON_OBJECT(FLAGS,ITEM,SV_CV) STMT_START { \
+ if (!((FLAGS) & 1)) { \
+ HV *me = gv_stashpvs("UNIVERSAL", 0); \
+ HV *them = (ITEM); \
+ if (me && them) { \
+ const char *does="DOES"; \
+ GV * const gv_me = gv_fetchmethod_autoload(me, does, FALSE); \
+ GV * const gv_them = gv_fetchmethod_autoload(them, does, FALSE); \
+ if (gv_me != gv_them && gv_me && isGV(gv_me) && gv_them && \
+ isGV(gv_them) && GvCV(gv_me) != GvCV(gv_them)) \
+ (SV_CV) = (SV*)GvCV(gv_them); \
+ } \
+ } \
+} STMT_END
+
/*
=for apidoc sv_does
Returns a boolean indicating whether the SV performs a specific, named role.
The SV can be a Perl object or the name of a Perl class.
+Named roles are as in isa(), with the addition of five special roles for
+refering to referencing operations that are allowed on the SV. These
+take the form of ${}, %{}, @{}, &{} and *{}. In addition the role
+'qr//' is defined which really checks if the reference is an object
+with regexp magic attached.
+
+Under normal circumstances if this routine detects that the SV is an object or
+classname which possess its own DOES routine then this routine will delegate
+to it. To block with then when (flags & 1) is true then no delegation will
+occur. This is to support the use of Class->SUPER::DOES() without infinite
+recursion occuring due to delegation.
+
=cut
*/
-
-#include "XSUB.h"
-
bool
-Perl_sv_does(pTHX_ SV *sv, const char *name)
+Perl_sv_does(pTHX_ SV *sv, const char *name, STRLEN namelen, U32 flags)
{
- const char *classname;
- bool does_it;
- dSP;
- ENTER;
- SAVETMPS;
+ bool does_it = 0; /* return value */
+ SV *rv = NULL; /* what thing does sv reference (if any) */
+ bool is_obj = 0; /* is rv an object? */
+
+ SV *sv_name = NULL; /* the name but in sv form (why isnt this an argument?) */
+ SV *sv_cv = NULL; /* if we are going to execute a code ref this is it */
+ const char *subname = NULL; /* what subroutine/method do we execute */
+ int count; /* how many items did the subroutine execute */
+
- SvGETMAGIC(sv);
+ SvGETMAGIC(sv); /* make sure we play nice with magic */
+ /* base tests for non object/references */
if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
- || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
- return FALSE;
-
- if (sv_isobject(sv)) {
- classname = sv_reftype(SvRV(sv),TRUE);
- } else {
- classname = SvPV(sv,PL_na);
+ || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
+ return FALSE;
+
+ if (SvROK(sv)) { /* is it a reference ?*/
+ rv = (SV*)SvRV(sv); /* to what? */
+ if (rv && SvOBJECT(rv)) { /* is it an object? */
+ is_obj = 1;
+ /* check to see if we are in the wrong DOES code
+ such as if they say UNIVERSAL::DOES($x,$y) but $x
+ has a overridden DOES with something else. */
+ CHECK_IF_SUB_USED_ON_OBJECT(flags, SvSTASH(rv),sv_cv);
+ }
}
- if (strEQ(name,classname))
- return TRUE;
+ if (!sv_cv) { /* no overriden method to be called */
+ /* check if we are checking a special internal role */
+ if (namelen == 4 && strEQ(name,"qr//")) {
+ /* does sv have regexp magic associated to it? */
+ if (is_obj && SvTYPE(rv) == SVt_PVMG && mg_find(rv, PERL_MAGIC_qr))
+ return 1;
+ else
+ return 0;
+ } else if ( namelen == 3 && name[1]=='{' && name[2]=='}' ) {
+ /* Check to see how things can be dereferenced */
+ const svtype t = SvTYPE(rv);
+ switch (t) {
+ case SVt_NULL:
+ case SVt_IV:
+ case SVt_NV:
+ case SVt_RV:
+ case SVt_PV:
+ case SVt_PVIV:
+ case SVt_PVNV:
+ case SVt_PVMG:
+ case SVt_PVLV:
+ if (name[0] == '$') return 1;
+ break;
+ case SVt_PVAV:
+ if (name[0] == '@') return 1;
+ break;
+ case SVt_PVHV: if (name[0] == '%') return 1;
+ break;
+ case SVt_PVCV:
+ if (name[0] == '&') return 1;
+ break;
+ case SVt_PVGV:
+ if (name[0] == '*') return 1;
+ break;
+ case SVt_PVFM:
+ case SVt_PVIO:
+ case SVt_BIND:
+ default:
+ break;
+ }
+
+ if (is_obj) {
+ /* we need check to see if the object overloads dereferencing
+ but to do that we need to ensure overload has been loaded
+ */
+ dSP;
+ PUTBACK;
+ ENTER;
- PUSHMARK(SP);
- XPUSHs(sv);
- XPUSHs(sv_2mortal(newSVpv(name, 0)));
- PUTBACK;
+ Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
+ newSVpvs("overload") , NULL);
- call_method("isa", G_SCALAR);
- SPAGAIN;
+ LEAVE;
+ SPAGAIN;
- does_it = SvTRUE( TOPs );
- FREETMPS;
- LEAVE;
+ sv_name = sv_2mortal( newSVpv( name, namelen ) );
+ subname = "overload::Method";
+ } else
+ return 0;
+ } else {
+ /* Check to see if the object supports a named role */
+ const char *classname;
+ if (is_obj) {
+ classname = sv_reftype(rv,TRUE);
+ } else {
+ CHECK_IF_SUB_USED_ON_OBJECT(flags,gv_stashsv(sv, 0),sv_cv);
+ classname = SvPV(sv,PL_na);
+ }
+ if (!sv_cv) {
+ if ( strEQ( name, classname ))
+ return TRUE;
+
+ sv_name = sv_2mortal( newSVpv( name, namelen ) );
+ if (rv && !is_obj)
+ subname = "UNIVERSAL::isa";
+ else
+ subname = "isa";
+ }
+ }
+ }
+ /* everything before this moment was in preparation for now */
+ {
+ /* call the final routine which will decide things */
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv);
+ XPUSHs(sv_name);
+ PUTBACK;
+ if (sv_cv)
+ count = call_sv(sv_cv,G_SCALAR);
+ else if (subname[0]=='i') /* 'i' for "isa" */
+ count = call_method(subname, G_SCALAR);
+ else
+ count = call_pv(subname,G_SCALAR);
+
+ SPAGAIN;
+ if (count != 1)
+ Perl_croak(aTHX_ "panic: DOES helper method returned "
+ " incorrect number of values\n") ;
+ does_it = SvTRUE( TOPs );
+ FREETMPS;
+ LEAVE;
+ }
+
return does_it;
}
+#undef CHECK_IF_SUB_USED_ON_OBJECT
regexp *
Perl_get_re_arg( pTHX_ SV *sv, U32 flags, MAGIC **mgp) {
@@ -413,16 +555,21 @@
{
dVAR;
dXSARGS;
+ U32 flags = 0;
PERL_UNUSED_ARG(cv);
+
- if (items != 2)
- Perl_croak(aTHX_ "Usage: invocant->does(kind)");
- else {
- SV * const sv = ST(0);
- const char *name;
-
- name = SvPV_nolen_const(ST(1));
- if (sv_does( sv, name ))
+ if (items == 3) {
+ if (SvTRUE(ST(2))) flags |= 1;
+ } else if (items != 2)
+ Perl_croak(aTHX_ "Usage: invocant->DOES(kind[,no_delegate])");
+
+ {
+ SV * const sv = ST(0);
+ STRLEN name_len;
+ const char *name = SvPV(ST(1), name_len);
+
+ if (Perl_sv_does( aTHX_ sv, name, name_len, flags ))
XSRETURN_YES;
XSRETURN_NO;
|
From @cpansproutOn Sun Jun 24 23:48:39 2012, demerphq wrote:
Having UNIVERSAL::DOES call the method could cause infinite looping if Having built-in roles like qr// sounds like a nice idea, but don’t we -- Father Chrysostomos |
From @demerphqOn 25 June 2012 15:28, Father Chrysostomos via RT
The patch explains how to do this properly doesn't it? +B<WARNING:> the delegation behaviour of UNIVERSAL::DOES() means that if a Im not thrilled that this edge case is a possibility but I figured it cheers, -- |
From @demerphqOn 25 June 2012 15:34, demerphq <demerphq@gmail.com> wrote:
Eg: cat perl overload_inf.pl sub stringify { my $obj= bless {},"Foo"; Also loops infinitely and eventually segfaults perl. So to the extent Yves -- |
From @doyOn Mon, Jun 25, 2012 at 08:48:00AM +0200, demerphq wrote:
So I like the general concept here, but I don't know if I'm a huge fan I think this would work a lot better if UNIVERSAL::DOES was only called -doy |
From @demerphqOn 25 June 2012 16:43, Jesse Luehrs <doy@tozt.net> wrote:
This doesnt fly as you then restrict the use of DOES to objects and Perhaps there is an alternative but "must be called as a method" isn't cheers -- |
From @doyOn Mon, Jun 25, 2012 at 04:59:18PM +0200, demerphq wrote:
No, you misunderstood - introduce a new separate keyword which itself -doy |
From @demerphqOn 25 June 2012 17:04, Jesse Luehrs <doy@tozt.net> wrote:
Ah. Yes I did misunderstand. Thanks for clarifying. Yves -- |
From @sciurius[Quoting Jesse Luehrs, on June 25 2012, 10:04, in "Re: [perl #77256] sv"]
Great! Finally we'd get rid of isa($foo, 'ARRAY') ... -- Johan |
From @demerphqOn 25 June 2012 18:39, Johan Vromans <jvromans@squirrel.nl> wrote:
If Ricardo is fine with something like this then I am willing to do cheers, -- |
From @sciuriusdemerphq <demerphq@gmail.com> writes:
Do we already have a list of predefined rules (like '@{}' that you used |
From @doyOn Mon, Jun 25, 2012 at 07:46:22PM +0200, Johan Vromans wrote:
As long as anywhere that I'm currently doing -doy |
From @sciurius[Quoting Jesse Luehrs, on June 25 2012, 12:56, in "Re: [perl #77256] sv"]
I'd expect: my $a = bless [], "Foo"; -- Johan |
From @demerphqOn 25 June 2012 22:25, Johan Vromans <jvromans@squirrel.nl> wrote:
The patch would want you to write that as: does($a,"ARRAY") Just as you would with UNIVERSAL::isa(). but it supports say "Array-like" if does($a, '@{}'); # says "Array" if you wanted to know if you could pretend it was an array. Yves -- |
From @sciurius[Quoting demerphq, on June 25 2012, 22:42, in "Re: [perl #77256] sv"]
I think we might be missing an opportunity here. A( ref to a)n array that's blessed seems to me an excellent case for So, if does( [], 'ARRAY' ); # true then $a = bless [], 'Foo'; Maybe it helps if you explain the difference between does( ..., 'ARRAY' ) and does( ..., '@{}' ) -- Johan |
From @doyOn Mon, Jun 25, 2012 at 10:51:00PM +0200, Johan Vromans wrote:
I imagine that does(..., '@{}') takes overloading into account. One -doy |
From @phaylonOn Mon, 2012-06-25 at 15:55 -0500, Jesse Luehrs wrote:
It might also be a good idea if it were to ignore the actual type of the regards, |
From @demerphqOn 25 June 2012 22:51, Johan Vromans <jvromans@squirrel.nl> wrote:
Same as isa( ..., 'ARRAY'), so it returns true if the reftype(...) eq Which actually says you are right and we need a does( ..., '[]') to
The idea was to tell you if the object was reftype eq 'ARRAY' OR that Yves -- |
From chromatic@wgz.orgOn Sunday, June 24, 2012 09:57:59 PM Johan Vromans wrote:
Any CPAN module which reimplements a part of the core, badly, has a bug, in my -- c |
From @sciurius[Quoting demerphq, on June 25 2012, 23:18, in "Re: [perl #77256] sv"]
No! This is the fundamental difference between isa and does. does does( $thing, 'ARRAY' ) being true means I can do $thing->[0] and There are no other array-oriented roles than 'ARRAY'. Overloading must -- Johan |
From @demerphqOn 26 June 2012 08:09, Johan Vromans <jvromans@squirrel.nl> wrote:
No no. Sometime you WANT an AV and I dont see how its useful to force This is part of the point for me, DOES and Perls OO model shouldnt Cheers, -- |
From @sciurius[Quoting demerphq, on June 26 2012, 08:49, in "Re: [perl #77256] sv"]
Yes, naturally. Only that's not a role for does, we have reftype for
You risk ending up with several functions with much overlapping -- Johan |
From @demerphqOn 26 June 2012 09:14, Johan Vromans <jvromans@squirrel.nl> wrote:
I want one routine that I can use for all of it.
Like pack? I think the uses are related enough that people wont be confused. Yves -- |
From @sciurius[Quoting demerphq, on June 26 2012, 09:19, in "Re: [perl #77256] sv"]
Let's agree to disagree, then. -- Johan |
From @phaylonOn Tue, 2012-06-26 at 09:19 +0200, demerphq wrote:
That would mean the check would break encapsulation by default. It means
In my mind, 'does' & Co. are about intents. An unblessed hash reference If an object would _want_ to be used as a hash reference, it could just regards, |
From @sciuriusRobert Sedlacek <rs@474.at> writes:
This would make more sense if perl had opaque objects. -- Johan |
From @phaylonOn Tue, 2012-06-26 at 17:23 +0200, Johan Vromans wrote:
It might make more sense, but I think it makes enough already, at least use intent::hash; # provides a DOES that is true for hash access I can certainly see the value of reftype and co, sometimes you want to regards, |
From @sciuriusRobert Sedlacek <rs@474.at> writes:
That's precisely what I was thinking of. A nice, clean and elegant way +1 -- Johan |
From @jkeenanOn Mon Aug 16 16:02:16 2010, ben@morrow.me.uk wrote:
I reviewed this older ticket tonight. What I quote above was the I would like to ask those who posted to review their comments and, as I am taking this ticket for the purpose of closing it within 7 days Thank you very much. |
Migrated from rt.perl.org#77256 (status was 'open')
Searchable as RT77256$
The text was updated successfully, but these errors were encountered: