博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
带通滤波中零相位和最小相位_相位器在Perl 6中的工作方式
阅读量:2528 次
发布时间:2019-05-11

本文共 10787 字,大约阅读时间需要 35 分钟。

带通滤波中零相位和最小相位

这是关于将代码从Perl 5迁移到Perl 6 的第六 。本文着眼中的 ,例如BEGINEND ,以及Perl中所谓的在语义上的细微变化。 6。

Perl 6已将一些Perl 5功能概括为相位器,而Perl 5的特殊功能块并未涵盖这些相位器。它还添加了其他相位器,而这些相位器根本没有任何(标准)Perl 5功能覆盖。

属于程序正常执行流程的一部分。 运行时执行程序根据相位器的类型和上下文来决定何时运行相位器。 因此,Perl 6中的所有相位器均以大写字母拼写,以使其脱颖而出。

概述

让我们从Perl 5的特殊块及其在Perl 6中执行的顺序开始,对它们进行概述:

Perl 5 Perl 6 笔记
BEGIN 开始 加载预编译的代码时无法运行
UNITCHECK 检查
CHECK Perl 6中没有等效项
INIT 在里面
END 结束

Perl 6中的这些相位器通常被称为因为它们与完整程序的执行相关,无论它们在程序中的位置如何。

开始

Perl 5中的BEGIN特殊块和Perl 6中的移相器的语义是相同的。 它指定了要在解析后立即执行的一段代码(因此, 整个程序(也就是编译单元)被解析之前)。

但是,在Perl 6中使用BEGIN有一个警告:默认情况下,Perl 6中的模块是预编译的,而与Perl 5则没有任何模块或脚本的预编译相反。

作为Perl 6模块的用户或开发人员,您不必考虑模块是否应该进行预编译(再次)。 在安装模块时以及每次Rakudo Perl 6更新之后,所有这些操作都会在后台自动完成。 每当开发人员对模块进行更改时,它也会自动完成。 您可能会注意到的唯一一件事是加载模块时的延迟很小。

这意味着仅在发生预编译时才执行BEGIN块, 而不是在每次加载模块时才执行。 这与Perl 5不同,在Perl 5中,模块通常仅作为加载模块时编译的源代码存在(即使该模块可以加载已编译的本机库组件)。

当将代码从Perl 5移植到Perl 6时,这可能会引起一些不愉快的意外,因为预编译可能是很久以前甚至在另一台机器上进行的(如果是从OS分发的软件包中安装的)。 考虑使用环境变量的值来启用调试的情况。 在Perl 5中,您可以这样写:

# Perl 5      
my
$DEBUG
;
BEGIN
{
$DEBUG
=
$ENV
{
DEBUG
}
//
0
}

这在Perl 5中会很好用,因为每次加载模块都会对其进行编译,因此BEGIN块会在每次加载模块时运行。 $ DEBUG的值将是正确的,具体取决于环境变量的设置。 但是在Perl 6中却不是这样。由于BEGIN移相器仅执行一次,因此在预编译时, $ DEBUG变量将具有在模块预编译时而不是在模块加载时确定的值!

一个简单的解决方法是禁止在Perl 6中预编译模块:

# Perl 6      
precompilation
;  
# this code should not be pre-compiled

但是,预编译具有一些您不希望轻易忽略的优点:

  • 数据结构设置只需完成一次。 如果您具有每次加载模块时都必须设置的数据结构,则在模块预编译时可以执行一次。 如果经常加载模块,这可能会节省大量的时间和CPU。

  • 它可以加载模块快得多 。 因为不需要解析任何源代码,所以预编译模块的加载速度比一遍又一遍地编译的模块快得多。 一个主要的例子是Perl 6的核心设置,这是用Perl 6编写的部分。它由一个64 / 2MB源文件(从许多单独的源文件中生成,用于维护)组成。 在Perl 6安装期间,大约需要一分钟的时间来编译此源文件。 在Perl 6启动时,加载此预编译的代码大约需要125毫秒。 这几乎是500倍的速度提升!

隐式使用BEGIN功能的Perl 5 Perl 6的其他一些功能也有相同的警告。 以下面的示例为例,我们希望常量DEBUG具有环境变量DEBUG的值,或者如果该变量不可用,则其值为0

# Perl 5      
use constant DEBUG
=>
$ENV
{
DEBUG
}
//
0
;
# Perl 6      
my constant DEBUG
=
%
*ENV
//
0
;

Perl 6中最好的等效项可能是INIT移相器:

# Perl 6      
INIT
my
\DEBUG
=
%
*ENV
//
0
;  
# sigilless variable bound to value

与Perl 5一样, INIT移相器在执行开始之前运行。 您还可以将Perl 6的模块预编译行为用作功能:

