=pod

=encoding utf8

=head1 NAME

immutable - Immutable Data Structures for Perl

=head1 SYNOPSIS

    use immutable::0 ':all';

    $hash1 = imap(k1 => 123, k2 => 456);
    $k1 = $hash->{k1};                      # 123

    $hash1->{k3} = 789;                     # Error
    $hash2 = $hash1->set(k3 => 789);        # Correct
    $hash2->get('k3');                      # 789

    delete $hash2->{k3};                    # Error
    $hash3 = $hash2->del('k3');             # Correct

    $string = "$hash3";                     # <immutable::map 2 94394857332096>
    $id = $hash3->id;                       # 94394857332096
    $num = $hash3->size;                    # 2
    $hash3->is_empty;                       # false

=head1 DESCRIPTION

The C<immutable> module provides immutable versions of native Perl data structures.

Immutable data makes programs easier to reason about, and is foundational for functional programming and concurrency.

Immutable objects support both a tied interface (for use with Perl object access syntax) and an OO interface.

Mutating operation like C<$h->{x} = 1> and C<delete $h->{x}> will throw errors. You need to use the OO methods like C<$h->set(x => 1)> and C<$h->del('x')> which will return a new C<immutable::map> immutable hash object. By throwing errors on these operations, it will make things obvious when you pass them to existing code that tries to do a mutating operation.

=head1 EXPORTS

The C<immutable> module exports a number of sugar functions for creating new immutable objects.

=over

=item * C<iobj>

Create an immutable object from a plain scalar object.

C<$i_hash = iobj $hash;>

=item * C<imap>

Create an immutable hash (C<immutable::map>) object. Takes an even number (0 to n) of key and value arguments.

=over

=item * C<$i_hash = imap;> # Empty hash

=item * C<$i_hash = imap x => 1, y => 2;>

=back

=item * C<iseq>

Create an immutable array (C<immutable::seq>) object. Takes 0 or more scalar values to initialize the array.

=over

=item * C<$i_array = iseq;> # Empty array

=item * C<$i_array = iseq 1, 2, 3;>

=back

=item * C<iset>

Immutable set object. Not implemented yet.

=item * C<ilist>

Immutable lazy list. Not implemented yet.

=item * C<istr>

Immutable string. Not implemented yet.

=item * C<inum>

Immutable number. Not implemented yet.

=item * C<ibool>

Immutable boolean. Not implemented yet.

=back

=head1 OBJECT OPERATIONS AND METHODS

Each types of immutable object has a class with various methods. The immutable objects are also tied so they respond to Perl syntax and keyword functions appropriately.

=head2 C<IMMUTABLE::MAP>

=over

=item * C<new>

Takes a list of zero or more key/value scalars. Returns a new C<immutable::map> hashref object that is also tied.

=item * C<$imap->{key}>

Get the hash/map value associated with the key.

=item * C<$imap->get('key')>

Same as above using method call.

=item * C<$imap->{key} = $val>

Not allowed. Throws an error.

=item * C<$imap->set(key => $value, ...)>

Clones the map and adds the key value pairs to it.

Calling this with no args creates an equivalent clone of the caller.

=item * C<delete $imap->{key}>

Not allowed. Throws an error.

=item * C<$imap->del('key')>

Clones the map and deletes the key pair from it.

=item * C<$imap->id>

Returns an integer id number for the map.

=item * C<$imap->size>

Returns the number of key value pairs in the map.

=item * C<$imap->is_empty>

Returns true if the map is empty.

=back

=head2 C<IMMUTABLE::SEQ>

=over

=item * C<new>

Takes a list of zero or more scalars. Returns a new C<immutable::seq> arrayref object that is also tied.

=item * C<$iseq->[$i]>

Get the array/seq value associated with the index.

=item * C<$iseq->get($i)>

Same as above using method call.

=item * C<$iseq->[$i] = $val>

Not allowed. Throws an error.

=item * C<$iseq->set($i => $value)>

Returns a clone of the seq with the value at the index position.

=item * C<$iseq->push($val, ...)>

Returns a clone of the seq with the values appended.

=item * C<$iseq->pop>

In scalar context, returns a clone of the seq with the last value removed. In list context, returns the clone and the value removed.

=item * C<$iseq->shift>

In scalar context, returns a clone of the seq with the first value removed. In list context, returns the clone and the value removed.

=item * C<$iseq->unshift($val, ...)>

Returns a clone of the seq with the values appended.

=item * C<$iseq->id>

Returns an integer id number for the seq.

=item * C<$iseq->size>

Returns the number of values in the seq.

=item * C<$iseq->is_empty>

Returns true if the seq is empty.

=back

=head1 STATUS

This module is new and too incomplete, buggy and slow to use for any real code.

It is being developed for use in Lingy, a Perl implementation of Clojure, which needs immutable data types.

Only immutable maps are support in this early version.

Very little effort is currently placed on performance and memory usage. The intent is to use performant and memory efficient XS based algorithms once the API stabilizes.

=head1 COPYRIGHT AND LICENSE

Copyright 2023 by Ingy döt Net

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html|http://www.perl.com/perl/misc/Artistic.html>

=cut
