ZScript Discussion

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Locked
User avatar
Eevee
Posts: 592
Joined: Wed Jul 16, 2003 5:26 am
Contact:

Re: ZScript Discussion

Post by Eevee »

dpJudas wrote:To me, the key feature of static typing is that it is documentation. To me, and the IDE 'go to reference' system. The type being used is often more useful knowledge to me than the variable name, or at the very least a strong hint what I can expect it to contain. I'm yet to find a way in dynamic languages to convey this information to other developers in a realistic way.
This always seemed a little overblown to me. A lot of arguments are something trivially obvious from both the type and the name, like "Environment environment", or they're a very generic type that's meaningless without the name, like "int num_players". I'm not saying you're wrong, just that types aren't automatically good documentation, and at least a good bit of the time they don't tell you any more than the name.
dpJudas wrote:A fine example of what you get from types being clearly declared to your fellow programmers.
Oh, certainly. I'm aware I'm arguing this both ways. :)

I'm not completely opposed to static typing. I do like the look of Rust, though I haven't found an excuse to write something substantial in it yet. My objections are that it's a lot of upfront effort that only might justify itself later, and most type systems just aren't good enough. Squabbling with a type system because it just doesn't have a way to express an otherwise robust idea is incredibly annoying. So is using a type system that can't express constraints I think are important, like "this is not nullable".

It's nicer to have for a larger codebase, but I seriously doubt many ZDoom mods will compare in size to, say, ZDoom.
dpJudas wrote:But at least you know its a sector_t* and not a subsector_t*. In a dynamic language there is no way of knowing.
I'm aware! I've used them before. ;) Though in a dynamic language you might want those particular types to be interchangeable in some cases...
dpJudas wrote:Imagine the floating point rewrite done to the software renderer in a dynamic language. As it is right now, half the types are double and other half fixed_t. I can see exactly which are which - in a dynamic language I'd be doomed.
You're thinking about it in terms of a static language without the type annotations. In some ways (not all!) it could be easier in a dynamic language, because none of those types would be declared in the first place; they would just be "something like a number". You could convert a few fixeds to doubles at a time and let them propagate throughout the system without having to change anything else. Rig math operators to convert fixed operands to doubles, change a few macros, and you're already mostly done.

I've done some wacky refactors on fairly large dynamic codebases, and they're much less intimidating if you're willing to embrace the dynamism when it's helpful. Especially for refactors that touch runtime behavior more than mere code structure. You're free to introduce temporary wrapper types, for example, without touching either the underlying type or the code that consumes it.
Graf Zahl wrote:Let's not forget something: ZScript needs to interact and integrate with a large and complex existing native C++ class hierarchy.
Fair! I do think I could make actor class creation work with Lua, which doesn't even have classes, but I haven't actually tried it yet. Or maybe not having classes would make it easier?
Graf Zahl wrote:@dpJudas: I fully agree on the documentation feature of strong types. The last Javascript project I worked on was a textbook example of playing loose with a liberal language: It was close to impossible to deduce what was which because the former developer showed no discipline either documenting his code or giving his variables self-descriptive names, or even using them consistently.
Strong typing means no implicit runtime conversion. Python is fairly strongly typed; C is somewhat weakly typed.

If this developer can't even name variables sensibly, what makes you think the code would've been any better in a statically-typed language? I envision that kind of dev making a struct like this and using it everywhere:

Code: Select all

struct data {
    int int1;
    int int2;
    int int3;
    string str1;
    string str2;
};

// arg1 is an x/y coordinate, where (int1, int2) are (x, y)
// arg2 is the player data, where str1 is the name and ints 1-3 are a model color
// now imagine these comments weren't here.  good luck!
void create_player(data& arg1, data& arg2);
Easier and faster than designing a robust set of types, but it'll still type check just fine. And it'll be just as horrible to debug or untangle — much worse than well-written dynamic code. You can prevent common pitfalls, and you can offer robust tools, but you can't force good design.

I need a shower after writing that struct. Let's hope this hypothetical person doesn't find out about downcasting.
Graf Zahl wrote:To be blunt: It's the completely wrong way to go, and the mere fact that Microsoft invented TypeScript to get around Javascript's deficiencies tells me more than anything else. A typed language forces the programmer to put in a lot more thought up front and to me that's only a good thing.
I think you have this backwards. People use TypeScript because they want to — because they're already putting thought into their architecture, and they want a compiler to double-check their effort. Someone who doesn't value good architecture isn't going to suddenly "get it" because they have to write out type names. The whole point of static typing is that you get to express the constraints you made up; nothing says the constraints have to be sensible.

