Perl的哪些功能使其成为一种功能性编程语言? [英] Which features of Perl make it a functional programming language?

查看:101
本文介绍了Perl的哪些功能使其成为一种功能性编程语言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

灵感来源: https://stackoverflow.com/我发现: hop.perl.plover.com/rel =nofollow noreferrer>高级Perl



它让我怀疑Perl是一个函数编程语言。现在,我明白功能编程是一种技术(很像面向对象)。

然而,我已经找到了是什么使得函数式编程语言


  • 首先




  • 词法分析

  • 单一分配

  • 懒惰评估

  • 垃圾收集

  • 类型推断

  • 尾巴呼叫优化

  • 列表理解

  • Monadic特效



现在我熟悉一些这些:

例如,垃圾收集是Perl引用计数和释放内存,当不再需要时。

词法分析甚至是FAQ的一部分:什么是闭包? - 这里可能有更好的文章: http://www.perl.com/pub/2002/05/29/closure.html



但是例如,我认为这是指 map / grep List :: Util reduce ?)

<我能帮助我填补空白吗?以上哪一项可以让Perl轻松实现(并且有一个简单的例子),并且它有倒塌的例子吗? http://www.perlmonks.org/?node_id=450922 =nofollow noreferrer> Perl僧侣们对功能性程序设计的咆哮

高阶Perl

C2.com函数式编程定义

头等功能



在计算机科学中,如果一种编程语言把功能当作一等公民来对待,那么它就被认为具有一流的功能。具体来说,这意味着语言支持将函数作为参数传递给其他函数,并将它们作为其他函数的值返回,并将它们赋值给变量或将其存储在数据结构中。



所以在Perl中:

  my $ print_something = sub {printSomething \\\
};

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

do_something($ print_something);



判决:本地支持



高阶函数




在数学和计算机科学中,高阶函数(也是函数形式,函数或函子)是一个至少执行以下其中一项的函数:


  • 以一个或多个函数作为输入


  • 输出函数

  • b $ b

参考 perlmonks上的这篇文章


在Perl术语中,我们经常称它们为回调,工厂,以及返回代码引用(通常是闭包)的函数。



结论:本地支持



Lexical Closure



在perl FAQ中,我们有关于 什么是关闭?


闭包是一个计算机科学术语,具有精确但难以解释的含义。通常,闭包在Perl中以匿名子例程的形式实现,持久引用词汇变量在它们自己的作用域之外。这些词汇神奇地指的是定义子程序时的变量(深度绑定)。



闭包在编程语言中最常用,您可以获得返回值一个函数本身就是一个函数,就像你在Perl中一样。

这篇文章的解释可能更清楚一点:实现封闭

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

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



结论:本地支持



模式匹配




在纯函数语言和本页面的上下文中,模式匹配是一种调度机制:选择函数的哪个变体是正确调用的函数。受标准数学符号的启发。

调度表是最接近的近似值 - 本质上是匿名子代码或代码引用的散列。

  use strict; 
使用警告;

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

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

因为它只是一个散列,你可以添加代码引用和匿名子例程。 (注意 - 与面向对象编程不完全不同)
$ b $ h2>结论:解决方法

单一作业




改变现有值的任何赋值(例如x:= x + 1)在纯功能语言中都是不允许的。 4 在函数式编程中,不鼓励赋值赋予单个赋值,也称为初始化。单一赋值是名称绑定的一个例子,与本文所述的赋值不同,它只能执行一次,通常是在创建变量时;

我不确定 perl 真的没有这个。最接近的近似值可能是reference / anonymous subs或者 constant 。

结论:不支持



懒惰评估




等待最后一刻评估表达式,特别是用于优化可能不使用表达式值的算法。

