簡體   English   中英

Perl的哪些功能使它成為一種函數式編程語言?

[英]Which features of Perl make it a functional programming language?

靈感來自: https//stackoverflow.com/questions/30977789/why-is-c-not-a-functional-programming-language

我發現: 高階Perl

這讓我對Perl是一種函數式編程語言的斷言感到疑惑。 現在,我欣賞函數式編程是一種技術(很像面向對象)。

但是我找到了一個函數式編程語言的列表:

  • 頭等艙功能
  • 高階函數
  • 詞匯封閉
  • 模式匹配
  • 單一作業
  • 懶惰的評價
  • 垃圾收集
  • 類型推斷
  • 尾調用優化
  • 列表理解
  • 單子效應

現在其中一些我很熟悉:

例如,垃圾收集是Perl引用計數,並在不再需要時釋放內存。

詞匯封閉甚至是FAQ的一部分: 什么是封閉? - 這里可能有更好的文章: http//www.perl.com/pub/2002/05/29/closure.html

但是我開始對其中的一些感到有點模糊 - 例如List Insrehensions - 我認為這是指map / grepList::Utilreduce ?)

我有人能幫我填補這里的空白嗎? Perl可以輕松完成以上哪些操作(並且有一個簡單的例子)並且有哪些例子可以解決它?

有用的東西:

Perl僧侶們對功能編程大肆宣揚

高階Perl

C2.com函數式編程定義

頭等艙功能

在計算機科學中,如果將編程語言視為一等公民,則稱其具有一流的功能。 具體來說,這意味着該語言支持將函數作為參數傳遞給其他函數,將它們作為其他函數的值返回,並將它們分配給變量或將它們存儲在數據結構中。

在Perl中:

my $print_something = sub { print "Something\n" };

sub do_something {
    my ($function) = @_;
    $function->();
}

do_something($print_something);

判決:本機支持

高階函數

在數學和計算機科學中,高階函數(也是函數形式,函數或函子)是至少執行以下任一操作的函數:

  • 將一個或多個函數作為輸入

  • 輸出一個功能

關於perlmonks的這篇文章

在Perl術語中,我們經常將它們稱為回調,工廠和返回代碼引用(通常是閉包)的函數。

判決:本機支持

詞匯封閉

在perl FAQ中我們有關於What is a closure?

閉包是一個計算機科學術語,具有精確但難以解釋的含義。 通常,閉包在Perl中作為匿名子例程實現,並且在其自己的作用域之外具有對詞法變量的持久引用。 這些詞匯神奇地指的是定義子程序時的變量(深度綁定)。

閉包最常用於編程語言中,您可以將函數的返回值本身作為函數,就像在Perl中一樣。

在文章中可能會更清楚地解釋這一點: 實現關閉

sub make_hello_printer {
    my $message = "Hello, world!";
    return sub { print $message; }
}

my $print_hello = make_hello_printer();
$print_hello->()

判決:本機支持

模式匹配

在純函數語言和此頁面的上下文中,模式匹配是一種調度機制:選擇函數的哪個變體是正確的調用。 受標准數學符號的啟發。

調度表是最接近的近似值 - 本質上是匿名子代碼或代碼引用的散列。

use strict;
use warnings;

sub do_it {
    print join( ":", @_ );
}
my $dispatch = {
    'onething'      => sub { print @_; },
    'another_thing' => \&do_it,
};

$dispatch->{'onething'}->("fish");

因為它just一個哈希,所以你也可以添加代碼引用和匿名子程序。 (注意 - 與面向對象的編程並不完全不同)

判決:解決方法

單一作業

在純函數式語言中不允許任何更改現有值的賦值(例如x:= x + 1)。 4在函數式編程中,不鼓勵賦值單個賦值,也稱為初始化。 單一賦值是名稱綁定的一個示例,與本文所述的賦值不同之處在於它通常只能創建一次,通常是在創建變量時; 不允許后續重新分配。

我不確定perl真的這樣做。 最接近的近似可能是引用/匿名子或可能是constant

判決:不支持