# Perl 6      
say
"This module was compiled at { BEGIN DateTime.now }"
;
# This module was compiled at 2018-10-04T22:18:39.598087+02:00

但是稍后会详细介绍该语法。

统一

Perl 5中的UNITCHECK特殊块的功能是由Perl 6中的移相器执行的。 它指定当在当前编译单元的编译完成将要执行的一段代码。

检查

Perl 5 CHECK特殊块的Perl 6中没有 等效项 。 主要原因是您可能不应该再使用Perl 5中的CHECK特殊块了。 请改用UNITCHECK,因为它的语义要好得多。 (自开始提供。)

在里面

Perl 6中的移相器的功能与Perl 5中的INIT特殊块相同。它指定了要在编译单元中的代码执行之前执行的一段代码。

在Perl 6的预编译模块中, INIT移相器可以替代BEGIN移相器。

结束

相位器的在Perl 6的功能是一样的END特殊块的在Perl 5.它指定毕竟在编译单元中的代码已被执行时,或者当代码决定退出(无论是有意或将要执行的代码段意外,因为会引发异常)。

一个例子

这是一个使用所有四个程序执行移相器及其Perl 5特殊块对应物的示例

# Perl 5      
say
"running in Perl 5"
;
END      
{
say
"END"  
}
INIT      
{
say
"INIT"  
}
UNITCHECK
{
say
"CHECK"
}
BEGIN    
{
say
"BEGIN"
}
# BEGIN
# CHECK
# INIT
# running in Perl 5
# END
# Perl 6
say
"running in Perl 6"
;
END  
{
say
"END"  
}
INIT  
{
say
"INIT"  
}
CHECK
{
say
"CHECK"
}
BEGIN
{
say
"BEGIN"
}
# BEGIN
# CHECK
# INIT
# running in Perl 6
# END

不仅仅是特殊的块

Perl 6中的相位器具有其他功能,使其不仅限于特殊块。

不需要块

Perl 6中的大多数移相器不必是一个 (即,花括号之间的代码)。 它们也可以由不带花括号的单个语句组成。 这意味着如果您在Perl 5中编写了此代码:

# Perl 5      
# need to define lexical outside of BEGIN scope
my
$foo
;
# otherwise it won't be known in the rest of the code
BEGIN
{
$foo
=
%
*ENV
//
42
}
;

您可以在Perl 6中将其编写为:

# Perl 6      
# share scope with surrounding code
BEGIN
my
$foo
=
%
*ENV
//
42
;

可能会返回一个值

所有程序执行移相器都返回其代码的最后一个值,以便您可以在表达式中使用它们。 上面使用BEGIN的示例也可以写成:

# Perl 6      
my
$foo
=
BEGIN
%
*ENV
//
42
;

BEGIN移相器一起使用时,您将创建一个无名常量并在运行时分配它。

由于模块的预编译,如果要在模块中进行这种类型的初始化,则最好使用INIT移相器:

# Perl 6      
my
$foo
= INIT
%
*ENV
//
42
;

这样可以确保在加载模块时(而不是在预编译时)确定该值(通常在模块安装期间发生一次)。

其他相位器在Perl 6

如果只对学习Perl 5特殊块在Perl 6中的工作方式感兴趣,则可以跳过本文的其余部分。 但是您会错过人们已经实现的许多不错且有用的功能。

块环相位器

块和环路移相器始终与周围的块相关联,无论它们在块中的位置如何。 除了不限于只使用其中之一,尽管您可能会说不止一个不能改善可维护性。

请注意,就这些移相器而言,任何子程序方法 也都被视为“块”。

名称 描述
ENTER 每次进入块时运行
LEAVE 每次离开块时运行
PRE 运行块之前检查条件
POST 运行块后检查返回值
KEEP 每次成功离开块时运行
UNDO 每次块成功取消运行

输入并离开

和移相器非常不言自明:只要输入一个Block,就会调用ENTER移相器。 每当离开一个块(正常地或通过异常)时,都会调用LEAVE移相器。 一个简单的例子:

# Perl 6      
say
"outside"
;
{
    LEAVE say
"left"
;
    ENTER say
"entered"
;
    say
"inside"
;
}
say
"outside again"
;
# outside
# entered
# inside
# left
# outside again

返回ENTER相位器的最后一个值,以便可以在表达式中使用它。 这是一个人为的例子:

# Perl 6      
{
    LEAVE say
"stayed "
~
( now
- ENTER now
)
~
" seconds"
;
   
2
;
}
# stayed 2.001867 seconds

LEAVE相位器与许多其他现代编程语言中的DEFER功能相对应。

保持和撤消

和移相器是LEAVE移相器的特殊情况。 根据周围块的返回值调用它们。 如果在返回值上调用方法的结果为True ,则将调用任何KEEP移相器。 如果定义的调用结果不是True ,则将调用任何UNDO移相器。 该块的实际值将在主题中可用(即$ _ )。