再次回到
高阶Perl (I'这本书不属于本书,诚实 - 它似乎是关于这个主题的关键文本之一)。


这里的核心概念似乎是 - 在perl中创建一个'链表'(使用面向对象的技术),但是在你的'结束标记'处嵌入一个代码引用来评估如果你有这么远。

判决:解决方法




Perl通过引用计数来执行此操作,并在不再引用时释放它们。请注意,这可能会影响您在功能性编程时可能遇到的某些事情(可能!)。 noreferrer> perldoc perlref

判决:原生支持



类型推断




TypeInference是一个程序的分析,用于推断某些或所有表达式的类型,通常在CompileTime中



Perl会根据需要来隐式地转换值。通常这种方式工作得很好,以至于你不需要搞砸它。偶尔你需要通过明确的数字或​​字符串操作来强制进程。通常,这是通过加0或连接一个空字符串。


你可以通过使用 dualvars



结论:原生支持



尾部呼叫优化




尾部呼叫优化(或尾部呼叫合并或尾部呼叫消除)是一种泛化TailRecursion:如果一个例程在返回之前做的最后一件事情是调用另一个例程,而不是做一个跳转和添加栈帧,紧接着是一个弹出栈帧和返回调用者,它应该是安全的,只需跳到第二个例程的开始,让它重新使用第一个例程的堆栈框架(环境)。

为什么Perl是如此害怕深度递归?



它会工作,但它会警告你的递归深度是否大于100。您可以通过添加以下内容来禁用此功能:

 无警告'递归'; 

但显然 - 您需要对递归深度和内存占用情况稍微谨慎。



据我所知,没有任何特别的优化,如果您想以高效的方式执行此类操作,你可能需要(有效地)展开你的递归并迭代。


perl支持Tailcalls。要么看到goto⊂符号,或者查看由 Sub :: Call :: Tail



$ b $提供的整理语法b

结论:本地



列表理解




列表解析是许多现代FunctionalProgrammingLanguages的一个特性。根据特定的规则,它们为GeneratingElements提供简洁的符号?在一个列表中。
列表理解是SyntacticSugar,用于函数concat,map和filter的应用程序组合

Perl具有 map grep reduce



它也可以处理范围和重复次数的扩展:

pre $ my @letters =(a。 。z);

所以你可以:

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



判决:原生( List :: Utils 是一个核心模块)



Monadic effects

a>

...不行,仍然遇到这些问题。它要么比我想象的要简单得多,要么复杂得多。

如果任何人有更多的东西,请切入或编辑这篇文章或...东西。对于一些涉及的概念,我仍然是一个粗略的概念,所以这篇文章更多的是一个起点。

Inspired a little by: https://stackoverflow.com/questions/30977789/why-is-c-not-a-functional-programming-language

I found: Higher Order Perl

It made me wonder about the assertion that Perl is a functional programming language. Now, I appreciate that functional programming is a technique (much like object oriented).

However I've found a list of what makes a functional programming language:

  • First Class functions
  • Higher Order Functions
  • Lexical Closures
  • Pattern Matching
  • Single Assignment
  • Lazy Evaluation
  • Garbage Collection
  • Type Inference
  • Tail Call Optimization
  • List Comprehensions
  • Monadic effects

Now some of these I'm quite familiar with:

Garbage collection, for example, is Perl reference counting and releasing memory when no longer required.

Lexical closures are even part of the FAQ: What is a closure? - there's probably a better article here: http://www.perl.com/pub/2002/05/29/closure.html

But I start to get a bit fuzzy on some of these - List Comprehensions, for example - I think that's referring to map/grep (List::Util and reduce?)

I anyone able to help me fill in the blanks here? Which of the above can Perl do easily (and is there an easy example) and are there examples where it falls down?

解决方案

Useful things that are relevant:

Perl monks rant about functional programming

Higher Order Perl

C2.com functional programming definitions

First Class functions

In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens. Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.

So in Perl:

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

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

do_something($print_something);

Verdict: Natively supported

Higher Order Functions

In mathematics and computer science, a higher-order function (also functional form, functional or functor) is a function that does at least one of the following:

  • takes one or more functions as an input

  • outputs a function

With reference to this post on perlmonks:

In Perl terminology, we often refer to them as callbacks, factories, and functions that return code refs (usually closures).

Verdict: Natively supported

Lexical Closures

Within the perl FAQ we have questions regarding What is a closure?:

Closure is a computer science term with a precise but hard-to-explain meaning. Usually, closures are implemented in Perl as anonymous subroutines with lasting references to lexical variables outside their own scopes. These lexicals magically refer to the variables that were around when the subroutine was defined (deep binding).

Closures are most often used in programming languages where you can have the return value of a function be itself a function, as you can in Perl.

This is explained perhaps a little more clearly in the article: Achieving Closure

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

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

Verdict: Natively supported

Pattern Matching

In the context of pure functional languages and of this page, Pattern Matching is a dispatch mechanism: choosing which variant of a function is the correct one to call. Inspired by standard mathematical notations.

Dispatch tables are the closest approximation - essentially a hash of either anonymous subs or code refs.

use strict;
use warnings;

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

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

Because it's just a hash, you can add code references and anonymous subroutines too. (Note - not entirely dissimilar to Object Oriented programming)

Verdict: Workaround

Single Assignment

Any assignment that changes an existing value (e.g. x := x + 1) is disallowed in purely functional languages.4 In functional programming, assignment is discouraged in favor of single assignment, also called initialization. Single assignment is an example of name binding and differs from assignment as described in this article in that it can only be done once, usually when the variable is created; no subsequent reassignment is allowed.

I'm not sure perl really does this. The closest approximation might be references/anonymous subs or perhaps constant.

Verdict: Not Supported

Lazy Evaluation

Waiting until the last possible moment to evaluate an expression, especially for the purpose of optimizing an algorithm that may not use the value of the expression.

Examples of lazy evaluation techniques in Perl 5?

And again, coming back to Higher Order Perl (I'm not affiliated with this book, honest - it just seems to be one of the key texts on the subject).

The core concept here seems to be - create a 'linked list' in perl (using object oriented techniques) but embed a code reference at your 'end marker' that evaluates if you ever get that far.

Verdict: Workaround

Garbage Collection

"GarbageCollection (GC), also known as automatic memory management, is the automatic recycling of heap memory."

Perl does this via reference counting, and releasing things when they are no longer referenced. Note that this can have implications for certain things that you're (probably!) more likely to encounter when functional programming.

Specifically - circular references which are covered in perldoc perlref

Verdict: Native support

Type Inference

TypeInference is the analysis of a program to infer the types of some or all expressions, usually at CompileTime

Perl does implicitly cast values back and forth as it needs to. Usually this works well enough that you don't need to mess with it. Occasionally you need to 'force' the process, by making an explicit numeric or string operation. Canonically, this is either by adding 0, or concatenating an empty string.

You can overload a scalar to do different things in by using dualvars

Verdict: Native support

Tail Call Optimization

Tail-call optimization (or tail-call merging or tail-call elimination) is a generalization of TailRecursion: If the last thing a routine does before it returns is call another routine, rather than doing a jump-and-add-stack-frame immediately followed by a pop-stack-frame-and-return-to-caller, it should be safe to simply jump to the start of the second routine, letting it re-use the first routine's stack frame (environment).

Why is Perl so afraid of "deep recursion"?

It'll work, but it'll warn if your recursion depth is >100. You can disable this by adding:

no warnings 'recursion';

But obviously - you need to be slightly cautious about recursion depth and memory footprint.

As far as I can tell, there isn't any particular optimisation and if you want to do something like this in an efficient fashion, you may need to (effectively) unroll your recursives and iterate instead.

Tailcalls are supported by perl. Either see the goto ⊂ notation, or see the neater syntax for it provided by Sub::Call::Tail

Verdict: Native

List Comprehensions

List comprehensions are a feature of many modern FunctionalProgrammingLanguages. Subject to certain rules, they provide a succinct notation for GeneratingElements? in a list. A list comprehension is SyntacticSugar for a combination of applications of the functions concat, map and filter

Perl has map, grep, reduce.

It also copes with expansion of ranges and repetitions:

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

So you can:

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

Verdict: Native (List::Utils is a core module)

Monadic effects

... nope, still having trouble with these. It's either much simpler or much more complex than I can grok.

If anyone's got anything more, please chip in or edit this post or ... something. I'm still a sketchy on some of the concepts involved, so this post is more a starting point.

这篇关于Perl的哪些功能使其成为一种功能性编程语言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