Generics in Perl

Perl does not have built-in support for generics. However, we can simulate some aspects of generic programming using Perl’s dynamic typing and references. Here’s an equivalent implementation:

use strict;
use warnings;

# SlicesIndex takes an array reference and a value, and returns the index
# of the first occurrence of the value in the array, or -1 if not present.
sub SlicesIndex {
    my ($arr_ref, $v) = @_;
    for my $i (0 .. $#$arr_ref) {
        return $i if $arr_ref->[$i] eq $v;
    }
    return -1;
}

# List is a singly-linked list that can hold values of any type.
package List {
    sub new {
        my $class = shift;
        bless { head => undef, tail => undef }, $class;
    }

    sub push {
        my ($self, $v) = @_;
        my $new_elem = { val => $v, next => undef };
        if (!$self->{tail}) {
            $self->{head} = $self->{tail} = $new_elem;
        } else {
            $self->{tail}->{next} = $new_elem;
            $self->{tail} = $new_elem;
        }
    }

    sub all_elements {
        my $self = shift;
        my @elems;
        my $e = $self->{head};
        while ($e) {
            push @elems, $e->{val};
            $e = $e->{next};
        }
        return \@elems;
    }
}

# Main function
sub main {
    my @s = qw(foo bar zoo);
    
    print "index of zoo: ", SlicesIndex(\@s, "zoo"), "\n";

    my $lst = List->new();
    $lst->push(10);
    $lst->push(13);
    $lst->push(23);
    print "list: ", join(", ", @{$lst->all_elements()}), "\n";
}

main();

This Perl code provides similar functionality to the Go example, with some key differences:

  1. Perl doesn’t have explicit type parameters. Instead, we use Perl’s dynamic typing to allow our functions and data structures to work with different types.

  2. The SlicesIndex function takes an array reference instead of a slice. It uses the eq operator for comparison, which works for both strings and numbers in Perl.

  3. The List class is implemented as a Perl package. It uses hash references to represent the linked list nodes.

  4. Instead of using generics, our List implementation can naturally hold values of any type due to Perl’s dynamic typing.

  5. The all_elements method returns an array reference instead of a slice.

  6. In the main function, we create and use our data structures similarly to the Go example, but without need for explicit type parameters.

To run this program, save it to a file (e.g., generics.pl) and execute it with the Perl interpreter:

$ perl generics.pl
index of zoo: 2
list: 10, 13, 23

While Perl doesn’t have built-in generics, its dynamic typing and flexible data structures allow for writing code that works with multiple types without explicit type parameters.