Yes, you’re on the right track. You’ll have to cast the registry values ‘as string’ though to use the ‘concatenation’ operator:
q: concatenation ", " of values "InstallLocation" whose (it != "") of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
E: The operator "concatenation" is not defined.
q: concatenation ", " of (values "InstallLocation" whose (it != "") of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of native registry as string)
A: C:\Program Files\7-Zip\, C:\Program Files\Git\, C:\Program Files\Microsoft Office
q: tuple string item 0 of concatenation ", " of (values "InstallLocation" whose (it != "") of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of native registry as string)
A: C:\Program Files\7-Zip\
T: 10.715 ms
I: singular string
That’s how we did it before the ‘tuple string of’ inspector was added, in 9.5.3.
Now with 9.5.3 or higher, there is a safer version using the ‘tuple string of’ inspector. It creates a single tuple string given a group of plural results, and it handles escaping in case the results included embedded commas of their own. That probably won’t come up in this case, it’s unlikely that InstallLocation values will have embedded commas, but if you had other more general cases of wanting the first string of many it could be safer:
q: tuple string of (values "InstallLocation" whose (it != "") of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of native registry as string)
A: C:\Program Files\7-Zip\, C:\Program Files\Git\, C:\Program Files\Microsoft Office
q: tuple string item 0 of tuple string of (values "InstallLocation" whose (it != "") of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of native registry as string)
A: C:\Program Files\7-Zip\
Consider where the strings might have embedded commas of their own, breaking your expectation of ‘tuple string’ -
q: ("to be, or not to be, that is the question"; " -Shakespeare")
A: to be, or not to be, that is the question
A: -Shakespeare
T: 0.369 ms
I: plural string
// manually concatenating doesn't consider the original strings had their own commas
q: concatenation ", " of ("to be, or not to be, that is the question"; " -Shakespeare")
A: to be, or not to be, that is the question, -Shakespeare
T: 0.332 ms
I: singular string
// now we can't tell "our" concatenation from the original embedded commas
q: tuple string item 0 of concatenation ", " of ("to be, or not to be, that is the question"; " -Shakespeare")
A: to be
T: 0.244 ms
I: singular string
// `tuple string of` escapes the original commas by wrapping in parentheses
q: tuple string of ("to be, or not to be, that is the question"; " -Shakespeare")
A: ( to be, or not to be, that is the question ), -Shakespeare
T: 0.149 ms
I: singular string
// tuple string item un-escapes the parentheses that were added by the 'tuple string of' escape
q: tuple string item 0 of tuple string of ("to be, or not to be, that is the question"; " -Shakespeare")
A: to be, or not to be, that is the question
T: 0.077 ms
I: singular string