views:

70

answers:

2

This is a very simple task in every language I have ever used, but I can't seem to figure it out in PowerShell. An example of what I'm talking about in C:

abs(x + y)

The expression x + y is evaluated, and the result passed to abs as the parameter... how do I do that in PowerShell? The only way I have figured out so far is to create a temporary variable to store the result of the expression, and pass that.

PowerShell seems to have very strange grammar and parsing rules that are constantly catching me by surprise, just like this situation. Does anyone know of documentation or a tutorial that explains the basic underlying theory of the language? I can't believe these are all special cases, there must be some rhyme or reason that no tutorial I have yet read explains. And yes, I've read this question, and all of those tutorials are awful. I've pretty much been relegated to learning from existing code.

+2  A: 

Not sure I follow exactly the problem you are encountering. The following shows that this works as expected in PowerShell:

PS> function abs($val) {Write-Host "`$val is $val"; if ($val -ge 0) {$val} `
                                                    else {-$val}}
PS> abs (3+4)
$val is 7
7

As for the best docs on the language, I highly recommend Windows PowerShell in Action by Bruce Payette (he's the guy behind the grammar). If you can wait a few more months (or are OK with an eletronic copy), there is a second edition due out this summer that has been updated for PowerShell 2.0.

You may also find my Effective PowerShell series helpful. Checkout item #10 on PowerShell Parsing Modes.

Keith Hill
+3  A: 

In your case, simply surrounding the expression with parenthesis will allow you to pass it to your function.


You need to do this because PowerShell has more than one parsing mode depending on the beginning of the command.

Expression mode is similar to how most other languages parse - numbers are numbers and strings are quoted.

Command mode treats everything as a string except for variables and parenthesis. Strings here don't need to be quoted.

1+2          Expression mode - starts with number
"string"     Expression mode - starts with quote
string       Command mode - starts with letter
& "string"   Command mode - starts with &
. "string"   Command mode - starts with . and a space
.123         Expression mode - starts with . and number (without space)
.string      Command mode - starts with a . that is part of a command name

You can mix modes in a single line by enclosing the commands with parenthesis.

You can see this effect if you define function abs in the following way:

function Abs($value)
{
    Write-Host $args
    if($value -lt 0) { -$value } else { $value }
}

Abs 1 + 2
#Prints:  + 2
#Returns: 1

Abs 1+2
#Prints:  
#Returns: 1+2

Abs (1 + 2)
#Prints:  
#Returns: 3

Abs (1+2)
#Prints:  
#Returns: 3
Corey Ross
thank you for explaining the modes. I had no idea it even had different modes, as none of the tutorials I have found thus far mentioned any such thing. I didn't try parens because I previously ran into an issue with calling a function with parens where it passed a single array of all the arguments (as the first argument) instead of the arguments in their proper places.
rmeador
@rmeador PowerShell in Action is highly recommended :) The modes are explained there as well. It is book #1.
stej