HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Static structures in newgen?

11-16-2007, 12:47 PM#1
Strilanc
Can a structure be declared static (can't be instanciated) in NewGen? Also, can a structure be declared permanent (can't be destroyed)?

These aren't necessary for any functionality, they just help make it explicit that destroying/creating structure X is a mistake. Of course, a static structure as little more than a library, but structures have some properties I like (no order dependency, private and readonly members). Permanent would be useful for structures representing players and teams.

Currently I use
Collapse JASS:
//note the PRIVATE, which throws scope errors if anything outside tries to create the structure
private static method create takes nothing returns nothing
  //show error message, just in case
  return 0
endmethod
to prohibit creation, which works alright (except it takes up 4 lines, and doesn't block allocate). The same thing doesn't work for destroy, though.

*edit* An actual suggestion for NewGen:
Make structures typesafe (don't allow haphazard conversions to integers and back) and give a method to enumerate all instances of structure. Something as simple as S.first() and S.next(s) would work great.
11-16-2007, 03:48 PM#2
Malf
Static structs == interfaces.

You don't really need to add the private prefix to the create method. Just add it to the struct itself.
11-16-2007, 04:17 PM#3
Earth-Fury
Quote:
Originally Posted by Strilanc
*edit* An actual suggestion for NewGen:
Make structures typesafe (don't allow haphazard conversions to integers and back) and give a method to enumerate all instances of structure. Something as simple as S.first() and S.next(s) would work great.
Structs are type-safe... if you do:
MyFuncTakesInt(structvar)
it should (but maybe still doesn't) generate an error. but you can do explicit typecasts ala:
MyFuncTakesInt(integer(structvar))

also, enumerating for all structs of a type is as simple as defining a static array and a static count variable within the struct itself. add items to the array on create, remove them on destroy... simple.

and anyway, why would you need a static structure like that?
11-16-2007, 05:26 PM#4
Strilanc
Quote:
Originally Posted by Earth-Fury
Structs are type-safe... if you do:
MyFuncTakesInt(structvar)
it should (but maybe still doesn't) generate an error. but you can do explicit typecasts ala:
MyFuncTakesInt(integer(structvar))

also, enumerating for all structs of a type is as simple as defining a static array and a static count variable within the struct itself. add items to the array on create, remove them on destroy... simple.

and anyway, why would you need a static structure like that?

It still allows implicit conversion.

I do use that technique for enumeration. The problem is I end up doing for almost all my structs. When you write the same block of code over and over again, it's a sign it should be handled by the language. Also, it takes even more code to make it thread safe.

The main reason I want a static structure is because I want readonly variables. As far as I know you can't get readonly variables in a library. readonly is really useful because it lets you give access to sensitive values without writing a ton of get functions.

Quote:
Static structs == interfaces.

You don't really need to add the private prefix to the create method. Just add it to the struct itself.

Interfaces are close, but they can't actually contain any code. For example
Collapse JASS:
interface A
  public method B takes nothing returns nothing
  endmethod
endinterface
throws errors. Declaring the structure private doesn't work either.

----

To be clear, what I want to do is the equivalent of:
Collapse JASS:
static struct S
  readonly integer i = 0
  public method increase takes nothing returns nothing
    set S.i = S.i + 1
  endmethod
endstruct

//elsewhere ...

function F takes nothing returns nothing
  call S.increase()
  call DisplayTextToForce(GetPlayersAll(), "val: " + I2S(S.i))
endfunction
function BAD takes nothing returns nothing
  local S s //error: can't instanciate S
  call S.create() //error: no create method
endfunction
11-17-2007, 08:00 AM#5
Pyrogasm
I'll just pop this over to Triggers and Scripts.

As far as I know (which may be very limited), this should not error:
Collapse JASS:
interface A
  public method B takes nothing returns nothing
  //no endmethod
endinterface
11-17-2007, 10:16 AM#6
Malf
So THAT's the only thing you want? Easy stuff, rly.

Collapse JASS:
globals
    private integer N = 0
endglobals

function F takes nothing returns nothing
  set N = N+1
  call DisplayTextToForce(GetPlayersAll(), "val: " + I2S(N))
endfunction
11-18-2007, 12:10 AM#7
Strilanc
Quote:
Originally Posted by Malf
So THAT's the only thing you want? Easy stuff, rly.

Collapse JASS:
globals
    private integer N = 0
endglobals

function F takes nothing returns nothing
  set N = N+1
  call DisplayTextToForce(GetPlayersAll(), "val: " + I2S(N))
endfunction

No, that is not what I want. I want *readonly* access to N. Obviously I don't need to apply it to situations as simple as the example. I have structures with a ton of variables I don't want to accidentally modify elsewhere in the code, but I do want to be able to know their values.

That is not the issue though. The issue is that I want to make a static struct.
11-18-2007, 12:13 AM#8
Malf
You want a static struct for what? You don't need read only things, just don't modify 'N' where not needed.
11-18-2007, 01:16 AM#9
Strilanc
Quote:
Originally Posted by Malf
You want a static struct for what? You don't need read only things, just don't modify 'N' where not needed.

... I think you are missing the point of having scopes in the first place. I don't like getting into bad programming habits just because I'm working with a game.
11-18-2007, 01:34 AM#10
Malf
First of all, just what the hell are you trying to say?

Quote:
Originally Posted by You
No, that is not what I want. I want *readonly* access to N. Obviously I don't need to apply it to situations as simple as the example. I have structures with a ton of variables I don't want to accidentally modify elsewhere in the code, but I do want to be able to know their values.

Then DON'T modify them. There is no need for static structs, if you disagree, I'll need you to explicitly explain what you need it for.
11-18-2007, 10:18 PM#11
Strilanc
I've solved my problem, at least partially. I use these:

Collapse JASS:
    ///Shorthand for making a structure permanent (only provides warnings, almost no compile-time enforcement)
    //! textmacro EnforcePermanent takes StructureName
        private method onDestroy takes nothing returns nothing
            call DisplayTextToForce(GetPlayersAll(), "Critical Map Error: destroyed a permanent structure ($StructureName$).")
        endmethod
    //! endtextmacro

    ///Shorthand for making a structure static (only provides warnings, partial compile-time enforcement)
    //! textmacro EnforceStatic takes StructureName
        private method onDestroy takes nothing returns nothing
            call DisplayTextToForce(GetPlayersAll(), "Critical Map Error: destroyed a static structure ($StructureName$).")
        endmethod
        private static method create takes nothing returns $StructureName$
            call DisplayTextToForce(GetPlayersAll(), "Critical Map Error: attempted to instanciate a static structure ($StructureName$).")
        endmethod
    //! endtextmacro
Collapse JASS:
struct S //! runtextmacro EnforceStatic
  //a structure that complains when you create or kill it
  //also (mostly) stops you from using create
endstruct
struct S //! runtextmacro EnforcePermanent
  //a structure that complains when you kill it
endstruct
11-18-2007, 10:27 PM#12
Vexorian
You can get rid of create by making it private. So your text macro doesn't really need the error message.

Since you are not going to allow the player to use create, .destroy will always do nothing and show an error if debug mode is enabled.

So, just have a private create method and done.

I think verbatin declaration of this create method is less complicated than the text macro, but I guess this is a taste issue...
11-18-2007, 11:08 PM#13
Strilanc
Quote:
Originally Posted by Vexorian
You can get rid of create by making it private. So your text macro doesn't really need the error message.

Since you are not going to allow the player to use create, .destroy will always do nothing and show an error if debug mode is enabled.

So, just have a private create method and done.

I think verbatin declaration of this create method is less complicated than the text macro, but I guess this is a taste issue...

The main reason for the warning is to avoid creation inside the structure itself. The onDestroy method in EnforceStatic is mainly to warn me about the left-over onDestroy methods I have in structures from before I used the macro.

I like the text macro form better because it makes the intention obvious and takes 0 extra lines. On the downside, text macros look ugly. Really. Ugly. I understand where your taste is coming from.
11-18-2007, 11:55 PM#14
Vexorian
Quote:
The main reason for the warning is to avoid creation inside the structure itself

That would be worthless since inside the structure you can always use allocate anyways...

I don't really understand why would you want to add that stuff to an struct that was before intended to be created.

I don't think private create is any less obvious than textmacro stuff.