Type UDT
Dim As String S = "You lost!"
End Type
Const As String S0 = "You won!"
Dim Shared As UDT u0
u0.S = S0
#define initializer u0
'--- Zone beginning of code insertion ---
#undef shared
#define shared
'--- Zone ending of code insertion ------
Dim Shared As UDT u = initializer
Print u.S
Sleep
'--- Zone beginning of code insertion ---
#undef initializer
type UDT2
declare constructor(byref as string)
declare operator cast() as UDT
as string _s
end type
constructor UDT2(byref S as string)
THIS._s = S
end constructor
operator UDT2.cast() as UDT
dim as UDT u
u.S = THIS._s
return u
end operator
#define initializer UDT2(S0)
'--- Zone ending of code insertion ------
#undef initializer
type UDT2
declare constructor(byref as string)
declare operator cast() as UDT
as string _s
end type
constructor UDT2(byref S as string)
THIS._s = S
end constructor
operator UDT2.cast() as UDT
dim as UDT u
u.S = THIS._s
return u
end operator
#define initializer UDT2(u.S)
There is something anyway I don't understand. The UDT2 constructor is called first at the very begining, maybe before all the instructions, as shown by printing something from inside UDT2 constructor...
Type UDT
Dim As String S = "You lost!"
End Type
Const As String S0 = "You won!"
Dim Shared As UDT u0
u0.S = S0
? "why am I second?", u0.S
#define initializer u0
'--- Zone beginning of code insertion ---
#undef initializer
type UDT2
declare constructor(byref as string)
declare operator cast() as UDT
as string _s
end type
constructor UDT2(byref S as string)
? "why am I first?", S
THIS._s = S
end constructor
operator UDT2.cast() as UDT
dim as UDT u
u.S = THIS._s
return u
end operator
#define initializer UDT2(u.S)
'--- Zone ending of code insertion ------
Dim Shared As UDT u = initializer
? "third here is neither win or lost"
Print "::"; u.S
Sleep
Yes, it is a correct solution but much more complex than mine:
- You use an additional UDT with constructor and cast operator (13 lines in all).
- I use only simple function (5 lines in all):
'--- Zone beginning of code insertion ---
#undef initializer
Function createInitUDT () As UDT
Dim As UDT u
u.S = S0
Return u
End Function
#define initializer createInitUDT()
'--- Zone ending of code insertion ------
NOTES (for Shared variables excluding Common variables):
Generally a Shared variable may only be initialized with a constant value (its starting value is set at the start of the program in the .data section before any code is run, and so it cannot depend on any variables or functions in it).
A first exception is a Shared variable of var-len string type, that never can be initialized, even with a constant string (because of its structure with a descriptor in the .data section, but to point to a dynamic memory block).
A second exception is a Shared variable of user-defined type having a constructor even implicit, that can be initialized with a non-constant value (because it's the constructor code, called when the program starts, which writes the "initial" values into the .data section).
FreeBASIC supports non-constant initializers in case the Shared variable is a user-defined type with constructor:
- In addition to hard-coding the value into the .data section, the global variable's constructor must be called anyways when the program starts, so it may aswell allow non-constant initializers which will end up being arguments in the constructor call.
The above UDT has an implicit constructor because it contains a complex pseudo-object (a var-len string) as member.
fxm wrote:Yes, it is a correct solution but much more complex than mine
Your solution is a kind of external copy-constructor, that's a nice tip.
But it's still a little weird that u0.S has lost its value in the meantime. For instance neither me or you reuse it: I can't do UDT2(u0.S) for instance, which was what I wanted first rather than UDT2(S0)...
And the execution order is absolutly weird (see paragraph 3 about UDT2 constructor).
This challenge points out very mysterious affairs.
Whatever the positions of the lines 'Dim Shared .....' in the program body, there are all executed at the top of program, before execution of the other lines.
fxm wrote:Whatever the positions of the lines 'Dim Shared .....' in the program body, there are all executed at the top of program, before execution of the other lines.
About the printing, I miss totally the trick, line 1 is not executed first?
OK, I see now, you mean that not only dim shared is executed first, but it's initialization too! This is something that looked to me totally separated.
? "why am I second to print? (line 1)"
Type UDT
Dim As String S = "You lost!"
End Type
Const As String S0 = "You won!"
Dim Shared As UDT u0
u0.S = S0
#define initializer u0
'--- Zone beginning of code insertion ---
#undef initializer
type UDT2
declare constructor(byref as string)
declare operator cast() as UDT
as string _s
end type
constructor UDT2(byref S as string)
? "why am I first to print? (constructor)"
THIS._s = S
end constructor
operator UDT2.cast() as UDT
dim as UDT u
u.S = THIS._s
return u
end operator
#define initializer UDT2(S0)
'--- Zone ending of code insertion ------
print !"\n(line 32)
Dim Shared As UDT u = initializer
Print u.S
Sleep
Last edited by Tourist Trap on Jan 17, 2017 15:36, edited 1 time in total.
fxm wrote:See documentation at : Storage classes , paragraph 'Static'.
I thought that "dim shared" or static and so on were just reserving free space at the begining of the program, but that initialization as further assignations would be executed at any time (following the execution order). Ok, now that's clearer. But then I think that initializing a shared variable with a UDT is not the best practice ever ;)
Well done Tourist Trap.
I knew that if fxm actually defines something, it begs for a re definition.
Here's a trivial one along the lines of first come, first served.
Declare Sub A
Declare Sub B
Declare Sub C
Declare Sub D
Declare Sub E
Declare Sub F
F:E:D:C:B:A:Sleep:End
'============= 3 lines to produce ABCDEF on the console (colons) without cls ==============
'==============================================================================
Sub A
Print __function__;
End Sub
Sub B
Print __function__;
End Sub
Sub C
Print __function__;
End Sub
Sub D
Print __function__;
End Sub
Sub E
Print __function__;
End Sub
Sub F
Print __function__;
End Sub
Sleep
'============= 3 lines to produce ABCDEF on the console (colons) without cls ==============
#undef __function__
Function __function__ () As String : Static As Integer cursor : Function = iif(cursor=0, "A", iif(cursor=1, "B", iif(cursor=2, "C", iif(cursor=3, "D", iif(cursor=4, "E", "F"))))) : cursor += 1 : End Function
'==============================================================================