2010-08-26 60 views
4

Perl被認爲是通用編程語言嗎?Perl提供的其他語言不支持哪些編譯時功能?

Wikipedia

Perl的閱讀有關它具有圖靈完全語法解析,因爲可通過在編譯階段執行的運行時代碼的影響。[41]因此,Perl不能由直接的Lex/Yacc詞法分析器/解析器組合來分析。相反,解釋器實現自己的詞法分析器,它與修改過的GNU野牛分析器進行協調,以解決語言中的歧義問題。

通常會說「只有perl可以解析Perl」,這意味着只有Perl解釋器(perl)才能解析Perl語言(Perl),但即使這樣也不是真的。由於Perl解釋器可以在其編譯階段模擬圖靈機,因此需要確定停機問題以便在每種情況下完成解析。這是一個長期以來的結果,暫停問題是不可判定的,因此甚至連perl都不能解析Perl。 Perl使得用戶可以在自己的編譯階段訪問其完整的編程能力。理論純度方面的成本很高,但實際的不便似乎很少見。

所以,它說,雖然Perl有圖靈完整的徽章,它與其他語言不同,因爲給了「在自己的編譯階段,以充分發揮其編程能力的用戶訪問」。那是什麼意思? Perl在編譯階段爲我提供了哪些編程能力?

+0

社區Wiki? – fredley 2010-08-26 13:39:34

+5

這是一個非主觀答案的恰當問題。 – muhmuhten 2010-08-26 13:42:54

+2

這個維基百科條目需要編輯。即使編譯完成,編譯器也不需要在編譯過程中「決定」暫停問題。這是循環邏輯。 – dawg 2010-08-26 13:49:08

回答

6

Perl沒有任何功能不會出現在任何其他語言中。 Lisp可以做任何事情(Lisp是示例,在這裏)。因此,也許我們可以縮小問題的範圍,Perl的功能是什麼,使廣泛的行爲擺動是一件容易的事情。

  • BEGIN塊(END塊,太。),其期間編譯改變行爲。所以我可以編寫Perl代碼來改變要加載的模塊的位置。

    即使下面的代碼可能有不同的含義。

    use Frobnify; 
    Frobnify->new->initialize; 
    

    ,因爲我已經改變了這裏Frobnify負載從:

    BEGIN { 
        if ([ localtime ]->[6] == 2) { 
         s|^/var|/var/days/tuesday| foreach @INC; 
        } 
    } 
    

    所以在星期二,我加載/var/days/tuesday/perl/lib/Frobnify.pm

  • Source Filters可以通過編程編輯將執行代碼。 (源代碼過濾器上的CAVEAT!)(粗略地和大致等同於LISP宏)

  • BEGIN有一些區別是@INC hooks。因爲我可以在開始時修改@INC以查看更改加載的內容。我可以在@INC陣列的前面設置一個子程序來加載我想加載的任何東西。掛鉤可以接收加載Frobnify的請求,並通過加載Defrobnify.pm來響應該請求。

  • 與此相關的還有Symbol Manipuation。加載Defrobnify.pm後,我可以這樣做:

    *Frobnify:: = \*Defrobnify::; 
    

    現在Frobnify->new創建Defrobnify對象!

+0

LISP比Perl更普遍。 – delnan 2010-08-26 13:50:04

+4

@delnan它取決於你的意思是「編譯」。 Perl被編譯爲字節碼。 @Axeman:「LISP可以做任何事情」:你是什麼意思?任何圖靈完全語言都可以在可計算性上做任何事情,但是我還沒有看到一種語言不缺少我喜歡的其他語言的特性。 – 2010-08-26 13:52:49

+0

@delnan:Perl總是*編譯,所以這是不可能的。我對LISP不是最新的,我的理解是它被解釋了。 – Axeman 2010-08-26 14:01:53

1

簡單的答案是,BEGIN塊提供圖靈完備:

BEGIN { 
    my $foo = turing_machine_simulator($program); 
} 

BEGIN塊儘快Perl編譯看到他們執行。這意味着可以要求編譯器執行任意複雜的任務。 Perl可以做什麼,它可以在編譯階段完成。

4

子程序原型是一個編譯時間功能,或多或少是Perl專用的。 Perl的許多內置函數在其參數(標量,列表,引用,代碼塊,捕獲)上施加了特殊類型的上下文。原型是將某些功能移植到用戶定義的子例程的一種方式。

例如,Perl允許您用(&)原型有效地生成新的句法結構。這是在模塊中使用像Try::Tinytrycatch關鍵字添加到語言:

try { 
      die "foo"; 
    } catch { 
      warn "caught error: $_"; # not [email protected] 
    }; 

這工作,因爲trycatch被聲明爲sub try (&;@) { ... }sub name {...}語法相當於BEGIN { *name = sub {...} }這意味着它具有編譯時效果。在try的情況下,(&;@)原型告訴編譯器,只要它看到標識try,第一個參數必須是裸塊,並且在塊之後是可選列表。

這只是一個原型的例子,他們能夠做很多其他的事情:

$ imposes scalar context on an argument 
& imposes code context on an argument 
@ imposes list context on an argument 
% imposes list context (with an even number of elements) 
* imposes glob context on the argument 
\$ imposes scalar reference context 
\@ imposes array reference context 
    ... for the rest of the sigils 

由於他們的權力(而沒有其他語言)的原型可以是混亂和適度最好使用。 (就像Perl的其他高級功能一樣)。

+0

此外,名稱是一個問題。 C原型與Perl原型完全不同。 – daotoad 2010-08-27 00:06:29