At the end of the day, ZScript is yours to design however you want, but please at least believe that it's entirely feasible to write typeless code that isn't total garbage — and equally feasible to write typeful code that is. :)
Last edited by Eevee on Thu Nov 24, 2016 3:59 am, edited 1 time in total.
User avatar
Eevee
Posts: 592
Joined: Wed Jul 16, 2003 5:26 am
Contact:

Re: ZScript Discussion

Post by Eevee »

ZZYZX wrote:ZScript. Is. Not. DECORATE.
Since as we know Graf has a very special meaning of deprecation (that is, DECORATE is going to stay forever), people who are unable to comprehend proper programming may as well just stay with DECORATE.
No need to break and/or limit the language that was designed to be low-level and thus obviously more error-prone.
Hasn't Graf been saying that the type system is supposed to make it less error-prone? :) Anyway, Rust, while still in relatively early days, is a pretty solid rejection of the idea that low-level code needs to be brittle in the same ways that C is.
ZZYZX wrote:What would the target pointer return if the monster has no target?
Look at the examples I gave of Rust's optional type. That's probably a bit more generic than ZScript needs, granted. I'm less familiar with Swift, but it operates on largely the same principles and has some nicer syntax specifically for optionals. I think this is how Swift works:

Code: Select all

void A_Func()
{
    // NOT OK, compile error because this hasn't been checked
    print(target.health);

    if target != nil {
        print(target.health);  // ok
    }

    if let mytarget = SomeClass(target) {
        print(mytarget.user_whatever);  // ok
    }
}
Less generic than Rust, but more natural to C folks, which maybe Graf will appreciate. The trouble with a two-step process (cast, check for null) is that you can forget one of the steps, it still looks like it works, and you'll never find out anything's wrong unless you happen to hit that crash; something like the above prevents you from forgetting the check when necessary.
ZZYZX wrote:My suggestion is to introduce the C# separation here, the struct metatype and the class metatype. Class can be null, Struct can never be null (but can be undefined though, and that's a compile-time error).
It would be pretty much useless though, as IIRC currently ZScript has two general kinds of objects: primitives like int/double/bool which can't be null and Actor-derived objects which naturally have to be able to be null.
Hm, that's an interesting approach. But it wouldn't really help with the problem of optional target or potential failed typecast, yeah.
Last edited by Eevee on Thu Nov 24, 2016 4:03 am, edited 1 time in total.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: ZScript Discussion

Post by ZZYZX »

Wait, so you are suggesting that casting null to a type should fail? Basically making null a separate type? Then it's actually pretty nice, although I haven't seen languages that implement this :P
Eevee wrote:
dpJudas wrote:To me, the key feature of static typing is that it is documentation. To me, and the IDE 'go to reference' system. The type being used is often more useful knowledge to me than the variable name, or at the very least a strong hint what I can expect it to contain. I'm yet to find a way in dynamic languages to convey this information to other developers in a realistic way.
This always seemed a little overblown to me. A lot of arguments are something trivially obvious from both the type and the name, like "Environment environment", or they're a very generic type that's meaningless without the name, like "int num_players". I'm not saying you're wrong, just that types aren't automatically good documentation, and at least a good bit of the time they don't tell you any more than the name.
I don't think he meant quite that.
Imagine we have an abstract def add_vertex(v).
Now, we already know that add_vertex is something that's supposed to add a vertex and that v is probably a vertex.
But what type v is and how do I call this function? In a language that has static typing, the function would look like bool add_vertex(Vertex v), which would hint me that the function can return true/false and takes a parameter of type Vertex, which (in a proper IDE) could be looked up directly by following the declaration. Feel the difference.
This is something I hate about Python and sometimes JS. Only the totally awesome collection handling makes me not hate Python in general.
Remembering how I worked with PyQt4 and it was a nightmare because it has strict type checking in function arguments, but the expected types are listed in separate doc page.
Last edited by ZZYZX on Thu Nov 24, 2016 4:09 am, edited 1 time in total.
User avatar
Eevee
Posts: 592
Joined: Wed Jul 16, 2003 5:26 am
Contact:

Re: ZScript Discussion

Post by Eevee »

