Scripting Languages, Pros and Cons

Posted by Gore on Fri 16 Feb 2007 05:17 PM — 23 posts, 98,322 views.

#0
Could anyone illustrate the pro's and con's of each scripting language that mushclient provides support for? Why should I use Lua over Python, and vice versa? Any other languages worth noting/using, and for what purpose?
USA #1
I would think that Python and Lua are the most reasonable choices if you were to pick solely on the merits of the language: features, cleanliness, etc.

But, Lua seems to get a lot more support around here. That alone is almost all I would need to pick Lua over everything else.

Oh, Lua also is quite portable, and will work for people using Wine and so forth.

Still, I think in the end of the day it depends on what you prefer. All the languages supported by MUSHclient are decent languages. If you're interested in programming after MUSHclient I'd look at Python and Lua, followed JScript, and VBscript and Perlscript last. (I've never seen people using Perlscript. VBscript is at least heavily used if you write little plug-in thingies for Microsoft Office products. JScript is used all over the web so it's important in that respect.)
Australia Forum Administrator #2
The Lua scripting DLL is shipped with MUSHclient, so you can be sure that you (and anyone you give your scripts to), will have Lua.

Most Windows installations have VBscript and Jscript installed, so they can be used with a minimum of fuss.

The other languages have to be downloaded and installed, in some cases this can be a tedious process.

Lua is recommended these days, as a "common base" language, plus it is simple and easy to learn, yet very powerful when you get used to it.
USA #3
I think VBscript is the easiest for new coders.

Lua is the only language that supports grabbing the style of a line, so you'll need to know how to do that if you intend on being able to grab color codes from a line and duplicate it back easily (as far as I know).

The only plugin I've written in Perl was a socket to connect MUSHclient to a webserver for a bot. It works well, and I don't think any of the other languages would have been able to do that as easily.

Matt
Australia Forum Administrator #4
Lua scripting also has various extra things which are not available to other script languages, namely everything on this page:

http://www.gammon.com.au/scripts/doc.php?general=lua

