perl6的功能类似于" car cdr cons"在计划?

时间:2016-09-11 17:24:53

标签: arrays perl6 cons cdr

我真的很喜欢perl6和计划。我想知道perl6中是否有类似于" cons,car,cdr"方案中的功能?我一直在做的事情很麻烦:

sub cons($a, $aList) { return flat($a, $aList); } # sometimes flat is undesired;
sub car($aList) { return first($aList); }
sub cdr($aList) { return tail($aList.elems - 1); }

感谢。

2 个答案:

答案 0 :(得分:9)

Perl 6列表/数组不是链表 但是,Pair类型可用于构建链接列表,并提供这三个Lisp函数的功能。

使用嵌套的Pair s

Pair表示键值对。例如,在迭代Hash时,您会获得一系列Pair s。

如果您将Pair视为一个缺点单元格,那么您可以将Lisp链接列表构建为Pair,并将另一个Pair作为其值,还有另一个Pair作为其值,依此类推。

  • =>运算符(Pair构造函数)履行缺点的角色。
  • .key方法履行 car 的作用。
  • .value方法履行 cdr
  • 的角色

示例:

my $l = (1 => (2 => (3 => (4 => (5 => Nil)))));
say $l.key;    # 1
say $l.value;  # 2 => 3 => 4 => 5 => Nil

=>运算符是右关联的,因此第一行也可以在没有括号的情况下编写:

my $l = 1 => 2 => 3 => 4 => 5 => Nil;

如果您想以熟悉的名称声明Lisp函数,它将如下所示:

sub cons ($x, $y)  { $x => $y }
sub car  (Pair $y) { $y.key   }
sub cdr  (Pair $y) { $y.value }

但请注意,没有内置的便利功能可以使用这种基于Pair的链接列表进行列表处理。因此,如果你想做相当于Scheme的长度追加等功能,那么你必须自己编写这些函数。所有内置列表处理例程都假设是普通的Perl 6列表或兼容的Iterable类型,Pair不是。{/ p>

使用普通的Perl 6列表

如果你想使用普通的Perl 6列表/数组作为你的数据结构,但是为它们实现了Lisp函数的行为,我会这样写:

sub cons ($x, $y) { $x, |$y  }
sub car  (@y)     { @y[0]    }
sub cdr  (@y)     { @y[1..*] }

一些意见:

  • 我使用flat$y的元素放入外部列表,而不是使用| operator
  • first函数无法在您的代码中执行您所期望的操作。 用于搜索列表。它将第一个参数(在您的情况下为$aList)解释为谓词,将剩余的参数(在您的情况下为无)解释为要搜索的列表,因此在您的情况下它始终返回Nil
    要返回列表的第一个元素,您可以使用[ ] positional subscripting operator,就像我在这里做的那样。
  • return关键字是可选的;自动返回函数的最后一个语句的结果。

答案 1 :(得分:1)

这是另一组功能,类似于您的原件,并使用car / cdr的前缀运算符:

sub prefix:<car>(List $l) is tighter(&infix:<xx>) { $l.head }
sub prefix:<cdr>(List $l) is tighter(&infix:<xx>) { $l.tail(*-1).list }
sub cons($item, List $l) { ($item, |$l) }

如果您愿意,这些语法几乎可以提供lisp-ish语法。

my @l = (1, 2, 3, 4);
my $l = |@l;

say "Array";
say "car: ", (car @l).perl;
say "cdr: ", (cdr @l).perl;

say "List";
say "car: ", (car $l).perl;
say "cdr: ", (cdr $l).perl;

say "Literal";
say "car: ", (car (4, 3, 2, 1)).perl;
say "cdr: ", (cdr (4, 3, 2, 1)).perl;

say "cons: ", (cons car $l, cdr $l).perl;