懶惰的評價

等到最后可能的時刻來評估表達式,特別是為了優化可能不使用表達式值的算法。

Perl 5中的惰性評估技術示例?

再一次,回到高階Perl (我不是這本書的附屬,誠實 - 它似乎只是關於這個主題的關鍵文本之一)。

這里的核心概念似乎是 - 在perl中創建一個'鏈表'(使用面向對象的技術),但在你的'結束標記'中嵌入了一個代碼引用,用於評估你是否已經達到目標。

判決:解決方法

垃圾收集

“GarbageCollection(GC),也稱為自動內存管理,是堆內存的自動回收。”

Perl通過引用計數執行此操作,並在不再引用它們時釋放它們。 請注意,這可能會影響您(可能!)在函數式編程時更有可能遇到的某些事情。

具體而言 - perldoc perlref中涵蓋的循環引用

判決:原生支持

類型推斷

TypeInference是一個程序的分析,用於推斷一些或所有表達式的類型,通常在CompileTime

Perl會根據需要隱式地來回轉換值。 通常這很好用,你不需要弄亂它。 有時您需要通過進行顯式數字或字符串操作來“強制”該過程。 通常,這可以通過添加0或連接空字符串來實現。

您可以使用dualvars重載標量以執行不同的操作

判決:原生支持

尾調用優化

尾調用優化(或尾調用合並或尾調用消除)是TailRecursion的一般化:如果例程在返回之前做的最后一件事是調用另一個例程,而不是做一個跳轉和添加堆棧幀緊接着是一個pop-stack-frame-and-return-to-calller,它應該是安全的,只需跳轉到第二個例程的開頭,讓它重新使用第一個例程的堆棧幀(環境)。

為什么Perl如此害怕“深度遞歸”?

它會工作,但如果您的遞歸深度> 100,它會發出警告。 您可以通過添加:

no warnings 'recursion';

但顯然 - 你需要對遞歸深度和內存占用略微謹慎。

據我所知,沒有任何特定的優化 ,如果你想以有效的方式做這樣的事情,你可能需要(有效地)展開你的遞歸並迭代。

Perl支持Tailcalls。 要么看到轉到⊂符號,要么看看Sub::Call::Tail提供的neater語法

判決:原住民

列表理解

列表推導是許多現代FunctionalProgrammingLanguages的一個特征。 根據某些規則,它們為GeneratingElements提供了簡潔的表示法? 在列表中。 列表理解是SyntacticSugar,用於函數concat,map和filter的應用程序組合

Perl有mapgrepreduce

它還可以應對范圍和重復的擴展:

my @letters = ( "a" .. "z" ); 

所以你可以:

my %letters = map { $_ => 1 } ( "A" .. "z" ); 

判決:Native( List::Utils是核心模塊)

單子效應

......不,仍然有這些問題。 它要么比我能理解得簡單得多,要么復雜得多。

如果有人有更多的東西,請填寫或編輯這篇文章或......某事。 我對所涉及的一些概念仍然很粗略,所以這篇文章更多的是一個起點。

非常好的話題,我想寫一篇題為“駱駝功能正常”的文章。 讓我貢獻一些代碼。

Perl也支持這種匿名函數

 sub check_config {
    my ( $class, $obj ) = @_;

    my $separator = ' > ';

    # Build message from class namespace.
    my $message = join $separator, ( split '::', $class );

    # Use provided object $obj or
    # create an instance of class with defaults, provided by configuration.
    my $object = $obj || $class->new;

    # Return a Function.
    return sub {
        my $attribute = shift;

        # Compare attribute with configuration,
        # just to ensure it is read from there.
        is $object->config->{$attribute},

            # Call attribute accessor so it is read from config,
            # and validated by type checking.
            $object->$attribute,

            # Build message with attribute.
            join $separator, ( $message, $attribute );
        }
}

sub check_config_attributes {
    my ( $class, $obj ) = @_;

    return sub {
        my $attributes = shift;
        check_config( $class, $obj )->($_) for (@$attributes);
        }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM