https://perl.petamem.com/gpw2026/perl-mit-ai-gpw2026.html#/4/1/1 Perl mit AI I have been doing AI with Perl for a few decades. Now -- 3 decades into Perl -- I think it is time to turn the predicate around and let AI do Perl. Richard Jelinek * PetaMem s.r.o. * GPW 2026 - main arc | deep dive Prologue Since last time... GPW 2016 * Nuremberg * "KI: Wie testet man ein Hirn?" That was 10 years ago. A lot happened. "Patience you must have, my young Padawan" This prologue is not about Perl -- but it is necessary context. The classified stuff Some things are better left unspoken. What I can show you today is roughly half of what happened. - moving on PV & Energy Systems Designed, built, automated Experimental installation J1 Prague Experimental J1 * Prague 3.4 kWp * 64 kWh * 66% off-grid Reference installation W1 Sachsen Reference W1 * Saxony 20+ kWp * 40 kWh * 85% off-grid Victron ecosystem * Perl monitoring & control PV & Energy Systems Reference installation S1 Nuremberg Reference S1 * Nuremberg ~24 kWp * 45 kWh * 80+% off-grid * feed-in Reference installation J2 Prague Reference J2 * Prague 40 kWp * 120 kWh * 100% off-grid Villa-A A technocrat's house -- 2050s standard 1400m3 Heated volume 700t Thermal mass (concrete) Fiber-reinforced concrete Geothermal (Erdwarmekorbe) Capillary ceiling mats Full home automation Off-grid energy 40kWp solar 120kWh battery Villa-A -- Construction [geo_vsak] Villa-A -- Construction [geo_materi] Villa-A -- Construction [geo_makema] Villa-A -- Construction [geo_audiot] Villa-A -- Construction [geo_selfma] Villa-A -- Construction [house-ganz] Villa-A -- Construction [hvac_luftb] Villa-A -- Construction [house-luft] Villa-A -- Systems * Erdwarmekorbe, WP -- heizen, kuhlen (passiv) * "Klimamatten" -- Deckenheizung, Kuhlung (BEKA - Berlin) * Luftbrunnen, KWL * Privatkraftwerk (Offgrid) * Wasserwerk / Wasseraufbereitung * Digitale Lichtsteuerung, DALI "Full-Stack DC" (DALI-SELV) * ... und haste nicht gesehen ...and it all needs to be controlled. A house this complex needs an automation system that doesn't exist yet. - 02 WHIP Witty House Infrastructure Processor PV -- Perl Integration First tools: Victron Modbus + ECS BMS -- all in Perl $ ecs_bms_tool -range 1-16 # query all battery modules $ ecs_bms_tool -get cell_voltage -get cell_temperature $ ecs_bms_tool -otype json # JSON for pipeline integration $ Wmodbus discover 192.168.2.0/24 # find Modbus devices on network $ Wmodbus --host 192.168.2.201 --unit 2 read holding 0-10 $ Wmodbus --host 192.168.2.201 --profile vents-dbe900l monitor ecs_bms_tool -- ECS LiPro BMS management (SoC, cell voltage, balancing) Wmodbus -- Modbus TCP/RTU: discovery, read/write, device profiles, monitoring Wcli -- solar irradiance & PV power calculator Wthermal -- physics-based house thermal model Scripts work. But a house is more than solar panels. Looking for a Smarthome Preferably in Perl, obviously. MisterHouse MisterHouse -- Perl. v4.2 released 03/08/2017. Dead. FHEM FHEM -- Perl. Active. Tried it. Suffered. Home Assistant Home Assistant -- Python. Popular. Not Perl. Not 21st century enough. WHIP WHIP -- "I'll build my own." The FHEM Experience "We do not like CPAN" -- dependencies create problems. So we reimplement everything ourselves. But worse. "We do not like PBP" -- contributions are done by amateurs. Too high expectations would kill contribution. "Efficient algorithms are overrated" -- "So what? That's 0.1s faster?" "Tests? TDD? That's superfluous work!" "I don't like you, you cannot use my GPL code" QR FHEM SVN svn.fhem.de/trac/browser/trunk/fhem (FHEM people: no offense. Well, maybe a little.) MySensors Nice idea. Wrong execution. Open-source, DIY, community-driven Tree topology with auto-routing & self-healing Up to 254 nodes x 254 sensors -- decent scale Arduino -- ATmega328? For a house? In 2020? Arduino software model -- Endless loop with stuff in it. RS485 / nRF24L01+ -- Master-Slave Architecture Text protocol -- semicolon-delimited ASCII over serial. In 2020. No autonomous operation -- nodes depend on gateway/controller MySensors DIY node I felt there had to be something better. Birth of a Node CAN bus instead of RS485 Multi-master * Inherent collision resolution * Resilient Good enough for cars for decades. Industrial standard. 1 MBit instead of EIB/KNX 9600 baud Good for 20-30m runs. Plenty for a house. STM32F103 instead of ATmega328 72 MHz ARM Cortex-M3 * 7x faster than Arduino CAN peripheral built-in * $1.50 in 2020 FreeRTOS + libopencm3 instead of endless loops Real tasks * Priorities * Preemption * Hardware abstraction STM32 Black Pill RobotDyn Black Pill * STM32F103C8T6 Birth of a Node CAN bus instead of RS485 Multi-master * Inherent collision resolution * Resilient Good enough for cars for decades. Industrial standard. 1 MBit instead of EIB/KNX 9600 baud Good for 20-30m runs. Plenty for a house. STM32F103 instead of ATmega328 72 MHz ARM Cortex-M3 * 7x faster than Arduino CAN peripheral built-in * $15 in 2020 (COVID!) FreeRTOS + libopencm3 instead of endless loops Real tasks * Priorities * Preemption * Hardware abstraction STM32 Blue Pill Blue Pill * STM32F103C8T6 Birth of a Node CAN bus instead of RS485 Multi-master * Inherent collision resolution * Resilient Good enough for cars for decades. Industrial standard. 1 MBit instead of EIB/KNX 9600 baud Good for 20-30m runs. Plenty for a house. STM32F103 instead of ATmega328 72 MHz ARM Cortex-M3 * 7x faster than Arduino CAN peripheral built-in * no stock! - DIY FreeRTOS + libopencm3 instead of endless loops Real tasks * Priorities * Preemption * Hardware abstraction STM32 Green Pill Green Pill * STM32F103C8T6 * DIY Why CAN? Why CAN? Hardware arbitration (CSMA/CR) * true multi-master * 1 Mbit/ s * differential * industrial grade Why not WiFi/Zigbee? No batteries to die. No mesh to collapse. Building for 50 years, not 5. Why not RS485? No arbitration. Master-slave only. Two nodes transmit = garbage. Why not KNX? 9600 baud (1990s design). Expensive. Closed ecosystem. Birth of a Hub So you have 20 nodes -- now what? WHIP Hub Assembly Hub assembly * DIN rail mount Waveshare 2-CH CAN HAT Waveshare 2-CH CAN HAT RasPi 4B/5 * 2-ch CAN HAT * Relay Board * DIN Rail Mount * CAN/IP & CAN/CAN Gateway WHIP Architecture Nodes -- STM32 MCUs * FreeRTOS * 1MBit CAN bus * Autonomous C / Embedded Hubs -- RasPi * CAN/IP gateway * Hub Aggregation * Protocol bridges * Mojolicious Perl Server -- Orchestration * External connectivity Perl Higher layers are always a supplement, never a requirement. Nodes -- STM32 + FreeRTOS Hardware STM32F103 (Cortex-M3, 72 MHz) STM32F303 (Cortex-M4F, FPU) Native bxCAN controller Software FreeRTOS * libopencm3 No vendor HAL lock-in One YAML = one firmware 115+ sensor/actuator modules [?] BME280 * DS18x20 * SHT3x * NTC [?] INA219 * INA226 * ACS712 * ADC DALI * WS281x * PWM dimmer * SSR PCF857x * MCP23017 * relay * GPIO LoRa * Modbus RTU * 1-Wire * SPI [?] SSD1306 * ST7735 * status LEDs SCD4x * SGP4x * PMS5003 * SEN5x AS3935 (franklin) * MLX90614 * VL53L0x * HX711 Dependency resolver inspired by Linux Kconfig ~5 modules per node - 153,476,148 combinations Ganglion Ganglion = GANG of Lightweight I/O Nodes -- insect-brain model. IF-THEN rules, timers, local variables -- compiled to bytecode on the MCU. Nodes operate autonomously even when hub/server are down. Ganglion -- In Action DEF LightTimeout = 300 # 5 minutes # Motion detected: light on, start timer IF motion:detected THEN lights:on; SET $T_0 = LightTimeout # Timer expired: light off IF !$T_0 THEN lights:off # Cross-node: kitchen smoke - alarm everywhere DEF Kitchen = 42 IF Kitchen:smoke:detected THEN buzzer:alarm(1) Toolchain: Wgc -- Compiler (Perl) .tgc source - .bgc bytecode (10-50 bytes) Wgi -- Interpreter Disassembly + execution trace Same C source as on STM32 Wgs -- Simulator Perl reference impl * full memory model Mock sensors * timer simulation * 170 tests Hubs -- a Pantheon Specialized RasPi hubs. Named by function, not by accident. Raijin [?] Thunder god -- energy: Victron, BMS, MPPT, 120 kWh batteries Lucifer Light bearer -- DALI lighting: 4 buses, scenes, presence simulation Bragi Norse god of poetry -- multiroom audio, voice, AI assist Gaia Earth goddess -- greenhouse, garden, pond, irrigation Tyr [?][?] God of war -- ...you can guess. No hub is a single point of failure. Each domain runs independently. SELV-DALI -- Lighting without mains SELV = Safety Extra Low Voltage. Under 60V DC. Safe to touch. The trick: Entire lighting chain runs from battery storage. 48V - 24V DC/DC - LED. No 230V AC anywhere. DALI controls at 16V. Switches, sensors, dimmers -- all SELV. Inverters fail? Lights stay on -- they bypass AC entirely. Switch next to the bathtub? No problem. No electrician needed. QR EN English QR DE Deutsch WHIP -- Protocols & Integrations Protocols CAN bus 1Mbit Modbus TCP/RTU DALI MQTT SNMP I2C 1-Wire Modbus 17 of 21 function codes * 869 tests * 91% coverage 30+ external integrations Victron VRM * MasterTherm * PVGIS * Discord * Nextcloud * Proxmox * UniFi * ... All protocol handlers in Perl * Mojolicious async I/O WHIP -- In production Villa-A (Prague) -- completely off-grid * 40 kWp solar * 120 kWh LiFePO4 * 3x Multiplus-II 10kVA * MasterTherm heat pump * capillary ceiling heating/cooling * DALI lighting across 4 buses * distributed CAN nodes Villa-B (Germany) -- same concept, different config Two deployments = real generalization, not "works on my machine" Invisible when it works. Competent when it matters. Built for decades, not warranties. 03 AI does Perl Using AI to write Perl -- the practical reality AI contributed... A lot of Perl prototypes -- some grew to standard tools * An own PVGIS -- but better (many roofs) * Modbus, CANbus CLI command & introspection * Heat loss / inrush simulations (better than "energy experts") FreeRTOS / libopencm3 source * Modularized firmware for STM32 nodes * Over 100 modules (combinatorics!) * Tests, build system A lot of Perl code * API endpoints to ... everything * Discord, Reddit, Twitter, Kraken, Ollama, Proxmox * AWS, Azure, Anthropic, Kodi, Nextcloud, ... you name it! "Small" side projects MIB Parser SNMP::MIB::Compiler -- best MIB parser. Period. open source Grpc::FFI gRPC for Perl -- because everything else was dead open source The CPAN Situation 2025-09-28 "User 'PETAMEM' set to nologin. Your account may have been included in a precautionary password reset in the wake of a data breach incident at some other site. Please talk to modules@perl.org to find out how to proceed." - Talked to modules@perl.org. No answer. 2025-10-01 "Ich leite das mal auf Steffen Winklers Empfehlung hier weiter an Dich, weil von modules@perl.org bislang keine Reaktion kam. Wurde jetzt mal wieder gerne ein paar Module auf CPAN schmeissen. :-)" - An Andy Koenig. No answer. 2025-10-06 "Hi Soren. Weisst Du zufallig wo ich eines Andy Konig oder halt jemanden der mit PAUSE/CPAN weiterhelfen kann habhaft werden konnte? Wir wurden mal gerne unsere Module auf Vordermann bringen, aber [...] und bei modules@perl.org oder andyk@cpan.org ruhrt sich keiner." - An Soren Laird, LinkedIn. No answer. SNMP & MIBs -- quick primer SNMP Simple Network Management Protocol -- how you monitor and manage network devices. Routers, switches, firewalls, UPS, printers -- anything with an IP. MIB Management Information Base -- the schema. Defines what each device can report: CPU load, interface counters, temperature, error rates, ... The problem Thousands of vendor MIBs. Written in ASN.1. Riddled with vendor deviations from the standard. Every monitoring system needs a parser -- and every parser struggles. SNMP::MIB::Compiler 2 days with AI * CPAN module was 93% working * targeted fixes, no rewrite Parser Language Failures Pass rate pysmi Python 296 93.8% gosmi Go 91 98.1% Ours Perl 39 99.2% 4740 MIBs * 301 fixes * 52 fewer failures than Go QR GitHub github.com/petajoulecorp/SNMP-MIB-Compiler Grpc::FFI Wanted gRPC in Perl. Everything on CPAN: dormant, dead, or broken. So we built it. From scratch. FFI::Platypus bindings to the gRPC C API. Learning path: UUID::FFI - SQLite::FFI - Grpc::FFI 326 tests passing * zero memory leaks * zero crashes Cross-language: Perl client - Java/Go servers -- working Streaming: unary, client, server, bidirectional 85% production ready * ~43 implementation files And yet -- this was a prelude for something bigger. What if FFI wasn't just a tailored library connector... ...but more integrated and automatic? Navigator / Orchestrator AI doesn't do this on its own. Human: strategy, architecture, learning path, priorities AI: execution, documentation, pattern learning, iteration gRPC example: I decided "start with UUID, then SQLite, then gRPC" AI executed each phase, documented lessons, graduated to the next Without the navigator -- the AI builds impressive things that go nowhere. Without the AI -- the navigator doesn't have enough hours in the day. So... AI is quite good at Coding. [model_time] But how far can this actually go? 04 AI does Perl Turning the predicate around. pperl PetaPerl / ParallelPerl A Perl 5 interpreter -- designed by humans. Written in Rust -- by many AI agents. Serious -- no toy or academic exercise. pperl badge pperl PetaPerl / ParallelPerl A Perl 5 [S:interpreter:S] Platform -- designed by humans. Written in Rust -- by many AI agents. Serious -- no toy or academic exercise. pperl badge pperl -- Not the first attempt Topaz 1999 * C++ rewrite * Chip Salzenberg * abandoned B::C / perlcc 1996-2016 * Perl-to-C compiler * dead cperl 2015-2020 * Perl 5 fork * Reini Urban * dormant RPerl Restricted Perl - C++ * Will Braswell * dormant WebPerl Perl 5 - WebAssembly * runs in browser * semi-active PerlOnJava Perl 5 on JVM * Flavio Glock * active -- talk at this GPW! Common failure mode: underestimating Perl 5's complexity pperl -- Scope Perl 5.42 -- ish Compatibility: strive for maximum Perl 5 compliance, currently 5.42 Performance: strive for V8 levels XS: no, but yes Native Rust implementations, integral to the interpreter Linux only -- all architectures We really don't care about use v5.xx pperl -- Status 22,000+ tests total ~61-400 failures -- give or take Performance: good, bad and ugly Quotes from the AI 13095 pass (+25 from previous 13070), 31 fail (down from 46!). The File::Path native implementation not only works, it unblocked 15 previously-failing tests that depended on File::Path. Zero regressions. pperl -- Benchmarks Benchmark perl5 pperl ratio list_util::sum 191.8K 372.8K 1.9x list_util::min 199.8K 772.9K 3.9x list_util::max 201.3K 673.7K 3.3x list_util::product 2.7M 4.0M 1.5x Native Rust implementations -- not XS, not C pperl -- Beyond Perl5 Maximum compatibility. But more. Autoparallelization -- for/map/grep via Rayon * transparent * no threads pragma JIT Compilation -- Cranelift * hot codepath detection * native code at runtime Auto-FFI -- call any C library * no XS * no compilation * Peta::FFI namespace Pre-Compile -- .plc blobs * skip parsing * near-instant startup Daemonize -- emacs-style daemon/client * shared memory * zero cold start Autoparallelization Powered by Rayon -- Rust's data-parallelism library Work-stealing scheduler Divides work into tasks, idle threads steal from busy ones -- automatic load balancing One-line change in Rust .iter() - .par_iter() -- same code, parallel execution Guaranteed data-race freedom If it compiles, it's safe. Rust's type system enforces this at compile time. # This just works. In parallel. my @results = map { expensive_computation($_) } @large_list; # No threads. No MCE. No forks. # pperl detects safe loops - Rayon handles the rest. --parallel flag * list >= 1000 items * no shared mutation JIT Compilation Just-In-Time -- compile to machine code while running How it works in pperl: 1. Interpreter runs normally -- profiling hot paths 2. Hot loop detected - lower to Cranelift IR 3. Cranelift compiles IR - native machine code 4. Next iteration runs as native code -- zero dispatch overhead Cranelift -- the compiler backend behind Wasmtime and Rust's alternative codegen. Production-proven. Targets: x86-64 * AArch64 * s390x * RISC-V # pperl detects this as a hot loop pattern my $sum = 0; for my $i (1 .. 1_000_000) { $sum += $i; } # - Cranelift compiles to native machine code JIT -- First Win Inner loop JIT -- single hot loop compiled to native code Benchmark perl5 pperl interpreted pperl JIT vs perl5 Mandelbrot 133ms 1493ms 41ms 3.2x faster Ackermann 13ms 630ms 12ms 1.1x faster The JIT fired and the test passes! The answer is correct ( 500000500000). Good. But only the innermost loop is compiled. What about nested loops? $py = 0; while ($py < $height) { $y0 = $y_min + $py * $y_step; $row_off = $py * $width; $px = 0; while ($px < $width) { $x0 = $x_min + $px * $x_step; $zr = 0.0; $zi = 0.0; $iter = 0; while ($iter < $max_iter) { $r2 = $zr * $zr; $i2 = $zi * $zi; last if ($r2 + $i2 > 4.0); $zi = 2.0 * $zr * $zi + $y0; $zr = $r2 - $i2 + $x0; $iter++; } $frame[$row_off + $px] = $color_lut[$iter]; $px++; } $py++; } JIT -- The Code Mandelbrot set Triple-nested while loop 19 variables * float arithmetic Pure Perl. No XS. No Inline::C. No tricks. JIT -- Full Nested All 3 loop levels compiled as one native function Mandelbrot 1000x1000 perl5 pperl interpreted pperl JIT vs perl5 Wall time 12,514ms -- 163ms 76x faster 200 million escape iterations of float arithmetic. 19 variables, 3 loop levels -- Cranelift register-allocates across all of them. Perl. With JIT. That's a sentence nobody expected. Autoparallel JIT -- Full Win JIT + Rayon: compile to native, then split across cores Mandelbrot perl5 pperl JIT pperl JIT + 8 threads vs perl5 1000x1000 12,514ms 163ms 29ms 431x faster 4000x4000 ~200s 2,304ms 342ms ~580x faster JIT alone: 76x. Adding 8 threads: another ~7x on top. user 2.6s vs real 0.34s -- near-linear scaling across cores. Demo Time! Auto-FFI No XS. No Inline::C. No compilation. Just call C. # Layer 0 -- Raw: any library, you provide type signatures use Peta::FFI qw(dlopen call); my $lib = dlopen("libz.so.1"); my $ver = call($lib, "zlibVersion", "()p"); say "zlib: $ver"; # 1.3.1 # Layer 1 -- Pre-baked: curated signatures, zero ceremony use Peta::FFI::Libc qw(getpid strlen strerror uname); say strlen("hello"); # 5 my @info = uname(); say "$info[0] $info[2]"; # Linux 6.18.6-arch1-1 Pack-style type codes: (p)L = strlen(const char*) - size_t 50+ native Rust modules already built in -- Auto-FFI extends to everything else Auto-FFI -- Details Powered by libffi -- any signature works, no pre-generated stubs Layer Scope Mechanism Raw (Layer 0) Any .so on the dlopen + dlsym + libffi call frame system Pre-baked (Layer libc, libuuid, Direct Rust libc::* calls -- zero 1) ... overhead Discovery (Layer System-wide scan scan() - hashref of { soname => 2) path } # Layer 2 -- What's on this system? use Peta::FFI qw(scan dlopen call); my $libs = scan(); say scalar(keys %$libs), " libraries found"; if (exists $libs->{"libz.so.1"}) { my $z = dlopen("libz.so.1"); say "zlib: ", call($z, "zlibVersion", "()p"); } Libc: ~30 functions (process, strings, env, math, file, time) UUID: 6 functions via dlopen -- dies with install hint if missing Bytecode Cache (.plc) Like Python's .pyc -- but for Perl. Opt-in. # Default: no caching (safe for development) $ pperl script.pl # Enable: compile once, load from cache on subsequent runs $ pperl --cache script.pl # Invalidate all caches $ pperl --flush First run: parse - codegen - execute - save .plc Second run: load .plc - execute (no parsing, no codegen) Bytecode Cache -- Details Storable-model: bincode deserializes directly to final runtime types. Zero intermediate conversion. Benchmark perl5 pperl pperl --cache three_modules 22.3ms 12.6ms 9.9ms mixed_native_fallback 26.3ms 13.0ms 10.0ms deep_deps 18.1ms 13.1ms 9.9ms Net module-loading cost: 33-37% faster with cache. Biggest win on fallback modules. Native Rust modules already near-zero cost. SHA-256 keyed * mtime + version validation * aggressive format versioning Daemonize Emacs-style daemon/client model $ pperl --daemon script.pl # compile, warm up, listen $ pperl --client script.pl # connect - fork - run - respond $ pperl --stop script.pl # clean shutdown First run: parse - codegen - execute (warm-up) - listen Client request: connect - fork() - child inherits arenas - execute - respond fork() gives each client a fresh address space with all arenas already mapped -- zero I/O, zero parsing, zero deserialization Daemonize -- Details Benchmark perl5 pperl --cache --daemon 5 native modules 15.0ms 4.3ms 4.3ms 4.6ms fallback + native mix 23.5ms 15.8ms ~10ms 5.0ms (3.2x) Eliminates both startup costs: process creation (~3-4ms) + module compilation (0-15ms) Faster than bytecode cache -- no deserialization, arenas are already in memory Unix domain socket * JSON wire protocol * copy-on-write pages via fork() Daemonize -- Prior Art Solution Scope Isolation State leakage Status PPerl General CLI None Yes Dead (2004) SpeedyCGI CGI None Yes Dead (2003) mod_perl Apache Per-child Per-request Maintained Starman PSGI Per-worker Per-request Maintained FastCGI Web Per-process Per-request Maintained pperl daemon General CLI Per-request (fork) None Active All prior solutions: same interpreter across requests -- state leakage by design pperl: fresh child per request via fork() -- compiled arenas via COW, clean runtime state Future pperl [?] Seamless GPU -- restricted Perl - OpenCL/HIP/Vulkan/CUDA kernel * same code, GPU execution [?] pperl-mini -- tailored and scaled down versions. Maybe on a Raspberry Pico one day? [?] pperl-compiler -- Maybe code running on a STM32 one day? When to use pperl Good fit: * Workloads that benefit from JIT and/or autoparallelization * Scripts using native builtins (50+ Rust modules, fast) * Fast startup -- inherently ~2x faster than perl5, plus --cache * pperl-specific features: Auto-FFI, Daemonize, Bytecode Cache * Security: different codebase -- unlikely to share CVEs with perl5 * Smaller, less complex scripts Not yet: * Large, complex codebases -- edge cases where pperl differs from perl5 * We strive for maximum compatibility, but we're not 100% there yet Rule of thumb: the longer and more complex the script, the more likely you hit a corner case. If you don't want to touch the code -- use perl5. Correctness Case Study How serious is "maximum compatibility"? The bug: $, (OFS) vs $\ (ORS) in print pperl checked both with the same flag mask. Perl5 doesn't. perl5 -- $, (OFS) if (SvGMAGICAL(ofs) || SvOK(ofs)) Checks get-magic AND ok-flags perl5 -- $\ (ORS) if (PL_ors_sv && SvOK(PL_ors_sv)) Checks ok-flags only. No get-magic. pperl had: // Same mask for both -- SVS_GMG included for ORS. Wrong. if flags & (SVF_IOK | SVF_NOK | SVF_POK | SVF_ROK | SVS_GMG) != 0 Practical impact: near zero. To trigger this, you'd need a tie on $\ whose FETCH returns undef, while the underlying SV has get-magic set but none of IOK/NOK/POK/ROK -- and then call print. Nobody writes this. Nobody has ever written this. We fixed it anyway. The depth of compatibility is the product's guarantee. I have been doing AI with Perl for a few decades. Now it is time to let AI do Perl. Get it here: QR perl.petamem.com perl.petamem.com Danke. Richard Jelinek * rj@petamem.com PetaMem s.r.o. * petamem.com One more thing. psh An interactive Perl shell ls "-la"; # it's just a sub call cd "/tmp"; # chdir wrapper ps "aux"; # system command # But you're already in a scripting language: for my $f (glob("*.log")) { if (-M $f > 7) { rm $f; say "cleaned $f"; } } Object pipes -- pass data structures, not text: ps() | grep { $_->{mem} > 100_000 } | sort { $b->{cpu} <=> $a->{cpu} }; PowerShell's philosophy * Perl's text power * pperl's JIT speed