一个人为的例子可以阐明:

# Perl 6      
for
42
, Nil
{
    KEEP
{
say
"Keeping because of $_"
}
    UNDO
{
say
"Undoing because of $_.perl()"
}
   
$_
;
}
# Keeping because of 42
# Undoing because of Nil

就像现实生活中的例子一样:

# Perl 6      
{
    KEEP
$dbh
. commit
;
    UNDO
$dbh
. rollback
;
   
...    
# set up a big transaction in a database
    True
;  
# indicate success
}

因此,如果在数据库中设置大事务时出现任何问题, UNDO移相器将确保可以回滚该事务。 相反,如果成功离开该块,则KEEP移相器将自动提交事务。

KEEPUNDO移相器为您提供了穷人 。

之前和之后

移相器是ENTER移相器的特殊版本。 相位器是LEAVE相位器的特例。

如果可以进入模块,则PRE移相器应返回一个真值。 如果没有,则将引发异常。 POST相位器接收该Block的返回值,并且如果可以离开该Block而不会引发异常,则可以返回一个true值。

一些例子:

# Perl 6      
{
    PRE
{
say
"called PRE"
; False
}    
# throws exception
   
...
}
say
"we made it!"
;                    
# never makes it here
# called PRE
# Precondition '{ say "called PRE"; False }' failed
# Perl 6
{
    PRE  
{
say
"called PRE"
; True  
}  
# does NOT throw exception
    POST
{
say
"called POST"
; False
}  
# throws exception
    say
"inside the block"
;            
# also returns True
}
say
"we made it!"
;                    
# never makes it here
# called PRE
# inside the block
# called POST
# Postcondition '{ say "called POST"; False }' failed

如果只想检查某个块是否返回特定的值或类型,则最好为该块指定一个返回签名。 注意:

# Perl 6      
{
    POST
{
$_
~~ Int
}  
# check if the return value is an Int
   
...                  
# calculate result
   
$result
;
}

只是一种非常round回的说法:

# Perl 6      
-->
Int
{
               
# return value should be an Int
   
...                  
# calculate result
   
$result
;
}

通常,仅在必要的检查非常涉及并且无法简化为简单的类型检查的情况下,才使用POST相位器。

环路移相器

循环移相器是特定于循环结构的特殊类型的块移相器。 一个在第一次迭代( )之前运行,一个在每次迭代( )之后运行,一个在最后一次迭代( )之后运行。

名称 描述
FIRST 在第一次迭代之前运行
NEXT 在每个完成的迭代之后或与下一个迭代一起运行
LAST 在最后一次迭代之后或最后一次运行

名称不言自明。 一个人为的例子:

# Perl 6      
my
$total
=
0
;
for
1
..
5
{
   
$total
+=
$_
;
    LAST  say
"------ + \n $total.fmt('%6d')"
;
    FIRST say
"values \n ======"
;
    NEXT  say
. fmt
(
'%6d'
)
;
}
# values
# ======
#      1
#      2
#      3
#      4
#      5
# ------ +
#     15

循环结构包括 ; ; 以及 。

如果需要,可以将Loop相位器与其他Block相位器一起使用,但这通常是不必要的。

摘要

除了在Perl 6中具有与之相对应的Perl 5特殊块(称为相位器)之外,Perl 6还具有许多与代码和循环结构块相关的特殊用途的相位器。 Perl 6还具有与异常处理和警告,事件驱动的编程以及文档(pod)解析有关的阶段器。 这些将在本系列的后续文章中介绍。

翻译自:

带通滤波中零相位和最小相位

转载地址:http://vmdzd.baihongyu.com/

你可能感兴趣的文章
Java Bigdecimal使用
查看>>
SQL注入之绕过WAF和Filter
查看>>
jquery validate使用方法
查看>>
DataNode 工作机制
查看>>
windows系统下安装MySQL
查看>>
错误提示总结
查看>>
实验二+070+胡阳洋
查看>>
Linux IPC实践(3) --具名FIFO
查看>>
Qt之模拟时钟
查看>>
第一次接触安卓--记于2015.8.21
查看>>
(转)在分层架构下寻找java web漏洞
查看>>
mac下多线程实现处理
查看>>
C++ ifstream ofstream
查看>>
跟初学者学习IbatisNet第四篇
查看>>
seL4环境配置
查看>>
Git报错:insufficient permission for adding an object to repository database .git/objects
查看>>
ajax跨域,携带cookie
查看>>
BZOJ 1600: [Usaco2008 Oct]建造栅栏( dp )
查看>>
洛谷 CF937A Olympiad
查看>>
Codeforces Round #445 C. Petya and Catacombs【思维/题意】
查看>>