I've also followed all the new additions since I started.
I barely read any of the DM Guide. Of what I have read, it seems like Dan was a pretty witty guy.
(note: I didn't realize how long this would get. I'm not a writer, and I'm definitely not good at predicting if you'll even take the time and effort to go through this. So, there's a tl;dr.)
I don't remember how exactly I figured out language syntax, I think it just came to me naturally after a while.
A lot of programming is basic algebra; variables and functions, as I've come to know it.
You could say d(x)=a(b(c(x))), but d(x) ends up to be one value, of possibly many possible values.
a(x) = x
b(x) = 2*x
c(x) = 3*x
d(x) = a(b(c(x)))
d(4) = a(b(c(4)))
= a(b(3*4)) = a(b(12))
= a(2*12) = a(24)
d(4) = 24
Procedures in DM take input(s) (AKA arguments), and only return one value (AKA the return value).
Operators work exactly the same way, except their inputs are positioned differently.
There are operators that take 1, 2, or 3 inputs, but only return one output.
There's also the >> and << operators, but of those, only the bit-shift operators actually return something.
(Please note that none of this below is magical, undocumented observations. Everything is mentioned in the DM Reference, like short-circuiting and the fact that operators literally have a "return value" like procs do.)
// all of these expressions are true
What you choose to do with the output is up to you. The important thing is, they don't need an if() to be useful. You can treat the result as any other value, like by storing it in a variable.
A good thing to know about if() statements is, in the end, they're only checking one value (a number, string, object, or null). You can put a ton of operators and procedures (remember, essentially the same) in an if() statement, but in the end, it's just one value.
That's because operators and procedures only return one value.
Combinations of the two don't make a difference, they'll still only return one value.
var hair_r = 255, hair_g = 255, hair_b = 0
Nothing after || matters because cake == "lie".
None of the procs after the || are even called.
This is because of order of operations. (operations -> operator actions)
Playing with order of operations, you can do this:
..() won't be called if mob.locked is true, the && operator stops at the first false value.
You could even say that only if(1) statements pass if they are read like if(!!(c)), where c is the entire condition.
if("blah" && 2)
You should understand that if()s aren't as special as you might think. Conditional operators don't require them, similarly to how alert()s don't require a switch() statement to do anything. (alert() is just a proc, nothing more. It returns a value like everything else.)
Variables, however, are everywhere. Everything can be put inside a variable. If you always use call()() instead of calling procs by name, even procs (not built-in) can be put in variables and dynamically called.
var a = "a"
The above could all be written like this:
if("a" == "a") world << "Yay!"
If you consider the last two lines, you might notice that I did a simple replacement.
Realistically, procedures have much more flexibility and can have many different return values.
proc/a_sometimes() return prob(50) ? "a" : "b"
Some procedures don't care about return values, so you'd never use them when considering other things.
proc/say_hello() world << "Hello, world!"
This has been an over-complication of an extremely simple and fundamental part of most programming anyone will ever encounter:
Variables contain a data; procedures and operators return output data. Wherever you type an operator or procedure, it's replaced by its return value as soon as the code reaches it.
The reason I'm making this post is to make people realize how over-complicated they make some things. I've left out a lot, and if you read anything before the tl;dr, you probably have questions. I'll try to answer them, so long as they're not ridiculous.
Here's a poorly-made fish: </<>