| 1842 | class ClosureParamInferenceDemo |
| 1843 | { |
| 1844 | public function demo(): void |
| 1845 | { |
| 1846 | $src = new ScaffoldingClosureParamInference(); |
| 1847 | |
| 1848 | // $p is inferred as Pen from map's callable(TValue, TKey) signature |
| 1849 | $src->items->map(fn($p) => $p->write()); |
| 1850 | |
| 1851 | // Closure body |
| 1852 | $src->items->each(function ($pen) { |
| 1853 | $pen->write(); // resolves to Pen |
| 1854 | }); |
| 1855 | |
| 1856 | // Explicit type hint takes precedence over inference |
| 1857 | $src->items->map(fn(Pencil $p) => $p->sketch()); |
| 1858 | |
| 1859 | // $this in callable param resolves to receiver, not current class |
| 1860 | $pipeline = new ScaffoldingPipeline(); |
| 1861 | $pipeline->when(true, function ($pipe) { |
| 1862 | $pipe->send('data'); // resolves to ScaffoldingPipeline, not this demo class |
| 1863 | }); |
| 1864 | |
| 1865 | // Arrow function variant |
| 1866 | $pipeline->tap(fn($p) => $p->through([])); |
| 1867 | |
| 1868 | // Function-level @template callable inference |
| 1869 | // array_any(@param array<TKey, TValue>, @param callable(TValue, TKey): bool) |
| 1870 | // $item is inferred as Pen from the array's element type via template substitution |
| 1871 | $holder = new ScaffoldingTemplateCallableHolder(); |
| 1872 | array_any($holder->tools, fn($item) => $item->write() !== ''); |
| 1873 | } |
| 1874 | } |
| 1875 | |
| 1876 | |