Type global initilizers must be constant
BlitzMax Forums/BlitzMax Programming/Type global initilizers must be constant
| ||
Not really a bug report but rather a defect report, so to speak. I don't understand why global variables inside types are restricted to constant values. Global MyVar:MyType = New MyType compiles perfectly when outside of a type, but not within. Which can easily look inconsistent given that practically, putting a global variable inside a type affects only its scope. This was for the "at first sight" side of things. Actually I do see the difference: when doing "Global MyVar:MyType = New MyType" at global scope we not only declare a variable, but also put a statement (MyVar = New MyType) in the main program code, *at the location of the declaration*. When declaring a global variable inside a type, comes the question of where to put that "MyVar = New MyType" statement. I'd like to advocate in putting it right before the type declaration. That is Type MyType Global obj:MyType2 End Typeis equivalent to Global obj:MyType2 Type MyType End TypeExcept of course for the fact that you'd still access it via MyType.obj and not just obj As long as it is clearly specified in the docs I can't see any problem with this solution. A practical example of what it would allow: Type MyType Global g_List:TList = New TList Method New() g_List.AddLast(Self) End Method Method Delete() g_List.Remove(Self) End Method End TypeThat is, emulating the blitzbasic global list for a given class. Currently we are forced to put the global variable at the global scope, and to pollute the global namespace with something that should really be inside the the type. Or worse, always check inside the MyType instances if the list is allocated and if not do it. |
| ||
I suppose the problem is that outside of the type, it is very clear when the initializer code will be executed. But when should globals inside the type be initalized? |
| ||
Type MyType Global g_List:TList = New TList Method New() if g_list = null g_list = new TList endif g_List.AddLast(Self) End Method Method Delete() g_List.Remove(Self) End Method End Type |
| ||
Sorry to quote myself guys ... @Robert: That's exactly what I said. Or tried to say: When declaring a global variable inside a type, comes the question of where to put that "MyVar = New MyType" statement. and to me the solution seems simple: I'd like to advocate in putting it right before the type declaration. @Dreamora: This isn't a pleasing solution as I said: Or worse, always check inside the MyType instances if the list is allocated and if not do it. Simply because it adds an overhead. Sure this is mostly peanuts, but why having to live with it if the problem can be fixed easily by allowing non constant initializers? Also it simply makes the code less elegant and more error prone as you'll need to check g_List against Null every time you access it. In this case you'd better wrap that in a getter, which actually is a common idiom in other languages to enforce the singleton pattern Type MyType Global g_List:TList Function GetGlobalList:TList() If g_list = Null g_list = New TList EndIf Return g_List End Function Method New() GetGlobalList().AddLast(Self) End Method Method Delete() GetGlobalList().Remove(Self) End Method End Type But that's another additional overhead. And I'd like to have the choice not to have this overhead. I think this is perfectly legitimate, especially when considering there is apparently no real problem in fixing this. If there is I'd simply like to know what it is. |
| ||
Actually I think I will stick to the global inside types solution, and just put myself the "g_List = New TList" statement right before the type declaration (like I'd like BlitzMax to do for me behind the scenes).MyType.g_List = New TList Type MyType Global g_List:TList Method New() g_List.AddLast(Self) End Method Method Delete() g_List.Remove(Self) End Method End TypeWhich is already infinitely better than checking inside the MyType instances if the list is null or not. And *certainly* not that bad considering that we can't hide g_List from the outside anyway, due to the lack of support for Private/Public inside types (might be another feature request..), so we'll always be able to initialize type globals from the main program. I must say I had missed this fact, how accostumed to hiding class members I am (in other languages). But please Mark, take a moment anyway to consider adding this one day. Put that in your bag of minor but nice improvments. Or drop a post if there is is some killer problem for doing it. |
| ||
Hi, I'd like to see this in too, and it shouldn't be too tricky to add. Initializers would probably have to run *before* all main code, though, as you have to guarantee they execute. Anyways, this is high on my list of non-module things to do! |
| ||
Sweet. Glad to hear that :) And indeed this is certainly better for the general case to make it execute before everything else in the current module/program (in the order of type globals declaration). Thanks. |