Home Explore Blog CI



nushell

16th chunk of `blog/2022-03-22-nushell_0_60.md`
8633c8141b8fd881dd2f733cca729d712fb0b7688d805c0d0000000100000fb4
Another important area of correctness we wanted to fix from previous versions of Nushell was error spans. Prior Nushell versions struggled with a very common pattern: errors that happen in code that isn't the code you just typed. For example, aliases that failed, calls to custom commands that were previously defined, and more.

In 0.60, along with keeping around code that's still available for the user to call, we also keep around the original span information and original source. This allows us to give better errors for the cases where the error refers to code that's not the current line.

## Bind once, run anywhere

While improving the parser and engine, we also improved how the two connected to each other. One piece of this was "binding", that is, how definition sites and use sites connect to one another.

In the new engine, we use unique identifiers for all forms of definition in the engine, including variables, declarations, aliases, modules and more. During parse time, we bind the use we see against the definition in scope, and replace the use with a reference to the ID we found. With this, we can later safely export or pass the containing block without losing track of what the original code meant.

## Faster than ever before

The new engine's data representation is also quite a bit lighter than before. This allows us to evaluate scripts with less overhead. Early results are already quite positive:

| 1 million iteration tight loop | timing |
| ------------------------------ | ------ |
| 0.44                           | 626ms  |
| 0.60                           | 239ms  |

| Gradient drawing benchmark | timing |
| -------------------------- | ------ |
| 0.44                       | 168ms  |
| 0.60                       | 78ms   |

## Going parallel

The new engine has a fun trick up it's sleeve: you can effortlessly convert your scripts to run in parallel by changing `each` calls to `par-each`.

For example, if we had a script that opened files that fit a certain pattern and counted their number of lines:

```
ls **/*.rs | each { |row|
  let num_lines = (open $row.name | lines | length)
  {name: $row.name, loc: $num_lines}
}
```

We can turn this into a script that runs in parallel by changing the `each` to `par-each`:

```
ls **/*.rs | par-each { |row|
  let num_lines = (open $row.name | lines | length)
  {name: $row.name, loc: $num_lines}
}
```

| Line counter script | timing |
| ------------------- | ------ |
| `each`              | 683ms  |
| `par-each`          | 447ms  |

While further improvements are possible, it's nice to know we can get such a speedup with a four character change to our script.

# New plugin architecture

Rather that scanning for all new plugins on startup like we did with 0.44 (and taking ages to start Nu), the new `register` command stores the
location and signature of your plugins, making it easier to load at start up.

```
> register -e json ~/.cargo/bin/nu_plugin_extra_query
```

Also, the new plugin architecture is now multi-protocol, allowing you to pick the right protocol for your plugin. We currently support json and have experimental support for capnp.

By the way, you are not limited to write plugins in Rust. You can even create a python script and use it as a Nushell plugin. You only need to
specify what command should be used to run the plugin

```
> register -e json -s python ~/my_plugins/plugin.py
```

Nushell now has three optional plugins (all using 'json' serialization):

- `inc`: a value/version incrementor
- `gstat`: a git stats viewer
- `query`: a set of three commands for querying data

# Breaking changes

There are quite a number of breaking changes as we fixed design flaws, cleaned up the design, and rethought how commands should work.

| Nushell 0.44                             | Nushell 0.60                                                                                                                                                                                                       |

Title: Engine Improvements: Error Spans, Binding, Performance, Parallel Processing, and Plugin Architecture
Summary
This section discusses several improvements in Nushell's engine. It covers improved error spans by retaining original source information, a robust binding system using unique identifiers for definitions, significant performance gains demonstrated through benchmarks, the introduction of parallel processing with `par-each`, and a new plugin architecture with faster startup and multi-protocol support. It also mentions the ability to create plugins in languages other than Rust.