[% setvar title Allow grouping of -X file tests and add C builtin %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/


Allow grouping of -X file tests and add filetest builtin


  Maintainer: Nathan Wiger <nate@wiger.org>
  Date: 25 Sep 2000
  Last Modified: 30 Sep 2000
  Mailing List: perl6-language@perl.org
  Number: 320
  Version: 2
  Status: Frozen


Currently, file tests cannot be grouped, resulting in very long expressions when one wants to check to make sure some thing is a readable, writeable, executable directory:

   if ( -d $file && -r $file && -w $file && -x $file ) { ... }

It would be really nice if these could be grouped instead:

   if ( -drwx $file ) { ... }

Notice how much easier this is to read and write.


Everyone liked it (I even heard Tom say so :), the only concern raised was that it makes the direct negation of subs impossible because of the way -[a-zA-Z]+ would have to be tokenized. See the MIGRATION and also REFERENCES sections for details on this.


File Test Grouping

See above. Multiple file tests, when grouped, should be ANDed together. This RFC does not propose a way to OR them, since usage like this:

   if ( -d $file || -r $file || -w $file || -x $file ) { ... }

Is highly uncommon, to say the least.

Notice this has the nice side effect of eliminating the need for _ in many cases, since this:

   if ( -d $file && -r _ && -w _ && -x _ ) { ... }

Can simply be written as a single grouped file test, as shown above. If you need to check for more complex logic, you still have to do that separately:

   if ( -drwx $file and ! -h $file )  { ... }

This is the simplest and also probably the clearest way to implement this.

New filetest Builtin

This RFC also proposes a new filetest builtin that is actually what is used for these tests. The -[a-zA-Z]+ form is simply a shortcut to this builtin, just like <> is a shortcut to readline. So:

   if ( -rwdx $file ) { ... }

Is really just a shortcut to the filetest builtin:

   if ( filetest $file, 'rwdx' ) { ... }

Either form could be used, depending on the user's preferences (just like readline). Note that this filetest builtin is designed to supposedly make the implementation of this easier, but if it doesn't, then it's unnecessary and should not be added.


This would involve making -[a-zA-Z]+ a special token in all contexts, serving as a shortcut for the filetest builtin. This means that you will no longer be able to directly negate subroutine calls; see below.


There is a subtle trap if you are negating subroutines:

   $result = -drwx $file;

And expect this to be parsed like this:

   $result = - &drwx($file);

However, usage such as this is not common, since negating subs only makes sense in a very few cases. In Perl 6, instead of writing:

   $num = -exp($foo);

You would have to write:

   $num = - exp($foo);

The author personally feels this is not too much of a burden for the benefit of grouped filetests. Note that this is already required for people that use subs named r, w, d, or any other filetest character.

To fix this issue, the p52p6 translator simply has to look for -([a-zA-Z]{2,}) and replace it with - $1, since injecting a single space will break up the token. See the below links for more details on the discussions of this.