NAME
Infix::Custom - custom infix operators
VERSION
Version 0.01
SYNOPSIS
use utf8;
# call mode: lower to a sub call
use Infix::Custom op => '⊕', call => \&add, prec => 'add';
my $sum = 2 ⊕ 3; # add(2, 3) == 5
# op mode: lower to a native binary op (no call overhead)
use Infix::Custom op => '×', binop => '*', prec => 'mul';
my $area = $w × $h; # native multiply
sub add { $_[0] + $_[1] }
DESCRIPTION
Infix::Custom owns core's single PL_infix_plugin hook and exposes a small declarative API for adding your own binary infix operators. A declared operator is parsed at compile time and lowered to an ordinary optree, so there is no residual runtime cost beyond the work the operator names.
import options
use Infix::Custom op => GLYPH, <one lowering mode>, prec => NAME;
use Infix::Custom GLYPH => \&code, prec => NAME; # shorthand for call mode
op=> string-
The operator glyph (the shorthand passes it as the first argument). Any byte/UTF-8 sequence core will route to the plugin; it may not contain whitespace.
call=> CODE ref or sub name-
Call mode.
LHS op RHSlowers tocall(LHS, RHS). method=> bool (withcall)-
Method mode. The right-hand side is read as a bareword (an identifier, captured by a parse stage before
strict subssees it) and passed tocallas a string, soLHS op namelowers tocall(LHS, "name"). This is what makes a safe-navigation operator read naturally:sub nav { my ($o, $m) = @_; defined $o ? $o->$m : undef } use Infix::Custom op => '?->', call => \&nav, method => 1, prec => 'mul'; my $n = $obj ?-> child ?-> name // 'default'; # under strict, no quotesThe bareword must be a plain method name with no argument list; for arguments, fall back to call mode with a CODE ref (
$obj ?-> sub { $_[0]->m(@a) }). binop=> symbol-
Op mode.
LHS op RHSlowers to a native binary op, with no sub-call overhead. One of+ - * / % ** . x | & ^ << >>. build_op=> integer-
Escape hatch for XS authors (see "C-LEVEL build_op").
prec=> name-
One of
low,logical_or_low,logical_and_low,assign,logical_or,logical_and,rel,add,mul,pow,high(mirroring core'sINFIX_PREC_*ladder). Defaults tolow.Associativity follows the precedence tier — core's infix-plugin API ties the two together, so there is no separate
assocoption.add,mul,logical_or,logical_and(and the*_lowpair) are left-associative;assignandpoware right-associative;low,relandhighare non-associative.
Lexical scope
A declared operator is active only in the lexical scope that imported it (it is recorded in %^H) and is restored on scope exit. The same glyph can be rebound to a different meaning in a nested scope. Used outside any declaring scope, the glyph is an ordinary unknown-operator parse error. no Infix::Custom GLYPH; removes an operator earlier; no Infix::Custom; removes all of them.
C-LEVEL build_op
For operators that should lower to a custom optree rather than a sub call or a native binop, an XS author can supply their own build_op with the core signature
OP *build_op(pTHX_ SV **opdata, OP *lhs, OP *rhs, struct Perl_custom_infix *);
and pass its address (as an integer, e.g. via PTR2IV) as build_op:
use Infix::Custom op => '×', build_op => $addr, prec => 'mul';
The pointer is called at compile time with the parsed operands and must return the combined optree. This is a deliberately low-level hatch; the call and binop modes cover everything reachable from pure Perl.
Perl version requirement
Requires perl 5.38 or newer. The PL_infix_plugin hook that makes ambient infix operators possible was added to core in 5.38; there is no way to parse a custom operator mid-expression before then, so the distribution does not install on older perls.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under The Artistic License 2.0 (GPL Compatible).
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 29:
Non-ASCII character seen before =encoding in ''⊕','. Assuming UTF-8