ZZYZX wrote:Wait, so basically you are suggesting that casting null to a type should fail? Basically making null a separate type? Then it's actually pretty nice, although I haven't seen languages that implement this :P
Whoops, I edited my post with some Swift syntax while you were replying. But yes, null is a "separate type" in Swift and Rust and others — or, rather, "nullable T" is a separate type, and a plain T can never be null.
ZZYZX wrote:I don't think he meant quite that.
Imagine we have an abstract def add_vertex(v).
Now, we already know that add_vertex is something that's supposed to add a vertex and that v is probably a vertex.
But what type v is and how do I call this function? In a language that has static typing, the function would look like bool add_vertex(Vertex v), which would hint me that the function can return true/false and takes a parameter of type Vertex, which (in a proper IDE) could be looked up directly by following the declaration. Feel the difference.
Yes, but you figured half of that out already just from the letter "v". Make it "vertex" and you're confident; problem solved, and it's still shorter.

That bool is actually throwing me off; why would adding a vertex fail? Does it even mean failure? I have no idea. Almost like "bool" doesn't really convey all that much. ;) I also can't tell if you intended this function to do math on a vertex, or add a vertex to a mesh or something.

Admittedly I'm pretty used to not relying on IDEs, but it seems unlikely that ZScript will have one. One small advantage of a dynamic runtime (which some static languages have, like Java) is that you can inspect APIs from within a running system, no IDE required.
ZZYZX wrote:Remembering how I worked with PyQt4 and it was a nightmare because it has strict type checking in function arguments, but the expected types are listed in separate doc page.
Oh, no, does it just link to the C++ documentation? That's hot garbage, but kind of par for the course for generated bindings.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: ZScript Discussion

Post by ZZYZX »

Eevee wrote:
ZZYZX wrote:I don't think he meant quite that.
Imagine we have an abstract def add_vertex(v).
Now, we already know that add_vertex is something that's supposed to add a vertex and that v is probably a vertex.
But what type v is and how do I call this function? In a language that has static typing, the function would look like bool add_vertex(Vertex v), which would hint me that the function can return true/false and takes a parameter of type Vertex, which (in a proper IDE) could be looked up directly by following the declaration. Feel the difference.
Yes, but you figured half of that out already just from the letter "v". Make it "vertex" and you're confident; problem solved.

That bool is actually throwing me off; why would adding a vertex fail? Does it even mean failure? I have no idea. Almost like "bool" doesn't really convey all that much. ;)

Admittedly I'm pretty used to not relying on IDEs, but I note that ZScript will almost certainly not have one.
Well first off, adding a vertex could fail if it's a Triangle::add_vertex or a Quad::add_vertex and you are trying to add excessive vertices :)
Besides, vertex structure could be uninitialized if it depends on something else (for example on GL context being initialized).
And you still probably don't get it. The def add_vertex(v) could be used as add_vertex((1,4,2)), it could be used as add_vertex(Vertex(1,4,2)), it could allow floats/doubles, it could NOT allow floats/doubles, in JS they could even do add_vertex({x:1,y:4,z:2}) because they love JSON. And all this can be seen in the docs or by just reading the class declaration in case of static type being defined.
Eevee wrote:
ZZYZX wrote:Remembering how I worked with PyQt4 and it was a nightmare because it has strict type checking in function arguments, but the expected types are listed in separate doc page.
Oh, no, does it just link to the C++ documentation? That's hot garbage, but kind of par for the course for generated bindings.
No, they have separate documentation, and it's pretty hard to navigate in that one compared to the official C++ one. They have docstrings too, but then again due to how Python works IDEs have serious problems navigating the hierarchy automatically so I have to read the docs manually anyway.
Last edited by ZZYZX on Thu Nov 24, 2016 4:18 am, edited 1 time in total.
User avatar
MaxED
Posts: 2246
Joined: Tue Feb 28, 2012 12:55 pm

Re: ZScript Discussion

Post by MaxED »

