2

我可以同时使用两种方法进行本地化$|,还是应该使用其中一种来支持另一种?

方式一:备份“_init_scr”中的旧值,$|并在调用“_end_win”时设置回$|旧值。方式2:调用local $| = 1“_init_scr”后调用。

package Package_name

# ...

sub _init_scr {
    my ( $arg ) = @_;
    $arg->{old_handle} = select( $arg->{handle_out} );
    #$arg->{backup_flush} = $|; # way 1
    $| = 1;
    # ...
}

sub _end_win {
    my ( $arg ) = @_;
    # ...
    #$| = $arg->{backup_flush}; # way 1
    select( $arg->{old_handle} );
}

sub choose {
    my $arg = ...;
    # ...
    _init_scr( $arg );
    # way 2 - instead of setting `$|` in "_init_scr" set it here:
    #local $| = 1;
    # ...
    while ( 1 ) {
        my $c = _getch( $arg );
        # ...;
        given ( $c ) {
            # ...
            when ( $c == CONTROL_C ) {
                _end_win( $arg );
                print "^C";
                kill( 'INT', $$ );
                return;
            }
            when ( $c == KEY_ENTER ) {
                # ...
                _end_win( $arg );
                return $result;
            }
        }
    }
}
4

4 回答 4

3

使用local. 这样,$|无论子如何退出(异常,早期return等),都会恢复。

顺便说一句,您可以使用select()->flush;而不是来回切换$|

use IO::Handle qw( );  # Required in older versions of Perl.
print "^C";
select()->flush();

也就是说,local $|由于您无论如何都需要打电话_end_win进行清理,因此优势已经消失。所以让我们摆脱对_end_win.

use Sub::ScopeFinalizer qw( scope_finalizer );

sub _local_scr {
    my ( $arg ) = @_;
    my $old_autoflush = $|;
    my $old_handle = select( $arg->{handle_out} );
    $| = 1;

    return scope_finalizer {
       $| = $old_autoflush;
       select($old_handle);
    };
}

sub choose {
    my $arg = ...;

    my $guard = _local_scr( $arg );

    while ( 1 ) {
        ...
                print "^C";
                kill( 'INT', $$ );
                return;
        ...
    }
}
于 2013-04-16T14:44:11.540 回答
2

第三种方式:

use IO::Handle;
# ...
$arg->{handle_out}->autoflush(1);
# ...
$arg->{handle_out}->autoflush(0);

IO::Handle 中还有其他各种方便的方法。

于 2013-04-16T14:48:35.333 回答
2

如果要本地化该值,只需使用local. 当您退出本地化范围时,它将处理恢复原始值,而无需您进行任何额外的努力(或出错的机会)。

于 2013-04-16T14:43:14.017 回答
1

您应该使用local $| = 1;, 因为这是惯用的 Perl 方式。它比跟踪另一个变量中的值更简单。

使用一组额外的大括号(如果需要)来创建一个范围,以便它只适用于应该设置它的程序部分。

{
   #Buffering is turned off only in here.
   local $| = 1;
   unbuffered_commands();
}

buffered_commands();
于 2013-04-16T14:42:37.370 回答