Tips: How to avoid redundant code

While working on a module that has a huge memory workload, I wanted to avoid redundant code and used the following nice tips Mike F. Robbins demonstrated in this blog post
First try the following in a console:

$test = 'Heavy task'
($test = 'Heavy task')

Do you see the difference?

Having parentheses around the variable statement also outputs the result in the console.

Isn’t it very nice?

Why there is such a difference?

Having parentheses will make the interpreter parse the simple pipeline/expression (what’s inside the parentheses) in expression mode and output the result of this expression. It’s notation is:

(<expression>)

How do I know this?
Well, I just took the example Bruce Payette gave in the “Statement termination” paragraph in his awesome book “PowerShell in Action” and the error message revealed it šŸ™‚

Let me also quote what’s written in the “grouping /subexpressions and array expressions” paragraph:

Parantheses group expression operations and may contain either a simple expression or a simple pipeline

The notation can be either

(<expression>)

or

(<pipeline>)

Now, consider the if/else statement for a few seconds that has the following notation:

if (<pipeline>) { 
 <statementlist>
} elseif (<pipeline>) {
 <statementlist>
} else {
 <statementlist>
}

It also means that you can do both the variable assignment and test if anything assigned exists inside the if pipeline/expression. It will evaluate to $true if the output exists and to $false if it doesn’t. As far as I remember, some participants in the scripting games were also using this approach and Don Jones talked about it a few years ago (if you’ve a link please share it, I’ll add it).

When you process only once the heavy workload, capture its result into the variable and immediately test if it exists, it also allows to write less code and have a slightly faster execution in memory.
Here’s an example of what I mean:

if ($test = 'do my heavy task/function/cmdlet') {
 $test | Do-Something 
} else {
 Do-SomethingElse
}

Using the above syntax, you can actually avoid writing more code.
Please, let me repeat that there’s nothing wrong in doing the following:

# assign once but outside of the if/else statement
$test = 'do my heavy task/function/cmdlet'
if ($test) {
 $test | Do-Something 
} else {
 Do-SomethingElse
}

But, you definitely should avoid running twice the heavy memory workload if you do:

if ('do my heavy task/function/cmdlet') {
 $test =  'do my heavy task/function/cmdlet' 
 $test | Do-Something 
} else {
 Do-SomethingElse
}

Let’s measure how fast each of these pieces of code run.
I haven’t found better examples yet but you can try these examples.
The first and second examples run almost at the same speed.

# Example1:
# Both variable assignment and test 
# inside the if/else
Measure-Command {
 if ($test = 1..10000 | % { $_ * 2 }) {
  'ok'
 } else {
  'nok'
 }
}

# Example2:
# Variable assignment outside
# and test inside the if/else
Measure-Command {
 $test = 1..10000 | % { $_ * 2 }
 if ($test) {
  'ok'
 } else {
  'nok'
 }
}

# Example3:
# Test an expression
# Late variable assignment
# Runs twice, so avoid it
Measure-Command {
 if (1..10000 | % { $_ * 2 }) {
  $test = 1..10000 | % { $_ * 2 }
  'ok'
 } else {
  'nok'
 }
}

3 thoughts on “Tips: How to avoid redundant code

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.