::: details Statements which don't return a value
Some keywords in Nushell are _statements_ which don't return a value. If you use one of these statements as the final expression of a custom command, the _return value_ will be `null`. This may be unexpected in some cases. For example:
```nu
def exponents-of-three [] {
for x in [ 0 1 2 3 4 5 ] {
3 ** $x
}
}
exponents-of-three
```
The above command will not display anything, and the return value is empty, or `null` because `for` is a _statement_ which doesn't return a value.
To return a value from an input list, use a filter such as the `each` command:
````nu
def exponents-of-three [] {
[ 0 1 2 3 4 5 ] | each {|x|
3 ** $x
}
}
exponents-of-three
# => ╭───┬─────╮
# => │ 0 │ 1 │
# => │ 1 │ 3 │
# => │ 2 │ 9 │
# => │ 3 │ 27 │
# => │ 4 │ 81 │
# => │ 5 │ 243 │
# => ╰───┴─────╯
:::
::: details Match expression
```nu
# Return a random file in the current directory
def "random file" [] {
let files = (ls)
let num_files = ($files | length)
match $num_files {
0 => null # Return null for empty directory
_ => {
let random_file = (random int 0..($num_files - 1))
($files | get $random_file)
}
}
}
````
In this case, the final expression is the `match` statement which can return:
- `null` if the directory is empty
- Otherwise, a `record` representing the randomly chosen file
:::
## Custom Commands and Pipelines
Just as with built-in commands, the return value of a custom command can be passed into the next command in a pipeline. Custom commands can also accept pipeline input. In addition, whenever possible, pipeline input and output is streamed as it becomes available.
::: tip Important!
See also: [Pipelines](./pipelines.html)
:::
### Pipeline Output
```nu
ls | get name
```
Let's move [`ls`](/commands/docs/ls.md) into a command that we've written:
```nu
def my-ls [] { ls }
```
We can use the output from this command just as we would [`ls`](/commands/docs/ls.md).
```nu
my-ls | get name
# => ╭───┬───────────────────────╮
# => │ 0 │ myscript.nu │
# => │ 1 │ myscript2.nu │
# => │ 2 │ welcome_to_nushell.md │
# => ╰───┴───────────────────────╯
```
This lets us easily build custom commands and process their output. Remember that we don't use return statements like other languages. Instead, the [implicit return](#returning-values-from-a-command) allows us to build pipelines that output streams of data that can be connected to other pipelines.
::: tip Note
The `ls` content is still streamed in this case, even though it is in a separate command. Running this command against a long-directory on a slow (e.g., networked) filesystem would return rows as they became available.
:::
### Pipeline Input
Custom commands can also take input from the pipeline, just like other commands. This input is automatically passed to the custom command's block.
Let's make our own command that doubles every value it receives as input:
```nu
def double [] {
each { |num| 2 * $num }
}
```
Now, if we call the above command later in a pipeline, we can see what it does with the input:
```nu
[1 2 3] | double
# => ╭───┬───╮
# => │ 0 │ 2 │
# => │ 1 │ 4 │
# => │ 2 │ 6 │
# => ╰───┴───╯
```
::: tip Cool!
This command demonstrates both input and output _streaming_. Try running it with an infinite input:
```nu
1.. | each {||} | double
```
Even though the input command hasn't ended, the `double` command can still receive and output values as they become available.
Press <kbd>Ctrl</kbd>+<kbd>C</kbd> to stop the command.
:::
We can also store the input for later use using the [`$in` variable](pipelines.html#pipeline-input-and-the-special-in-variable):
```nu
def nullify [...cols] {
let start = $in
$cols | reduce --fold $start { |col, table|
$table | upsert $col null
}
}
ls | nullify name size
# => ╭───┬──────┬──────┬──────┬───────────────╮
# => │ # │ name │ type │ size │ modified │
# => ├───┼──────┼──────┼──────┼───────────────┤