Provided by: manpages-zh_1.5-1_all bug

NAME

       perlfaq7 - 综合的问题 (2003/07/24 02:17:21)

DESCRIPTION述
       本节讨论综合的 Perl 语言问题,不适于在其他所有段落中讨论的问题

       PerlBNF/yacc/RE$@%*/?

       一种从 Perl呼叫编译好的 C程式码的方法。阅读
       perlxstut是个多了解扩充(extensions)的好方法。

       PerlC/tainted() 函数 (可从 CPAN 获取,也包含在
       Perl 5.8.0 中)。参见 perlsec 中的 "Laundering and Detecting Tainted
       Data" 。

      ?

       关於闭包的说明,请看 perlref 。

       闭包 (closure)是个精确但又很难解释的计算机科学名词。在 Perl
       里面,闭包是以匿名函数的形式来实现,具有持续参照位於该函数范围之外的文字式变数值的能力。这些外部的文字变数会神奇地保留它们在闭包函数最初定义时的值
       (深连结)。

       如果一个程式语言容许函数递回另一个函数的话 (像 Perl
       就是),闭包便具有意义。要注意的是,有些语言虽提供匿名函数的功能,但却无法正确处理闭包;
       Python
       这个语言便是一例。如果要想多了解闭包的话,建议你去找本功能性程式设计的教科书来看。Scheme这个语言不仅支援闭包,更鼓励多加使用。

       以下是个典型的产生函数的函数:

           sub add_function_generator {
             return sub { shift + shift };
           }

           $add_sub = add_function_generator();
           $sum = $add_sub->(4,5);                # $sum is 9 now.

       闭包用起来就像是个 函数样板,其中保留了一些可以在稍後再填入的空格。
       add_function_generator()
       所递回的匿名函数在技术上来讲并不能算是一个闭包,因为它没有用到任何位在这个函数范围之外的文字变数。

       把上面这个例子和下面这个
       make_adder()函数对照一下,下面这个函数所递回的匿名函数中使用了一个外部的文字变数。这种指名外部函数的作法需要由
       Perl递回一个适当的闭包,因此那个文字变数在匿名函数产生之时的值便永久地被锁进闭
       包里。

           sub make_adder {
               my $addpiece = shift;
               return sub { shift + $addpiece };
           }

           $f1 = make_adder(20);
           $f2 = make_adder(555);

       这样一来 "&$f1($n)" 永远会是 20加上你传进去的值 $n ,而 "&$f2($n)" 将
       永远会是 555加上你传进去的值 $n。$addpiece 的值会在闭包中保留下来。

       闭包在比较实际的场合中也常用得到,譬如当你想把一些程式码传入一个函数时:

           my $line;
           timeout( 30, sub { $line = <STDIN> } );

       如果要执行的程式码当初是以字串的形式传入的话,即 '$line = <STDIN>'
       ,那麽 timeout()
       这个假想的函数在回到该函数被呼叫时所在的范围後便无法再撷取 $line
       这个文字变数的值了。

      ?

       变数自杀指的是 (暂时或是永久)地失去一个变数的值。造成这个现象的-
       因是做范围界定的 my() 和 local()和闭包或
       foreach()回圈变数及函数参数相互影响
       所致。过去很容易偶尔丢失变量,现在就困难多了,可以试试这段代码:

           my $f = "foo";
           sub T {
             while ($i++ < 3) { my $f = $f; $f .= "bar"; print $f, "\n" }
           }
           T;
           print "Finally $f\n";

       有叁个 "bar" 加进去的 $f 变数应该是一个新的 $f (因为 "my $f" 在每个-
       环都应该创造一个新的区域变数)。然而,实际上并非如此。这个臭虫最新的
       Perl 版本中已被修正 (在 5.004_05, 5.005_03 和 5.005_56 上测试过)。

      /Function, FileHandle, Array,Hash, Method, Regex}?

       除了正规表现式这个特例外,你需要以传参考值的方式传资料给这些物件。参看
       perlsub 中的 "Pass by Reference",里面有针对此问题的讨论,以及 perlref
       里面有引用的资讯。

       参见下面的 ``Passing Regexes'',学习如何传递正则表达式。

       传递变量和函数
           一般的变数和函数是相当简单的:只要传一个指向现存的匿名变数或函数的参考值即可:

               func( \$some_scalar );

               func( \@some_array  );
               func( [ 1 .. 10 ]   );

               func( \%some_hash   );
               func( { this => 10, that => 20 }   );

               func( \&some_func   );
               func( sub { $_[0] ** $_[1] }   );

       传递文件句柄
           在 Perl5.6
           中,你可以用标量变量表示文件句柄,并将它与其他标量同样处理

                   open my $fh, $filename or die "Cannot open $filename! $!";
                   func( $fh );

                   sub func {
                           my $passed_fh = shift;

                           my $line = <$fh>;
                           }

           在 Perl5.6 之前,必须用 *FH 或 "\*FH" 语法。这叫做
           "typeglobs"--参见 perldata 中的 "Typeglobs and Filehandles" 和
           perlsub 中的 "Pass by Reference"。

       传递正则表达式
           要传递正则表达式,你需要使用足够新的 Perl 发行,足以支持 "qr//"
           构造方式的版本,传递字符串,使用一个捕获异常的
           eval,或者其他更聪明的办法。

           这里有一个如何传递正则表达式字符串的例子,使用 "qr//":

               sub compare($$) {
                   my ($val1, $regex) = @_;
                   my $retval = $val1 =~ /$regex/;
                   return $retval;
               }
               $match = compare("old McDonald", qr/d.*D/i);

           注意 "qr//"
           如何允许在后面加上标志。这个模式在编译期被编译,尽管它后来才执行。
           "qr//" 表示法虽然好用,但是直到 5.005
           发行中才引入。在那之前,你必须用不直观的办法。例如,如果没有 "qr//"
           的话:

               sub compare($$) {
                   my ($val1, $regex) = @_;
                   my $retval = eval { $val1 =~ /$regex/ };
                   die if $@;
                   return $retval;
               }

               $match = compare("old McDonald", q/($?i)d.*D/);

           确保你没有任何这样的东西:

               return eval "\$val =~ /$regex/";   # WRONG

           否则别人会靠双引号括起来的字串以及 eval 双重解译的本质而偷偷插入
           shell指令来作坏事。例如:

               $pattern_of_evil = 'danger ${ system("rm -rf * &") } danger';

               eval "\$string =~ /$pattern_of_evil/";

           想学非常非常聪明的方法的读者可以参考 O'Reilly 出的 Mastering
           Regular Expressions这本书,作者是 Jeffrey Friedl。其中第 273页的
           Build_MatchMany_Function()特别的有趣。在 perlfaq2中可以找到有关本书
           的资料。

       传递方法
           要传递一个对象方法给一个函数,可以这样做:

               call_a_lot(10, $some_obj, "methname")
               sub call_a_lot {
                   my ($count, $widget, $trick) = @_;
                   for (my $i = 0; $i < $count; $i++) {
                       $widget->$trick();
                   }
               }

           或者,使用一个闭包来包含这个对象,它的方法调用及参数:

               my $whatnot =  sub { $some_obj->obfuscate(@args) };
               func($whatnot);
               sub func {
                   my $code = shift;
                   &$code();
               }

           也可以研究 UNIVERSAL 类别中的 can()方法 (附於标准 Perl 版本中)。

       How do I create a static variable?

       就像与 Perl相关的其他事情一样,``条条大路通罗马''
       (TMTOWTDI)。对其他语言来说叫做 ``静态变数'' (static variable)的东西,在
       Perl里面可能是一个函数私有的变数(只有该函数自己看得到,且在不同的呼叫间保持定值),或是一个档案私有(file-
       private)变数(只有同一个档案中的函数才看得到)。

       以下就是实作函数私有变数的程式:

           BEGIN {
               my $counter = 42;
               sub prev_counter { return --$counter }
               sub next_counter { return $counter++ }
           }

       prev_counter() 和 next_counter() 将会共用一个於编译时初始化的私有变数
       $counter。

       要声明一个档案私有(file-private)变数,你仍然得使用
       my(),将它放在档案开头处最外围。假设现在是在 Pax.pm 这个档案里:

           package Pax;
           my $started = scalar(localtime(time()));

           sub begun { return $started }

       当用 "use Pax" 或 "require Pax"
       载入此模组时,这个变数就会被初始化。不过它不会被资源回收,像其他出了有效范围的变数那样,因为
       begun()函数要用到它,但是没有其他函数能撷取它。这个变数不能以
       $Pax::started
       的形式来撷取,因为它所存在的范围与此包裹无关。它存在的范围是这个档案。可想见地,一个档案里可以放好几个包裹,而所有的包裹都撷取同一个私有变数,但从另一个档案中,即使是属於同一个包裹(package),也不能取得它的值。

       参见 perlsub 中的 "Persistent Private Variables" 的细节.

       What's the difference between dynamic and lexical (static) scoping?
       Between local() and my()?

       local($x) 将全域变数 $x的灾荡嫫鹄矗⒃诖撕葱衅诩涓秤枰桓鲂
       值,此值可以从此函数所呼叫的其他函数里看见。这整个步骤是在执行期间完成的,所以才叫做动态范围选取
       (dynamic
       scoping)。local()影响的是全域变数,或者称作包裹变数或动态变数。

       "my($x)"
       会创造一个只能在目前这个函数里看得见的新变数。这个步骤是在编译期完成(compile-
       time),所以称作文字式或是静态范围选取。my()总是作用在私有变数,也称作文字式变数或(不当地)称作静态(范围选取)变数。

       例如:

           sub visible {
               print "var has value $var\n";
           }

           sub dynamic {
               local $var = 'local';   # 为全局变量暂时赋值
               visible();              # 调用 $var 变量
           }

           sub lexical {
               my $var = 'private';    # 新的私有变量 $var
               visible();              # (在 sub 作用域之外不可见)
           }

           $var = 'global';

           visible();                  # prints global
           dynamic();                  # prints local
           lexical();                  # prints global

       你可以发现在整个过程中 ``private''这个值都印不出来。那是因为
       $var的值只存在於lexical()
       函数的区块里面,对它所呼叫的函数来说是看不到的。

       总结来说,local()不会产生你想像中的私有、区域变数。它只是将一个暂时的值授予一个全域变数。如果你要的是私有的变数,那麽
       my() 才是你要找的。

       参见 perlsub 中的 "Private Variables via my()" 以及 "Temporary Values
       via local()" 来获取详情

      ?

       如果你知道你所在的是哪一个包裹(package)的话,你可以直接指名,就像写
       $Some_Pack::var 这样。注意 $::var 这个写法 并非表示目前此包裹 (package)
       内的动态变数 $var,而是指在 main包裹(package) 里的那个,就等价於
       $main::var 。

               use vars '$var';
               local $var = "global";
               my    $var = "lexical";

               print "lexical is $var\n";
               print "global  is $main::var\n";

       可选的,可以使用编译器指令 our() 来在当前静态作用域中引入动态变量

               require 5.006; # our() did not exist before 5.6
               use vars '$var';

               local $var = "global";
               my $var    = "lexical";

               print "lexical is $var\n";

               {
                 our $var;
                 print "global  is $var\n";
               }

      ?

       在深连结中,匿名函数中所用到的文字式变数值是以该函数产生时所在的范围为准。在浅连结中,这些变数值是以函数被呼叫时所在的范围为准,如果在这个范围中恰巧有同名的变数,便使用这些当地变数的值。Perl总是使用文字式变数(就是以
       my()创造的)式的深连结。然而,动态变数(也称作全域(global),区域(local),或包裹(package)变数)在功效上是浅连结。就把这当作是少用它们的另一个理由好
       了。请参考 "什么是闭包" 一节。

      么

       local()会把 =号右边以序列情境来对待。而 <FH> 这个阅读的 动作,就像
       Perl里许多的函数以及运算子一样,会自动分辨出自己被呼叫时所在的情境并且采取适当的作法。一般来说,scalar()函数可以帮点忙。这个函数实际上对资料本身不会有任何作用(与一般所认为的相反),但是会告诉它所作用的函数要以对待纯量值的方法来运算。如果那个函数没有预先定义好碰到纯量情境的行为,那麽它当然也帮不了你(例如
       sort() 函数)。

       然而,在以上这个例子 (local...)中,只要省略括号便可强制使用标量情境:

           local($foo) = <FILE>;           # WRONG
           local($foo) = scalar(<FILE>);   # ok
           local $foo  = <FILE>;           # right

       其实在这个例子中,或许你该改用文字式变数 (lexical
       variables),不过会碰到 的问题跟上面一样:

           my($foo) = <FILE>;  # WRONG
           my $foo  = <FILE>;  # right

       ?

       为什麽要这麽做? :-)

       如果你要覆盖掉某个内建函数,例如说 open(),那你得将其定义从另一个模组载
       入。参考 perlsub 中的 Overriding Builtin Functions。在
       "Class::Template" 里面也有个范例。

       如果你要覆盖掉一个 Perl运算子,像是 "+" 或 "**", 那你该使用 "use
       overload" 这个编用,在 overload 中有记载。

       如果你要覆盖父类别 (parent class)里的方法呼叫 (method calls),请看
       perltoot 中的 Overridden Methods 。

       &foo foo()?

       当你用 &foo的方式呼叫一个函数时,你等於让这个函数撷取你目前
       @_里面的值,同时也跳过孕投ㄒ
       (prototypes)不用。这表式此函数抓到的是你当时的 @_, 而非一个空的
       @_!虽然严格讲起来它也不能算是个 bug (但是在
       perlsub里面是这麽说的)但在大部份情况下,这也算不上是个特别功能。

       当你用 &foo()的方式呼叫你的函数时,你会得到一个新的 @_,但是孕投ㄒ
       仍然会被避开不用。

       在一般情况下,你该用
       foo()的方式去呼叫函数。只有在编译器已事先知道这个函数的定义时,括号才能省略,譬如当这个函数所在的模组或包裹被
       use (但如果是被 require则不行)时,或是透过先前提及或 use
       subs宣告等方法,让编译器先接触到这个函数的定义。用这种呼叫方式,即使是当括号省掉时,你都会得到一个乾净的
       @_,不会有任何不该出现的旧值残留在上面。

      ?

       这个问题在 perlsyn 文件里有更详尽的解释。简单来说,因为
       Perl本身已提供了多种不同的条件测试方法可供使用 (数值比较、字串比较、
       glob比较、正规表示式 对应、覆盖比较,及其它),所以并没有正式的
       case叙述语法。虽然自 perl1起这就一直是许多人期盼的一个项目,但因
       Larry无法决定怎样才是呈现这功能的最好方法,因此还是将它略掉。

       从 Perl 5.8 开始,要使用 swtich 和 case,可以使用 Switch
       扩展,就是这样:

               use Switch;

       此后就可以用 switch 和 case 了.  It is not as fast as it could be
       because it's not really part of the language (it's done using source
       filters) but it is available, and it's very flexible.

       But if one wants to use pure Perl, the general answer is to write a
       construct like this:

           for ($variable_to_test) {
               if    (/pat1/)  { }     # do something
               elsif (/pat2/)  { }     # do something else
               elsif (/pat3/)  { }     # do something else
               else            { }     # default
           }

       下面这个简单的 switch范例以模式对应为基础。我们将要做的是对储存在
       $whatchamacallit里面的参考值
       (reference)的类型进行多重条件的判断。【译注:$whatchamacallit 函意为
       $what_you_might_call_it】

           SWITCH: for (ref $whatchamacallit) {

               /^$/            && die "not a reference";

               /SCALAR/        && do {
                                       print_scalar($$ref);
                                       last SWITCH;
                               };

               /ARRAY/         && do {
                                       print_array(@$ref);
                                       last SWITCH;
                               };

               /HASH/          && do {
                                       print_hash(%$ref);
                                       last SWITCH;
                               };

               /CODE/          && do {
                                       warn "can't print function ref";
                                       last SWITCH;
                               };

               # DEFAULT

               warn "User defined type skipped";

           }

       See "perlsyn/"Basic BLOCKs and Switch Statements"" for many other
       examples in this style.

       Sometimes you should change the positions of the constant and the
       variable.  For example, let's say you wanted to test which of many
       answers you were given, but in a case-insensitive way that also allows
       abbreviations.  You can use the following technique if the strings all
       start with different characters or if you want to arrange the matches
       so that one takes precedence over another, as "SEND" has precedence
       over "STOP" here:

           chomp($answer = <>);
           if    ("SEND"  =~ /^\Q$answer/i) { print "Action is send\n"  }
           elsif ("STOP"  =~ /^\Q$answer/i) { print "Action is stop\n"  }
           elsif ("ABORT" =~ /^\Q$answer/i) { print "Action is abort\n" }
           elsif ("LIST"  =~ /^\Q$answer/i) { print "Action is list\n"  }
           elsif ("EDIT"  =~ /^\Q$answer/i) { print "Action is edit\n"  }

       A totally different approach is to create a hash of function
       references.

           my %commands = (
               "happy" => \&joy,
               "sad",  => \&sullen,
               "done"  => sub { die "See ya!" },
               "mad"   => \&angry,
           );

           print "How are you? ";
           chomp($string = <STDIN>);
           if ($commands{$string}) {
               $commands{$string}->();
           } else {
               print "No such command: $string\n";
           }

      ?

       在 perlsub 中的 "Autoloading" 和 perltoot 中的 "AUTOLOAD: Proxy
       Methods" 里 提到的 AUTOLOAD 方法让你能捕捉对於未定义函数与方法的呼叫。

       When it comes to undefined variables that would trigger a warning under
       "use warnings", you can promote the warning to an error.

               use warnings FATAL => qw(uninitialized);

      ?

       一些可能的-
       因:你用的继承给搞混了、你拼错了该方法的名字,或是物件的类别错误。这些事在
       perltoot里都有更详尽的说明。同时你也可以用 "print ref($object)" 来找出
       $object 这个物件是被归到哪个类别底下。

       另一个可能的砸蚴悄阍 Perl还不知道这个包裹
       (package)存在之前便将某个类别名称在间接式物件语法中使用 (例如 "find
       Guru "Samy"")。最好是在开始使用你的包裹前,先确定都已-
       先把它们定义好了,如果你用的是 use 而非
       require的话,这件事便会自动处理好。不然的话,确定你使用箭头式语法
       (例如,"Guru->find("Samy")"))。在perlobj 里面对於物件的记号有详尽解释。

       Make sure to read about creating modules in perlmod and the perils of
       indirect objects in "Method Invocation" in perlobj.

      ?

       如果只是一个随意的程式的话,你可以用下面的方法找出目前正被编译的包裹为何:

           my $packname = __PACKAGE__;

       但如果是一个方法的话,而且印出的错误讯息中要包含呼叫此方法的物件
       (不见得就是把这个方法编译进去的那个物件)则:

           sub amethod {
               my $self  = shift;
               my $class = ref($self) || $self;
               warn "called me from a $class object";
           }

       perl?

       用内嵌 POD格式的方法把程式码变注解。将要注释掉的块包含在 POD 标记内,
       例如 "=for nobody" 和 "=cut" (标志着 POD 块的结束).

           # 这是程式

           =for nobody

           all of this stuff

           接下来此处所有的文字都会被忽略

           =cut

           # program continues

       The pod directives cannot go just anywhere.  You must put a pod
       directive where the parser is expecting a new statement, not just in
       the middle of an expression or some other arbitrary grammar production.

       See perlpod for more details.

       How do I clear a package?

       Use this code, provided by Mark-Jason Dominus:

           sub scrub_package {
               no strict 'refs';
               my $pack = shift;
               die "Shouldn't delete main package"
                   if $pack eq "" || $pack eq "main";
               my $stash = *{$pack . '::'}{HASH};
               my $name;
               foreach $name (keys %$stash) {
                   my $fullname = $pack . '::' . $name;
                   # Get rid of everything with that name.
                   undef $$fullname;
                   undef @$fullname;
                   undef %$fullname;
                   undef &$fullname;
                   undef *$fullname;
               }
           }

       Or, if you're using a recent release of Perl, you can just use the
       Symbol::delete_package() function instead.

       How can I use a variable as a variable name?

       Beginners often think they want to have a variable contain the name of
       a variable.

           $fred    = 23;
           $varname = "fred";
           ++$$varname;         # $fred now 24

       This works sometimes, but it is a very bad idea for two reasons.

       The first reason is that this technique only works on global variables.
       That means that if $fred is a lexical variable created with my() in the
       above example, the code wouldn't work at all: you'd accidentally access
       the global and skip right over the private lexical altogether.  Global
       variables are bad because they can easily collide accidentally and in
       general make for non-scalable and confusing code.

       Symbolic references are forbidden under the "use strict" pragma.  They
       are not true references and consequently are not reference counted or
       garbage collected.

       The other reason why using a variable to hold the name of another
       variable is a bad idea is that the question often stems from a lack of
       understanding of Perl data structures, particularly hashes.  By using
       symbolic references, you are just using the package's symbol-table hash
       (like %main::) instead of a user-defined hash.  The solution is to use
       your own hash or a real reference instead.

           $USER_VARS{"fred"} = 23;
           $varname = "fred";
           $USER_VARS{$varname}++;  # not $$varname++

       There we're using the %USER_VARS hash instead of symbolic references.
       Sometimes this comes up in reading strings from the user with variable
       references and wanting to expand them to the values of your perl
       program's variables.  This is also a bad idea because it conflates the
       program-addressable namespace and the user-addressable one.  Instead of
       reading a string and expanding it to the actual contents of your
       program's own variables:

           $str = 'this has a $fred and $barney in it';
           $str =~ s/(\$\w+)/$1/eeg;             # need double eval

       it would be better to keep a hash around like %USER_VARS and have
       variable references actually refer to entries in that hash:

           $str =~ s/\$(\w+)/$USER_VARS{$1}/g;   # no /e here at all

       That's faster, cleaner, and safer than the previous approach.  Of
       course, you don't need to use a dollar sign.  You could use your own
       scheme to make it less confusing, like bracketed percent symbols, etc.

           $str = 'this has a %fred% and %barney% in it';
           $str =~ s/%(\w+)%/$USER_VARS{$1}/g;   # no /e here at all

       Another reason that folks sometimes think they want a variable to
       contain the name of a variable is because they don't know how to build
       proper data structures using hashes.  For example, let's say they
       wanted two hashes in their program: %fred and %barney, and that they
       wanted to use another scalar variable to refer to those by name.

           $name = "fred";
           $$name{WIFE} = "wilma";     # set %fred

           $name = "barney";
           $$name{WIFE} = "betty";     # set %barney

       This is still a symbolic reference, and is still saddled with the
       problems enumerated above.  It would be far better to write:

           $folks{"fred"}{WIFE}   = "wilma";
           $folks{"barney"}{WIFE} = "betty";

       And just use a multilevel hash to start with.

       The only times that you absolutely must use symbolic references are
       when you really must refer to the symbol table.  This may be because
       it's something that can't take a real reference to, such as a format
       name.  Doing so may also be important for method calls, since these
       always go through the symbol table for resolution.

       In those cases, you would turn off "strict 'refs'" temporarily so you
       can play around with the symbol table.  For example:

           @colors = qw(red blue green yellow orange purple violet);
           for my $name (@colors) {
               no strict 'refs';  # renege for the block
               *$name = sub { "<FONT COLOR='$name'>@_</FONT>" };
           }

       All those functions (red(), blue(), green(), etc.) appear to be
       separate, but the real code in the closure actually was compiled only
       once.

       So, sometimes you might want to use symbolic references to directly
       manipulate the symbol table.  This doesn't matter for formats, handles,
       and subroutines, because they are always global--you can't use my() on
       them.  For scalars, arrays, and hashes, though--and usually for
       subroutines-- you probably only want to use hard references.

       What does "bad interpreter" mean?

       The "bad interpreter" message comes from the shell, not perl.  The
       actual message may vary depending on your platform, shell, and locale
       settings.

       If you see "bad interpreter - no such file or directory", the first
       line in your perl script (the "shebang" line) does not contain the
       right path to perl (or any other program capable of running scripts).
       Sometimes this happens when you move the script from one machine to
       another and each machine has a different path to perl---/usr/bin/perl
       versus /usr/local/bin/perl for instance.

       If you see "bad interpreter: Permission denied", you need to make your
       script executable.

       In either case, you should still be able to run the scripts with perl
       explicitly:

               % perl script.pl

       If you get a message like "perl: command not found", perl is not in
       your PATH, which might also mean that the location of perl is not where
       you expect it so you need to adjust your shebang line.

AUTHOR AND COPYRIGHT

       Copyright (c) 1997-2002 Tom Christiansen and Nathan Torkington.  All
       rights reserved.

       This documentation is free; you can redistribute it and/or modify it
       under the same terms as Perl itself.

       Irrespective of its distribution, all code examples in this file are
       hereby placed into the public domain.  You are permitted and encouraged
       to use this code in your own programs for fun or for profit as you see
       fit.  A simple comment in the code giving credit would be courteous but
       is not required.

者
      室