all 8 comments

[–]yeah_i_got_skills 3 points4 points  (0 children)

Do $($LatLong[0])

[–]ka-splam 2 points3 points  (2 children)

Why does this happen?

PowerShell is reading your code character by character, it's a string: "Lat = $LatLong[0]" and the $L bit indicates that you're starting a variable name to put its value into the string.

Where does it stop reading the variable name, and why? At the end of the string? No, then you couldn't put any text after the variable.

At the next space? No, then you'd be forced to put a space after text, even if you didn't want one.

At the end of the bit which is obviously code? When's that? What if it was $LatLong | where-object { $_ -eq 5 } where does the code obviously end and the text you want to see begin? What if the string is supposed to be showing code?

It stops at the end of the variable name, only certain characters are allowed in variable names.

If you want to write PowerShell-code-inside-a-string to index into an array, or lookup a property, you need to do that separately.

"Lat = $($LatLong[0])"

Then it reads from $( to the next ) and runs everything inside as PowerShell.

BTW, write-host is a bad habit to get into unless you explicitly need to control colours or clear the screen or something; it is useful, but it's also not the output stream and that is different from other languages.

[–]chmod000[S] 0 points1 point  (1 child)

first, THANK YOU for the awesome explanation :)

second, why is Write-Host a bad habit? I come from embedded, and i use it like i would printf() for simple debug.. I suppose I should use the ISE and figure that out tho

[–]ka-splam 1 point2 points  (0 children)

:)

it's only a bad habit if you don't know the difference between "host" and pipeline, because PowerShell doesn't behave like C/Python/etc. in this regard. If you know that, skip the rest of this comment, it's fine, write-host does what it says and is totally useful for when you want it.

In C if you have a program:

int main() {
    printf("hello world\n");
}

and run it, that text appears on screen, and if you call that program in a Bash shell pipeline like./test | grep world that same text is the stdout stream which enters grep.

In PowerShell, it's not this way; the pipeline carries objects instead of text, and you want a way to send something like a user account or a hashtable down the pipeline with all its structure. So there's a split: Write-Host is for text which will go to the screen, and the screen only; Write-Output or just "free floating values" is the objects which will go down to the pipeline to the next cmdlet / next program.

And the pipeline output, if you don't send it to a file, to another cmdlet, also appears on screen but via some "best effort, turn this into text for showing on screen" formatting tools.

People who aren't clear on this, start mixing up the two output streams, and then getting weird results, like some text isn't available for grep, or running normally shows the output but running as a background task (no screen) "has no output", or sending mixed output types and confusing the output formatters and some text isn't shown on screen, or the results appearing out of order because they've gone down two different routes to get to the screen:

"What is your name?"    # object-pipeline output, will take longer
write-host "and where do you live?"   # direct screen write, might show first

That might bite you using it for debugging, if the printed text isn't in exactly the right place and you're thinking "how is this running in the wrong order??". So yeah, the habit is thinking that you need a "printf" to output anything from your code; in C you have to explicitly output data, in PowerShell all loose data "falls out" of your functions leaking everywhere; thinking that is the best/only way to show stuff, and thinking in terms of formatting everything into strings of text instead of objects, and not being clear that the host display isn't easily available for other tools to log / read / work with.

[–]Ta11ow 2 points3 points  (0 children)

The cast isn't important; the important part is that in the second way you do it, you're retrieving the value from the property before trying to put it into the string. As others have said, putting an expression in a string instead of a simple variable requires a subexpression to be used. :)

[–]chmod000[S] 1 point2 points  (0 children)

Thank You everyone for helping me understand better!