So I've been playing with MSH, and even though it's awesome, unless I'm wrong, it has some fatal problems. I really don't want to see MSH go down the drain.
I'm not too sure where to take my suggestions for MSH, so it'd be nice if someone could give me a few pointers. Or maybe someone could just tell me if I'm mistaken in one way or another.
Two things: code sharing and consistency of syntax. I'll start with code sharing.
Edit: since the code sharing problem seems to be harder to understand than the syntax one (at least the way I've written it), I'll start with syntax instead.
Syntax: From what I understand, MSH is built with the idea of being easy to learn for anyone "1337"; that is, anyone with some UNIX shell knowledge or some programming (specifically .NET) knowledge. Which is pretty evident in the expressiveness, and which I appreciate.
On the other hand, this seems to cause some really awkward side effects. One that really bothers me is the function invocation syntax.
Suppose I have a function defined as follows:
function Pow($var, $exp) { [Math]::Pow($var, $exp) }
Coming from C#, I try to use Pow like this:
Pow(2,
+ 3;
It throws an exception, telling me that the value can't be converted from System.Object[] to System.Double. What happened here is that 2, 8 was tokenized as an array of two objects, rather than two arguments to Pow.
The correct way to use Pow is not
Pow(2,
+ 3; (results in an exception)
nor is it
Pow 2 8 + 3; (result is 256)
but it's
(Pow 2 8) + 3 (result is 259)
The correct way to use [Math]::Pow is not
[Math]::Pow 2 8 + 3 (results in an exception)
but it's
[Math]::Pow(2,
+ 3 (result is 259)
Apparently the only difference is that Math.Pow is invoked through .NET, whereas Pow is a function defined in MSH. Intrinsically both are identical, yet the correct syntax is totally different. When invoking a .NET method, x, y means "two parameters: x and y", whereas when invoking a MSH function, x, y means "an array of two objects: x and y".
A function like Sqrt($val), which would only take one argument, works fine with the normal C-like call expression. Anything else and it starts getting funky.
Two things that bug me about this:
1. The call Pow 2 8 + 3 throws no error, but the result is 256. Because MSH never complained, I wouldn't have known. This sort of thing is extremely dangerous, especially considering MSH is intended to be used casually for file manipulation.
2. Learning MSH is like learning two languages at the same time. I could learn through trial and error, which is just asking for bugs, or I could learn by studying it intensely -- which defeats MSH's purpose as a quick-to-learn language.
The solution would be, quite simply, to either make Foo 3 5 the only valid syntax, or to ditch instantiating arrays by just CSVing objects. Really, 3; 5 and {3, 5} are good enough. 3, 5 just isn't necessary.
Code sharing: One of the cool things about MSH is that you can share code on a function or script file level. If you have a cool function, you just paste it on your blog or on a forum or what not. The trouble begins when you have scripts that span multiple functions or reference other scripts.
Say Foo is a function that you want to share on your blog. Foo makes a call to Bar, which you also created. You post Foo on your blog, but a reader complains that he needs Bar for Foo to run. So a couple days later, when you're not too busy, you give them Bar. But they already have their own version of Bar, which just got overrided by Bar (for the MSH instance in which it's run). So their version of Bar suddenly doesn't do what they'd expect it to (Edit: okay, this seems to be true only if you have something defined in $profile, since that goes public).
Two problems arise in this example: In sharing anything more than a simple bit of code, you'll easily lose track of which methods, aliases, vars etc you need to provide; and in doing so, you risk a conflict between their existing code and your code. This can be expected to happen very often, since you're essentially relying on luck to avoid name conflicts.
In sharing anything more than a simple bit of code, you'll easily lose track of which methods, aliases, vars etc you need to provide.
A solution to the first problem would be to provide some sort of dependency check mechanism which sharers could run to make sure their audience is given everything they need. A solution to the second problem would be to use some form of namespacing.
Which ever the case, this needs to be fixed ASAP, or MSH will immediately lose its value as an easily shareable language.
I'd get these issues fixed by the first release even if it means breaking CTP code. Otherwise MSH is going to be so bug-prone that it'll be abandoned.
(MSH needs Anders 