control-flow intermediate

How to use smartmatch operator ~~ in Perl?

Question

How to use smartmatch operator ~~ in Perl?

Understanding and Using the Smartmatch Operator ~~ in Perl

The smartmatch operator ~~ was introduced in Perl 5.10 as a flexible way to compare two values or data structures that adapts its behavior based on the operands' types. It attempts to do the "right" comparison depending on context, making it powerful but also sometimes confusing.

How Does ~~ Work?

The ~~ operator tries to "smartly" compare two expressions on the left and right sides without you needing to explicitly specify the kind of comparison. This behavior is driven by what Perl calls the "smartmatch rules," which check the types and contexts of operands.

  • If both sides are scalars (numbers or strings), it performs a string equality test.
  • If the right side is an array reference, it checks if the left side is an element of that array (like grep search).
  • If the right side is a hash reference, it checks if the left side is a key in the hash.
  • If both sides are array references, it compares if any elements from the left array are found in the right array.
  • If both sides are code references, it calls the code and tests the results.
  • If the left side is an array and right side is a scalar, it checks if the scalar is an element of the array.

And more complex rules exist, including with regex, numbers, and objects.

Example Usage

use strict;
use warnings;

# Basic string comparison (same as eq)
print "apple" ~~ "apple" ? "Match\n" : "No match\n";  

# Scalar in array
my @fruits = qw(apple banana orange);
print "banana" ~~ \@fruits ? "Found banana\n" : "No banana\n";

# Scalar in hash keys
my %colors = (red => 1, green => 1, blue => 1);
print "green" ~~ \%colors ? "Green key exists\n" : "No green\n";

# Array ref smartmatch (any overlap)
my $arr1 = [1, 2, 3];
my $arr2 = [3, 4, 5];
print $arr1 ~~ $arr2 ? "Overlap found\n" : "No overlap\n";

# Regex smartmatch
print "hello" ~~ qr/hel/ ? "Matches regex\n" : "No regex match\n";

Important Notes and Gotchas

  • Experimental and Deprecated: As of Perl 5.18 and later, the smartmatch operator is considered experimental and subject to change. Its internal behaviors changed notably between versions 5.10 and 5.18, which can cause portability issues.
  • Context Sensitive: The behavior of ~~ depends heavily on the types of operands, which can sometimes lead to unexpected results if operand types differ from what you expect.
  • Prefer Explicitness: Because of the operator’s complexity and changes, many Perl developers recommend using explicit comparison constructs (like eq, grep, or exists) for clarity.
  • Warnings: Use use experimental 'smartmatch'; in Perl 5.18+ to enable and silence warnings about its experimental nature.

Summary

The smartmatch operator ~~ offers a convenient, polymorphic way to compare values in Perl, adapting its semantics based on the operands. It shines in simple membership tests and basic data structure comparisons but carries risks due to its experimental status and subtle behavior changes between Perl versions. Use it with care, test thoroughly, and consider explicit comparisons if portability and code clarity are priorities.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 7ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Match
Found banana
Green key exists
No overlap
Matches regex
STDERR
Smartmatch is experimental at - line 5.
Smartmatch is experimental at - line 9.
Smartmatch is experimental at - line 13.
Smartmatch is experimental at - line 18.
Smartmatch is experimental at - line 21.

Was this helpful?

Related Questions