[英]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
/ grep
( List::Util
和reduce
?)
我有人能幫我填補這里的空白嗎? Perl可以輕松完成以上哪些操作(並且有一個簡單的例子)並且有哪些例子可以解決它?
在計算機科學中,如果將編程語言視為一等公民,則稱其具有一流的功能。 具體來說,這意味着該語言支持將函數作為參數傳遞給其他函數,將它們作為其他函數的值返回,並將它們分配給變量或將它們存儲在數據結構中。
在Perl中:
my $print_something = sub { print "Something\n" };
sub do_something {
my ($function) = @_;
$function->();
}
do_something($print_something);
在數學和計算機科學中,高階函數(也是函數形式,函數或函子)是至少執行以下任一操作的函數:
將一個或多個函數作為輸入
輸出一個功能
在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 (我不是這本書的附屬,誠實 - 它似乎只是關於這個主題的關鍵文本之一)。
這里的核心概念似乎是 - 在perl中創建一個'鏈表'(使用面向對象的技術),但在你的'結束標記'中嵌入了一個代碼引用,用於評估你是否已經達到目標。
“GarbageCollection(GC),也稱為自動內存管理,是堆內存的自動回收。”
Perl通過引用計數執行此操作,並在不再引用它們時釋放它們。 請注意,這可能會影響您(可能!)在函數式編程時更有可能遇到的某些事情。
具體而言 - perldoc perlref
中涵蓋的循環引用
TypeInference是一個程序的分析,用於推斷一些或所有表達式的類型,通常在CompileTime
Perl會根據需要隱式地來回轉換值。 通常這很好用,你不需要弄亂它。 有時您需要通過進行顯式數字或字符串操作來“強制”該過程。 通常,這可以通過添加0或連接空字符串來實現。
您可以使用dualvars
重載標量以執行不同的操作
尾調用優化(或尾調用合並或尾調用消除)是TailRecursion的一般化:如果例程在返回之前做的最后一件事是調用另一個例程,而不是做一個跳轉和添加堆棧幀緊接着是一個pop-stack-frame-and-return-to-calller,它應該是安全的,只需跳轉到第二個例程的開頭,讓它重新使用第一個例程的堆棧幀(環境)。
它會工作,但如果您的遞歸深度> 100,它會發出警告。 您可以通過添加:
no warnings 'recursion';
但顯然 - 你需要對遞歸深度和內存占用略微謹慎。
據我所知,沒有任何特定的優化 ,如果你想以有效的方式做這樣的事情,你可能需要(有效地)展開你的遞歸並迭代。
Perl支持Tailcalls。 要么看到轉到⊂符號,要么看看
Sub::Call::Tail
提供的neater語法
列表推導是許多現代FunctionalProgrammingLanguages的一個特征。 根據某些規則,它們為GeneratingElements提供了簡潔的表示法? 在列表中。 列表理解是SyntacticSugar,用於函數concat,map和filter的應用程序組合
Perl有map
, grep
, reduce
。
它還可以應對范圍和重復的擴展:
my @letters = ( "a" .. "z" );
所以你可以:
my %letters = map { $_ => 1 } ( "A" .. "z" );
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.