|
| 1 | +# MeTTaScript 2.7.0 |
| 2 | + |
| 3 | +Leveled logging you can leave in the code, and two interpreter forms that now carry the types they always |
| 4 | +had. No existing program's evaluation or output changes. |
| 5 | + |
| 6 | +## Logging that costs nothing until you switch it on |
| 7 | + |
| 8 | +Instrumenting a function with `println!` means paying to build the message on every call, forever, which is |
| 9 | +why that instrumentation gets deleted rather than left in place. Logging is now a level: |
| 10 | + |
| 11 | +```metta |
| 12 | +!(pragma! log-level info) |
| 13 | +!(log! info (summarize $kb)) ; (Log info <value>) |
| 14 | +!(log! debug (expensive $kb)) ; nothing: debug is below info, and the payload is not built |
| 15 | +``` |
| 16 | + |
| 17 | +Levels rank `error < warn < info < debug < trace`, and a setting admits everything at or above its severity. |
| 18 | +Logging is off until a program sets the pragma, so a library that logs is silent in a program that never asks |
| 19 | +for it. `(log-enabled? <level>)` answers the same question for a caller that wants its own sink, such as |
| 20 | +recording events as atoms in a space instead of printing them. |
| 21 | + |
| 22 | +Two things keep the off path cheap. The level is a field on the interpreter's world, so `log-enabled?` reads |
| 23 | +it rather than matching against a space. And `log!`'s payload is declared `Atom`, so the unevaluated branches |
| 24 | +of `if` leave it alone: the expression that would build the message is never reduced. That lazy argument is |
| 25 | +what Rust's `log` crate gets from a closure and Log4j2 from a lambda; MeTTa's parameter types give it |
| 26 | +directly. |
| 27 | + |
| 28 | +Measured on a 200-iteration loop with tabling off, the off path is flat across a hundredfold change in |
| 29 | +payload cost, 68.6 ms at `(work 10)` and 68.7 ms at `(work 1000)`, while the same loop with the level set |
| 30 | +scales with it, 145 ms to 4765 ms. The same guard written in MeTTa over a space is flat too, but costs about |
| 31 | +40% more per call. |
| 32 | + |
| 33 | +## A missing bang on bind! or import! is reported |
| 34 | + |
| 35 | +`metta check` decides an operator is an action by reading the unit return type `(->)` off its signature. |
| 36 | +`bind!` and `import!` never carried a signature, so it could not see them: a top-level |
| 37 | +`(bind! &s (new-space))` or `(import! &self lib)` written without its leading `!` was stored as data, the |
| 38 | +token stayed unbound and the module never loaded, and nothing said so. The first symptom was a later `match` |
| 39 | +quietly finding nothing. Both now declare the types they already had, so the existing `unevaluated-action` |
| 40 | +warning covers them. |
| 41 | + |
1 | 42 | # MeTTaScript 2.6.0 |
2 | 43 |
|
3 | 44 | Two additions. `metta check` now catches a top-level action form that is stored as data instead of run, and |
|
0 commit comments