# pperl 0.6.18 *2026-09-10 to 2026-09-16, 78 commits.* - **Memoize** is native and no longer loaded from the host perl's library; its `Memoize::*` helper modules ship with pperl. `memoize`, `unmemoize` and `flush_cache` support `NORMALIZER`, `INSTALL` and the `MEMORY`, `HASH`, `TIE`, `FAULT` and `MERGE` caches, checked against the Memoize 1.17 distribution's own tests. A memoized function of one or two numeric arguments keeps its results in a cache that compiled code reads directly, and a loop calling it compiles: a memoized `fib(30)` called in a loop costs 43 instructions per call, against 2858 on perl5 with Memoize and 1682 on pperl without the JIT. - **Foreach loops** over an array or an array reference (`for my $e (@$table)`) compile when nested in another compiled loop, and a `last` that leaves one compiles to a jump, also from inside an `if (...) { ...; last }` block. Appending an array element to a string (`$line .= $e->[0]`, `$s .= $a[$i]`) compiles too. fasta, whose character-selection loop combines all three, runs 49.3% fewer instructions at 250,000. - **Integer array loops**: a compiled loop that copies scalars and swaps or stores elements of an integer array (`@p[$i,$j] = @p[$j,$i]`, `$p[$k] = $k`) keeps both integers and runs without leaving compiled code. fannkuch-redux at n=9, whose flip loop has this shape, runs 38.6% fewer instructions. - **Loop unrolling**: the JIT compiles a `for` loop over a constant range of at most eight iterations, such as `for my $i (0 .. 4)`, as straight-line copies of its body, and does the same for a loop nested in it whose bounds become constant in each copy, such as `for my $j ($i + 1 .. 4)`. nbody's pair loop becomes ten independent chains of `sqrt` and division, and nbody at 50,000,000 steps runs 21.9% fewer instructions. - **Substring counting**: a loop that counts substrings in a hash, `$h{substr($seq, $i, $k)}++`, compiles when the offset is a lexical loop variable (`for my $i (...)`) rather than `$_`. k-nucleotide at 250,000 runs 11.0% fewer instructions. - **SDBM_File** blesses the tied object into the class `tie` was given, so a subclass works: after `tie %h, 'My::DBM', ...`, `ref tied %h` is `My::DBM`, not `SDBM_File`. `Memoize::AnyDBM_File` relies on this. - **PDL**: `nan` and `inf` build an ndarray of the dimensions they are given (`nan(4,4)`) instead of ignoring their arguments; without arguments they still return a 0-dimensional value. `PDL::zeroes(4,4)` takes its first argument as the class and fails, as on perl5, while the `zeroes` and `zeros` that `use PDL` imports still take dimensions alone.