Eevee wrote:why would adding a vertex fail?
Well, here are 4 random reasons:
- vertex coordinates are outside of expected coordinates range.
- there's already a vertex at given coordinates.
- vertex coordinates are undefined (like float.NaN is C#).
- resulting vertex count exceeds the maximum supported vertices count.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49235
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript Discussion

Post by Graf Zahl »

Eevee wrote:
Graf Zahl wrote:To be blunt: It's the completely wrong way to go, and the mere fact that Microsoft invented TypeScript to get around Javascript's deficiencies tells me more than anything else. A typed language forces the programmer to put in a lot more thought up front and to me that's only a good thing.
I think you have this backwards. People use TypeScript because they want to — because they're already putting thought into their architecture, and they want a compiler to double-check their effort.
I don't think I have anything backwards. The point of TypeScript was precisely that: Allow more error checking on compile time. And that's why I am very skeptical about untyped languages, they defer too much error checking to run time. I have worked with such languages and they require a lot more testing because far less problems can be found while programming. Ultimately they cost time, not save some.
Eevee wrote: Someone who doesn't value good architecture isn't going to suddenly "get it" because they have to write out type names. The whole point of static typing is that you get to express the constraints you made up; nothing says the constraints have to be sensible.)
So what's the point of a language that makes EASIER for such hacks to unload their shit onto the world? The WWW is already a cesspool of shitty code, mostly spawned by the 'made for dummies' approach of Javascript, that was generall aimed at people who have no good grasp at programming concepts and made it easy for them to write code without ever learning to code first.
Edward-san
Posts: 1774
Joined: Sat Oct 17, 2009 9:40 am

Re: ZScript Discussion

Post by Edward-san »

Graf Zahl wrote:And how would that work? A null check is often just at the top of a function, after that the pointer is free to use.
I mean adding some capabilities to the parser, like making CFG (control flow graph) and then do an analysis on the pointer usage...
User avatar
Eevee
Posts: 592
Joined: Wed Jul 16, 2003 5:26 am
Contact:

Re: ZScript Discussion

Post by Eevee »

ZZYZX wrote:Well first off, adding a vertex could fail if it's a Triangle::add_vertex or a Quad::add_vertex and you are trying to add excessive vertices :)
Besides, vertex structure could be uninitialized if it depends on something else (for example on GL context being initialized).
See, "add_vertex" sounded to me like doing addition with a vertex, not adding to a collection. So even with types it's easy to be mistaken :)
ZZYZX wrote:And you still probably don't get it. The def add_vertex(v) could be used as add_vertex((1,4,2)), it could be used as add_vertex(Vertex(1,4,2)), it could allow floats/doubles, it could NOT allow floats/doubles, in JS they could even do add_vertex({x:1,y:4,z:2}) because they love JSON. And all this can be seen in the docs or by just reading the class declaration in case of static type being defined.
Oh, no, no. This is what I meant in that earlier post, about imagining dynamic code as just being static code with the types missing. The answer is: who cares? As long as you pass in some kind of sequence of some kind of numbers, it's fine. You don't have to screw around with turning a vector into an array or whatever. Can you iterate it? Great, gimme. I've written code that makes heavy use of a point type, and it will merrily accept (1, 2) or [1, 2] or Point(1, 2) anywhere. Everything consistently returns a Point, but is happy to accept anything point-like.

Dynamic languages would definitely be terrible if they were just C++ but with someone hiding all the types from you. :) The whole attitude is different.
Graf Zahl wrote:I don't think I have anything backwards. The point of TypeScript was precisely that: Allow more error checking on compile time. And that's why I am very skeptical about untyped languages, they defer too much error checking to run time. I have worked with such languages and they require a lot more testing because far less problems can be found while programming. Ultimately they cost time, not save some.
I have also worked with such languages, and obviously I disagree. But since you mention tests: the relative ease with which I can bang out a couple automated tests is invaluable. I don't even particularly like writing tests, but I'll write a few little ones here and there just because it's trivial to do so. I've seen enough statically typed projects that have no tests at all, apparently assuming that a few checks on argument types mean nothing can ever go wrong. Then they're plagued by crashes and regressions.

ZDoom's source is 23 years old, older than some people on this forum. Does it have an automated test suite?
Graf Zahl wrote:So what's the point of a language that makes EASIER for such hacks to unload their shit onto the world? The WWW is already a cesspool of shitty code, mostly spawned by the 'made for dummies' approach of Javascript, that was generall aimed at people who have no good grasp at programming concepts and made it easy for them to write code without ever learning to code first.
Oof. Now you're not really arguing for static checking so much as you're arguing for weeding out beginners.

I'm happy to see as many people try their hand at my craft as possible, even if they don't have as much experience as I do yet. Modding for a simple 3D video game seems like an obvious place to start, too, but this makes me wary of suggesting ZDoom to people interested in getting their feet wet.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49235
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript Discussion

Post by Graf Zahl »

