perl6 函数类似于"car cdr cons" 方案?
perl6 functions similar to "car cdr cons" in scheme?
我真的很喜欢 perl6 和 scheme。我想知道perl6中是否有类似于scheme中"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); }
谢谢。
Perl 6 lists/arrays 不是链表。
但是,Pair
类型可用于构建链表,并提供这三个 Lisp 函数的功能。
使用嵌套 Pair
s
A Pair
represents a key-value pair. For example when iterating a Hash
,你得到一个 Pair
的序列。
如果您将 Pair
视为一个 cons 单元格,那么您可以像 Lisp 一样构建一个链表作为一个 Pair
,它具有另一个 Pair
作为它的值,这依次有另一个 Pair
作为其值,依此类推。
=>
运算符(Pair
构造函数)完成了cons. 的作用
.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 的 length 或 append 功能等同的功能,那么您必须自己编写这些功能。所有内置的列表处理例程都采用正常的 Perl 6 列表或兼容的 Iterable
类型,而 Pair
不是。
使用普通的 Perl 6 列表
如果你想使用普通的 Perl 6 lists/arrays 作为你的数据结构,但要为它们实现 Lisp 函数的行为,我会这样写:
sub cons ($x, $y) { $x, |$y }
sub car (@y) { @y[0] }
sub cdr (@y) { @y[1..*] }
一些评论:
- 而不是使用
flat
, I used the |
operator 将 $y
的元素滑入外部列表。
first
函数没有执行您在代码中期望的操作。 它用于搜索 列表。它将第一个参数(在您的情况下 $aList
)解释为谓词,其余参数(在您的情况下 none)解释为要搜索的列表,因此在您的情况下它总是 returns Nil
.
要返回列表的第一个元素,您可以使用 [ ]
positional subscripting operator 代替,就像我在这里所做的那样。
return
关键字是可选的;自动返回函数最后一条语句的结果。
这是另一组函数,类似于您的原始函数,并且使用 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 式的语法。
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;
我真的很喜欢 perl6 和 scheme。我想知道perl6中是否有类似于scheme中"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); }
谢谢。
Perl 6 lists/arrays 不是链表。
但是,Pair
类型可用于构建链表,并提供这三个 Lisp 函数的功能。
使用嵌套 Pair
s
A Pair
represents a key-value pair. For example when iterating a Hash
,你得到一个 Pair
的序列。
如果您将 Pair
视为一个 cons 单元格,那么您可以像 Lisp 一样构建一个链表作为一个 Pair
,它具有另一个 Pair
作为它的值,这依次有另一个 Pair
作为其值,依此类推。
=>
运算符(Pair
构造函数)完成了cons. 的作用
.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 的 length 或 append 功能等同的功能,那么您必须自己编写这些功能。所有内置的列表处理例程都采用正常的 Perl 6 列表或兼容的 Iterable
类型,而 Pair
不是。
使用普通的 Perl 6 列表
如果你想使用普通的 Perl 6 lists/arrays 作为你的数据结构,但要为它们实现 Lisp 函数的行为,我会这样写:
sub cons ($x, $y) { $x, |$y }
sub car (@y) { @y[0] }
sub cdr (@y) { @y[1..*] }
一些评论:
- 而不是使用
flat
, I used the|
operator 将$y
的元素滑入外部列表。 first
函数没有执行您在代码中期望的操作。 它用于搜索 列表。它将第一个参数(在您的情况下$aList
)解释为谓词,其余参数(在您的情况下 none)解释为要搜索的列表,因此在您的情况下它总是 returnsNil
.
要返回列表的第一个元素,您可以使用[ ]
positional subscripting operator 代替,就像我在这里所做的那样。return
关键字是可选的;自动返回函数最后一条语句的结果。
这是另一组函数,类似于您的原始函数,并且使用 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 式的语法。
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;