# perldoc > Algorithm::Diff

---
type: CommandReference
command: Algorithm::Diff
mode: perldoc
section: ""
source: perldoc
---

## Quick Reference

- `@lcs = LCS(\@seq1, \@seq2)` — compute longest common subsequence
- `$count = LCS_length(\@seq1, \@seq2)` — length of LCS only
- `($idx1, $idx2) = LCSidx(\@seq1, \@seq2)` — indices of LCS elements
- `@diffs = diff(\@seq1, \@seq2)` — list of hunks (additions/deletions)
- `@sdiffs = sdiff(\@seq1, \@seq2)` — side-by-side diff display
- `@cdiffs = compact_diff(\@seq1, \@seq2)` — compact flat index format
- `$diff = Algorithm::Diff->new(\@seq1, \@seq2)` — OO interface for iteration
- `$diff->Next()` — iterate forward through hunks
- `$diff->Prev()` — iterate backward
- `$diff->Reset($pos)` — reset to position
- `$diff->Items($seqNum)` — items in current hunk
- `$diff->Base($newBase)` — set base (0 or 1) for line numbers

## Name

Compute intelligent differences between two files/lists.

## Synopsis

perl
use Algorithm::Diff qw(
    LCS LCS_length LCSidx
    diff sdiff compact_diff
    traverse_sequences traverse_balanced
    prepare
);

# Procedural interface
@lcs    = LCS( \@seq1, \@seq2 );
$count  = LCS_length( \@seq1, \@seq2 );
( $idx1, $idx2 ) = LCSidx( \@seq1, \@seq2 );
@diffs  = diff( \@seq1, \@seq2 );
@sdiffs = sdiff( \@seq1, \@seq2 );
@cdiffs = compact_diff( \@seq1, \@seq2 );

# OO interface
my $diff = Algorithm::Diff->new( \@seq1, \@seq2 );
$diff->Base(1);
while( $diff->Next() ) {
    next if $diff->Same();
    # process hunks
}
## Functions and Methods

### `LCS(\@seq1, \@seq2, [\&keyGen, @args])`

Returns an array containing the longest common subsequence. In scalar context, returns a reference. Optional key generation function for custom comparison.

### `LCS_length(\@seq1, \@seq2, [\&keyGen, @args])`

Like `LCS` but returns only the length. About 9% faster.

### `LCSidx(\@seq1, \@seq2, [\&keyGen, @args])`

Returns references to two arrays: indices into `@seq1` and `@seq2` where LCS items are located.

### `new(\@seq1, \@seq2, [\%opts])`

Creates an OO diff object. Computes the smallest set of additions/deletions.

### `Next([$count])`

Moves forward `$count` hunks (default 1). Returns position or false if past end. On a reset object, moves to first hunk.

### `Prev([$count])`

Moves backward `$count` hunks. On reset object, moves to last hunk.

### `Reset([$pos])`

Resets position to `$pos` (0 resets, 1 first, -1 last). Returns the object.

### `Copy([$pos, $newBase])`

Returns a copy of the object sharing data. Optional position and base.

### `Base([$newBase])`

Sets/returns the base for range indices (0 or 1). Default 0 (array indices).

### `Diff()`

Returns a bitmask: 1 (deletions in seq1), 2 (insertions in seq2), 3 (both), 0 (same).

### `Same()`

Returns list of items if current hunk is unchanged, else empty list. In scalar context returns count.

### `Items($seqNum)`

Returns list of items from sequence 1 or 2 in current hunk. Returns empty list if no items from that sequence.

### `Range($seqNum, [$base])`

Returns list of indices to items in current hunk. Optional base.

### `Min($seqNum, [$base])`

Returns first index of current hunk for sequence, or undef if empty.

### `Max($seqNum, [$base])`

Returns last index of current hunk for sequence, or undef if empty.

### `Get(@names)`

Returns multiple scalar values. Names follow regex: `/(-?\d+)?(min|max)[12]/i`, `/(range[12]|same|diff|base)/i`.

### `prepare(\@seq, [\&keyGen])`

Precomputes a hash for a sequence to speed up repeated LCS calls. Returns a reference to the hash. Provides ~50% performance gain.

### `diff(\@seq1, \@seq2, [\&keyGen, @args])`

Returns a list of hunks. Each hunk is an array of change descriptors: `[ '-', $index, $item ]` for deletions, `[ '+', $index, $item ]` for insertions, or `[ '-', $index, $item ], [ '+', $index, $item ]` for replacements.

### `sdiff(\@seq1, \@seq2, [\&keyGen, @args])`

Returns a list of display instructions for side-by-side diff. Each entry: `[ $modifier, $old_item, $new_item ]` where modifier is `+`, `-`, `u`, or `c`.

### `compact_diff(\@seq1, \@seq2, [\&keyGen, @args])`

Returns a flat list of indices alternating between `@seq1` and `@seq2` hunk boundaries. Even indices (0,2,4...) are start positions in `@seq1`; odd indices (1,3,5...) are start positions in `@seq2`. The last pair gives the total lengths.

### `traverse_sequences(\@seq1, \@seq2, { MATCH => sub, DISCARD_A => sub, DISCARD_B => sub }, [\&keyGen, @args])`

Advances arrows through both sequences, calling callbacks. Callbacks receive indices of the elements. Also supports `A_FINISHED` and `B_FINISHED`.

### `traverse_balanced(\@seq1, \@seq2, { MATCH => sub, DISCARD_A => sub, DISCARD_B => sub, CHANGE => sub }, [\&keyGen, @args])`

Like `traverse_sequences` but also supports `CHANGE` callback for replacements. If no `CHANGE` callback, maps to `DISCARD_A` and `DISCARD_B`.

## Key Generation Functions

Most functions accept an optional `\&keyGen` parameter. The key generator returns a string key for each element. By default, elements are compared using `eq` (stringified). Use a custom key generator when comparing objects by value (e.g., by SSN field) rather than by reference.

## Examples

### Traditional diff output using OO interface

perl
my $diff = Algorithm::Diff->new( \@seq1, \@seq2 );
$diff->Base(1);
while( $diff->Next() ) {
    next if $diff->Same();
    my $sep = '';
    if( ! $diff->Items(2) ) {
        printf "%d,%dd%d\n", $diff->Get(qw( Min1 Max1 Max2 ));
    } elsif( ! $diff->Items(1) ) {
        printf "%da%d,%d\n", $diff->Get(qw( Max1 Min2 Max2 ));
    } else {
        $sep = "---\n";
        printf "%d,%dc%d,%d\n", $diff->Get(qw( Min1 Max1 Min2 Max2 ));
    }
    print "< $_" for $diff->Items(1);
    print $sep;
    print "> $_" for $diff->Items(2);
}
## See Also

- [Algorithm::Diff::XS](https://metacpan.org/pod/Algorithm::Diff::XS) — faster C implementation
- [Algorithm::LCS](https://metacpan.org/pod/Algorithm::LCS) — alternative LCS algorithm
- [Text::Diff](https://metacpan.org/pod/Text::Diff) — higher-level diff interface
- [sdiff](https://man7.org/linux/man-pages/man1/sdiff.1.html) — Unix side-by-side diff utility

## Error Checking

All routines die with a message if passed a non-reference when a reference is expected.