Eevee wrote:I have also worked with such languages, and obviously I disagree. But since you mention tests: the relative ease with which I can bang out a couple automated tests is invaluable. I don't even particularly like writing tests, but I'll write a few little ones here and there just because it's trivial to do so. I've seen enough statically typed projects that have no tests at all, apparently assuming that a few checks on argument types mean nothing can ever go wrong. Then they're plagued by crashes and regressions.
Even better when you do not even have to write tests, eh? Half the tests I had to do for JS was to cope with the lack of typing - stuff that would not even have been necessary in a strictly typed language! Sometimes I can't even shake off the feeling that automated test suites were just invented to work around the shortcomings of untyped languages. :twisted: (And still, with the JS-code I have seen it even makes me wonder if the people who really should do such things actually do. Probably not.)

ZDoom's source is 23 years old, older than some people on this forum. Does it have an automated test suite?
To be honest, I wouldn't even know where to start with this code base... Too much of it violates every concept I value as a programmer, but the oh so important needs of remaining compatible prevent me from fixing all the inherent design flaws.
Graf Zahl wrote:So what's the point of a language that makes EASIER for such hacks to unload their shit onto the world? The WWW is already a cesspool of shitty code, mostly spawned by the 'made for dummies' approach of Javascript, that was generall aimed at people who have no good grasp at programming concepts and made it easy for them to write code without ever learning to code first.
Oof. Now you're not really arguing for static checking so much as you're arguing for weeding out beginners.
No, I am criticizing that these languages make it too easy to program without first learning programming. I have seen too often in my 22 years as a profesional developer where this leads to. It's always the same: Quick first results make these things appealing, but beware if the project grows, the mess is inevitable.

I'm happy to see as many people try their hand at my craft as possible, even if they don't have as much experience as I do yet. Modding for a simple 3D video game seems like an obvious place to start, too, but this makes me wary of suggesting ZDoom to people interested in getting their feet wet.
I prefer that people interested in these things actually take the time to learn so that in the process they become better programmers.
Hell Theatre
Posts: 23
Joined: Sat Apr 30, 2016 10:33 am

Re: ZScript Discussion

Post by Hell Theatre »

Eevee wrote:Walls of text

I guess we are down to "My programming philosophy is better than yours", eh?

Obviously you seem to be the type who is completely sold on all these abstract programming concept that have been surfacing in recent years. They all share one thing: Abstract away the gory details of programming to make the job supposedly easier.

Graf is right on one point: It's an illusion. You cannot make a job easier by hiding the pitfalls. All you do is make the problems harder to detect. Not being a programmer myself, I still work in a company where a lot of coding takes place and I have to say, I find it disturbing how much the automated testing had to be increased the more abstract the development languages became. There seems to be a directly proportional relation between the amount of abstraction and the amount of increased testing this requires.

My personal impression is that the stricter a language is, the lower is the risk of hidden errors. I agree that C++ is too low level for many things where performance is a secondary concern, but I'd take Java and even more C# over all those neat 'user friendly' language that seem to be so popular at any day. It's hard to say if it's the language itself or the people working with it or the tasks that are solved in these languages, but with these typed languages things appear to go far more smoothly than with Javascript.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49235
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript Discussion

Post by Graf Zahl »

Hell Theatre wrote: but I'd take Java and even more C# over all those neat 'user friendly' language that seem to be so popular at any day.
I'll be honest here: If C# didn't depend on a large runtime environment I'd already have tried to port ZDoom to it. By far the best of the bunch by a wide margin.
User avatar
MaxED
Posts: 2246
Joined: Tue Feb 28, 2012 12:55 pm

Re: ZScript Discussion

Post by MaxED »

NET Core 1.0.1 runtime is 27 Mb. I won't call it "large".
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49235
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript Discussion

Post by Graf Zahl »

Depends on the relation to what you want to do with it. It's also not platform independent.
User avatar
MaxED
Posts: 2246
Joined: Tue Feb 28, 2012 12:55 pm

Re: ZScript Discussion

Post by MaxED »

Graf Zahl wrote:It's also not platform independent.
Depends on the relation to what you call "platform independent".
Another option is MonoGame, which comes with OpenGL support out of the box and requires installing a 33 Mb redistributable to run. This will theoretically allow running ZDoom on iOS, Android, MacOS, Linux, all Windows platforms, OUYA, PS4, PSVita, and Xbox One.
Locked

Return to “Scripting”