Perl6 features similar to "car cdr cons" in schema?

I really like perl6 and the circuit. I am wondering if there are functions in perl6 similar to the cons, car, cdr functions in the circuit? What I'm doing seems cumbersome:

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); } 

Thanks.

+5
source share
2 answers

Perl 6 lists / arrays are not linked by list.
However, the Pair type can be used to build linked lists and provides the functionality of these three Lisp functions.

Using nested Pair s

A Pair represents a key-value pair. For example, when you repeat Hash you get the sequence Pair s.

If you think of Pair as a cons cell, then you can build linked lists ร  la Lisp as a Pair , which has a different Pair value, which in turn has a different Pair as its value, etc.

  • The operator => (constructor Pair ) acts as a cons .
  • The .key method acts as a car .
  • The .value method plays the role of cdr .

Example:

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

The operator => is right-associative, so the first line can also be written without parentheses:

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

If you want to declare Lisp functions under their familiar names, it will look like this:

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

Please note, however, that there are no built-in convenience functions for processing a list with such linked Pair lists. Therefore, if you want to fulfill the equivalent of length functions or add , etc., then you have to write these functions yourself. All the built-in list processing procedures assume regular Perl 6 lists or compatible Iterable types that Pair are not.

Using Regular Perl 6 Lists

If you want to use regular Perl 6 lists / arrays as your data structure, but implement the behavior of the Lisp functions for them, I would write this as follows:

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

Some comments:

  • Instead of flat I used | statement to remove $y items in an external list.
  • The first function does not do what you expect in your code. It is designed to search the list. It interprets the first argument (in your case $aList ) as a predicate, and the remaining arguments (in your case not) as a search list, so in your case it always returns Nil .
    To return the first element of the list, you can instead use the [ ] positional subscriber operator , as I am here.
  • The return keyword is optional; The result of the last function statement is automatically returned.
+8
source

Here's a different set of functions similar to your originals, and using prefix operators for 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) } 

They provide almost lisp -ish syntax if you want.

 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; 
+1
source

All Articles