Message boxes, dialog boxes, input boxes, compression, hashing, regular expression processing (both native and PCRE, XML parsing, file picker dialog, progress-bar dialog, and a few other things like extra functionality (as mentioned by MattMc) for existing script functions.

Personally I don't think Lua is harder to learn than VBscript. For one thing, multiple lines in Lua are simply indicated by a line break, whereas with VBscript you have to use an underscore, eg.

Lua



ColourNote ("red", "blue",
            "Here is a long message .....")


VBscript



ColourNote "red", "blue", _
            "Here is a long message ....."


Note the underscore at the end of the first line, which can be fiddly to add/remove if you decide to wrap/unwrap lines.
USA #5
Hmm. Yes, but its clearer and I can imagine that "some" situations may arise where using white space might confuse the parser. Though, if there are any statements that might create such a situation in Lua is far less certain. The reason you get by with it in Lua is that Lua requires () even in cases where VB doesn't. I.e., it clearly designates *start* and *stop* points for things like function parameters, while VB is sloppier about that.
Australia Forum Administrator #6
Exactly. And the reason you need to do that is because functions are "first class values" in Lua. What that means is they can be assigned, just like other variables, which you can't do in VBscript. Here is an example:


function f (a)
  return a * 2
end -- function f

b = f (10)   --> call function f

print (b)    --> 20

g = f        --> assign function f to variable g

b = g (20)   --> call function again

print (b)    --> 40


Note how in the above code, if you use f with the brackets, the function is called.

If you use f without the brackets, you are simply assigning the value of the function (that is, making a copy of the function reference).

You need the brackets when calling a function, even with no arguments, so Lua knows that you need to call it and not simply use the function reference itself.

Amended on Tue 20 Feb 2007 07:18 PM by Nick Gammon
USA #7
I don't think that the Lua parser can ever get confused by whitespace, since Lua is not a whitespace sensitive language. I think there is one exception, though, that I am not remembering at the moment.

And Lua does allow one situation where functions can be called without parentheses:

my_function "my_param"

It's a left-over from Lua's days as a configuration language. I don't remember if you're allowed to have any argument type but string, but that would be a very quick look-up in the Lua manual for anybody who's curious.
Australia Forum Administrator #8
The exception is, that when calling a function, the opening parenthesis has to occur on the same line, as it is ambiguous whether you are assigning a function or calling it.

eg.


b = f
 (10)   --> error: ambiguous syntax (function call x new statement) near '('


This is because a function name may occur inside parenthese (I forget why), like this:


function f (a)
  print (a)
end -- function f

(f) (22)


Since a line can start with something inside brackets, it is ambiguous in this sort of case which one is intended, an assignment or a function call.


a = f
(g) (22)


You can disambiguate by using a semicolon, eg.


a = f;
(g) (22)

Amended on Wed 21 Feb 2007 04:37 AM by Nick Gammon
USA #9
Oh, right, I knew it had something to do with functions, but had forgotten what it was. Good call.

Not sure why you'd want a function name to be within parentheses either. Since Lua does not allow assignments as expressions, it wouldn't be for that reason. Maybe it has to do with some kind of expression returning a function, but I'm not sure why you'd need parentheses in those cases.
USA #10
Quote:
a = f;
(g) (22)


Wait, what!?!

That is as confusing as hell even "with" the semicolon, at least to anyone that rationally assumes that () is *supposed* to designate parameters or some other distinct seperation of function. lol
Amended on Wed 21 Feb 2007 05:17 PM by Shadowfyr
USA #11
Parentheses can designate parameters to a function call but also expressions, and a function is an expression, so there's nothing terribly surprising about that syntax if you're familiar with other languages than e.g. VBScript. I'm not exactly sure why it's useful, but it's quite common to see a function call on the result of an expression.

e.g.
function g()
return function() return 5 end
end

print (g()()) -- 5
Australia Forum Administrator #12
Quote:

That is as confusing as hell even "with" the semicolon, at least to anyone that rationally assumes that () is *supposed* to designate parameters ...


There is an interesting discussion on this point, on this page:

http://www.wowace.com/wiki/Coding_Tips

One of the points made there, is that this can be a function call:


("foo bar"):sub(3, 5) == "o b"


This is because strings have an implied metatable (the string table), and thus that expression is really the same as:


string.sub("foo bar", 3, 5) == "o b"


The important point is, that using that construct, which the syntax of the language supports for a function call, means a function call can start with brackets.

Now whilst most people won't code like that, when language implementors sit down and write a language parser, they have to make it unambiguously support everything in the language specification, even if some things won't be written by humans.

Many languages have a "statement terminator" syntax, so that the parser can know when one statement ends, and another starts. For example:

  • C / C++ / PHP - statements are terminated by the ";" character
  • Cobol - statements are terminated at the end of the line, unless there is a "continuation character" in column 6 of the next punched card.
  • Visual Basic - statements are terminated at the end of the line, unless the line ends with the "_" character. Also, you can use ":" to separate multiple statements on one line.


Now Lua does not require a specific terminator character, however in occasional places it requires a semicolon to disambiguate.

I don't think I have ever found this to be a problem except when I occassionally put a function call on one line, and start its arguments on the next (usually because the line is very long). eg.


a = b + c + d + f
    (x, y, z)


This above code gives the error message. All you have to do is make sure the function name and its opening bracket are on the same line, either:


a = b + c + d + f (
    x, y, z)


or


a = b + c + d + 
    f (x, y, z)


or


a = b + c + d + f (x, y, z)


I think this one idiosyncracy is not too bad, as it lets you have multi-line statements, without either needing "_" at the end of each line (as in VB) or a semicolon at the end of every statement everywhere (as in C).
Amended on Wed 21 Feb 2007 07:06 PM by Nick Gammon
Australia Forum Administrator #13
Quote:

... () is *supposed* to designate parameters ...


You can't really make that blanket statement anyway. Take for a simple example:


a = (3 + 4) * 5


In that case ( ... ) does not designate parameters.
Amended on Wed 21 Feb 2007 07:10 PM by Nick Gammon
USA #14
Well, I mean in context of placing it on the line alone really. Generally something like (g) would be an error, because it presumes something it being (returned) or some subdivision is happening, like in math, etc. Its just damned odd, and most compilers/interpretters would freak when running across it, because they assume you completely missed some part of the line, such as an assignment. In fact, I would be willing to bet that most would return some error like, "Error on line blah. Missing = in assignment." QBasic just says, "Error: Missing Statement". Which is basically the same thing as saying, "I expected something like 'a =' in front of that '(g)'.

Its just not standard in "any" language I ever hear of to allow it, since most of them assume that () without a function name in front of them is automatically the equivalent of placing '(4 + 4)' on a blank line by themselves. It can do the math, but has no idea what to "do" with it after, so simply doesn't allow it at all.
USA #15
Shadowfyr, fire up your trusty text editor, enter the following:

int main()
{
  4+4;
  (4+4);
  return 0;
}


then compile it. Report back on what you get.

It is perfectly legal in very many language for an expression to be a statement. Now, the compiler will probably warn you about effectless statements (as above) but in general an expression is not necessarily without effects.

I'm curious what data points you have for making very broad statements about what "most compilers/interpreters" would do. For starters, every language behaves differently, so it's hard to make blanket statements about what "should" work in all language. And secondly, this construct is legal in many languages to begin with. So, I'm wondering what languages you are basing your claim on, because in many languages I know of, it is in fact perfectly legal to have expressions as statements without assignments etc.

Maybe QBasic doesn't like it, but then again, maybe QBasic isn't exactly a paradigmatic example of general programming languages.
Australia Forum Administrator #16
Quote:

Its just damned odd, and most compilers/interpretters would freak when running across it, because they assume you completely missed some part of the line, such as an assignment. In fact, I would be willing to bet that most would return some error like, "Error on line blah. Missing = in assignment."


Do this in Jscript in MUSHclient:


(a = 1);

Note (a);


That compiles OK, and prints "1".

The same thing works in C or C++.

In those languages what look like statements, for example:


a = 1;


... are really expressions that happen to have side effects (in this case, changing the value of a).

In fact, you can also do this:


Note (a = 1);


In this case "a = 1" is setting the value of a to 1, and also returning 1 as the result of the expression, which is then printed. The point is, it is valid to leave the word Note out, it still sets a to 1, and the brackets are still valid.

It is valid to put expressions in brackets, so my example further back is perfectly OK.

Thus, the compiler does not object, as you predicted.

The nice thing about Lua is that it doesn't insist either on a statement terminator (like the ";" in C / C++ / Java), or a "there is one statement per line" mentality like VBscript.

But, in one, rather obscure case, you need to put the semicolon in, to avoid ambiguity.
USA #17
Ok, ok. I guess most of them treat results returned by such a thing the same way they do if you where to define a function, but not assign the function to a result, i.e.:

function a(b)
a = b++
end function

a(5)

c = a(5)

Both of the calls are valid, one just does basically nothing. This is slightly odd, to me at least, in cases where the implication is that it "must" be passing a value. And yeah, I am most used to variations of Basic, as well as other languages, in which such a (a(5)) construct is not legal on the line by itself.
USA #18
I think a problem is that you are assuming that a function does nothing but return a value, and has no side effects. If a function were indeed to never modify anything and only return values, then yes, it would be odd to call a function on its own.

But, a function can do all kinds of things:
- it can modify the objects passed in (if they're by reference)
- it can modify global values
- it can write to output (or something like that)

In all of those cases, and more, it makes sense to call a function and throw away its return value. Saying that a function call does nothing when you don't store its return value is a very dangerous statement to make. Even in VB that's not true (see e.g. my three scenarios above).
USA #19
Quite a lot of the time, functions have the thowaway values that are very useful for debugging or error catching. Like if you have a loadfile function that returns a 0 if everything is fine, a 1 if the file didn't exist, and a 2 if the file was corrupt, then you could display better error messages to the user, or to the program itself.

As for the 'example' that was given, a better one to show would be this:

function a(b)
  print d
  d = d++
  a = b++
end function

d = 1
a(5)
print d

c = a(5)
print d

Still think the first call of a(5) does nothing? For your example, it's not really demonstrating anything at all, since you could have just put the number 6 on the line by itself and had the same effect. I think the main problem is comparing BASIC to, well, pretty much anything useful. Most languages nowadays don't care about functions or procedures, and they treat them the same. Procedures just always return a value of nil.
USA #20
Sigh. Not what I meant. I mean it does nothing with "any value returned". Sorry I wasn't clear about that. In a case like (4+4) by itself, the implication, to anyone that doesn't just like placing useless junk in their code, would be that "something" was supposed to happen to that value, not just throwing it out. Its like dumping NOP into the middle of machine language code, not because you need it for some critical timing issue (which with faster CPUs its almost worthless for), but "Just because I felt like it". The difference being, NOP is a valid instruction. Doing:

MOV A, &h4
PUSH A
ADD A, &h4
POP A

makes no damn sense. You're not doing anything. A good compiler/interpreter should "tell you" that its not going to do anything, or at least warn you, not just shrug its proverbial shoulders and go, "Well, ok. Not a problem." Something like the (a(5)) situation is a lot more ambigous, so... maybe you should be allowed to get by with it. But to me its still really odd syntax.
USA #21
It is indeed odd to just put (4+4) on its own line. And the compiler I used (gcc 4) does warn you about it. However it's not illegal, and in general it would be rather hard to validate expressions in general as being with or without effects. That is why it's up to the programmer to deal with it.

As for (a(5)), that's a side effect of the syntax of expressions. Nick went over that, but basically it has to do with the fact that in many languages:
- expressions can be used as statements
- a(5) is an expression
- (expression) is an expression)
- therefore (a(5)) is an expression
- therefore (a(5)); on its own is an expression.
Australia Forum Administrator #22
Quote:

... the implication, to anyone that doesn't just like placing useless junk in their code, would be that "something" was supposed to happen to that value ...

... A good compiler/interpreter should "tell you" that its not going to do anything, or at least warn you ...


True. And gcc does exactly that, if you compile with an appropriate warning level. The default doesn't.

This example demonstrates this:


int main (void)
  {
  5;
  return 0;
  } // end of main

$ gcc test.c -Wall
test.c: In function `main':
test.c:3: warning: statement with no effect


However your earlier position was:

Quote:

I would be willing to bet that most would return some error ...


The line with "5;" on it is an example of an expression that effectively does nothing. As you suggested, a warning can be issued. However, it does not raise an error, as it is within the boundaries of the syntax of the language.

Warnings are effectively saying "you are allowed to do this, but are you really sure it is a good idea?".