Creating Dynamic arrays in compiled

If I remember right: it did not used to be possible to create new variables, especially arrays, in a compiled environment. (other than considering a 2D array as an array of arrays)

However, I just ran a test: I executed this code in a compiled environment: and it worked:
<code 4D>
$it:=“a”+Substring(Generate UUID;1;20)
$Code:=“ARRAY TEXT(”+String($it)+";0)"
EXECUTE FORMULA($Code)
$Ptr:=Get pointer($it)
INSERT IN ARRAY($Ptr->;1;5)
ALERT(String(Size of array($Ptr->)))
</code 4D>

Can anyone tell me: how long has it been possible to dynamically create arrays in compiled environment?
Any “gotcha’s”?

You should rewrite that (toxic) code with collections. You should avoid using EXECUTE FORMULA. This command is not needed in normal development.

I know: it’s ugly!
However, there are tons of places where I need to maintain compatibility with legacy code: and this means traditional arrays.

And speaking of EXECUTE FORMULA: because of 4D’s implementation of preemptive processing: I’m using more EXECUTE FORMULA/EXECUTE METHOD than ever: to mask non thread-safe code from the compiler.

Ugly, Ugly, Ugly. …but get’s the job done.

Good to hear.

However, as long as i work with 4D (4D v6.5), it was possible with 4D to create process variables dynamically. But i guess, this is not well documented :mrgreen:

Maybe I was under the wrong understanding:
I knew that in Interpreted mode you could do it: but I thought that in Compiled: there was no creating “new” process (or IP) variables.
Was I wrong?

Only gotcha’s, after I had to work on an application using that at the beginning of this year.

What Gotcha’s?

Very often such “variables” are “declared” in loops:
for($i;1;$guessWhat)
execute formula(“array something(”+“myArray”+string($i)…
end for
Results in $guessWhat process variables that you can’t find in code, using ??? memory, unknown by the compiler, only existing at runtime. In case of problem the code is painful to maintain. As it’s not documented, it may stop working tomorrow (I remember on a recent summit Laurent Esnault talking about the “internal cost” of RESOLVE POINTER and that he’d like to remove it). “Toxic” is the right word. I think EXECUTE METHOD is not the same at all, it’s clean, while I always think twice (and more) before using EXECUTE FORMULA / Get pointer / RESOLVE POINTER.

To answer the original question: this is possible since 4D Compiler 1.0, somewhere back in 1992 if I remember the year right. It always worked.

It was always a dirty workaround. In the beginning it was for some needs the only available solution, to create something like “dynamical” variables. Later versions provided better ways and current versions have much better ways, I’m not aware of any need which could not be solved with a better approach.
But, I understand that modern coding style does not always fits in historic code and the time for a total rewrite is not always available.
Still, before writing new code today, I would think more than twice before using this concept.

If you don’t need 2D arrays, there is no reason to use execute formula. Setup a 2d process array of each type. Then add an API to allocate and clear your dynamically allocated arrays. I use this all the time for listbox arrays and many other things without ever using execute or declaring arrays explicitly. You can also do the same for dynamic scalar variable allocation (using a 1d array for each data type).

For example, here is what it looks like for a QUERY_WITH_COLLECTION method:

<code 4D>
//Like QUERY WITH ARRAY except using a collection.

//$1 - Field pointer.
//$2 - Collection. Each element must be convertible to field type.
//$3 - (optional) Query selection only. Defaults to false.

C_POINTER($1;$field)
C_COLLECTION($2;$cData)
C_BOOLEAN($3;$selOnly)

C_POINTER($nil;$pArray)
C_LONGINT($type)

$field:=$1
$cData:=$2
If (Count parameters>=3)
$selOnly:=$3
End if

$type:=Type($field->)
$pArray:=PM_Variable (ARRAY_Type ($nil;$type))

If ($cData#Null)
COLLECTION TO ARRAY($cData;$pArray->)
End if

If ($selOnly)
QUERY SELECTION WITH ARRAY($field->;$pArray->)
Else
QUERY WITH ARRAY($field->;$pArray->)
End if

PM_CLEAR_VARIABLE ($pArray)

</code 4D>

John,

Setup a 2d process array of each type.
I already have code that does exactly this.

The reason for my original post was the desire to know if there was a BETTER way to accomplish this.
Several posts have told me that the EXECUTE FORMULA method is a “dirty” way to do it: but no one has really told me why: the deep technical stuff.

  • does it cause memory leaks?
  • Will it crash 4D eventually?
  • will it give me dandruff?

I don’t plan to try to “RESOLVE POINTER” to my dynamically created arrays: I’ll keep a Pointer/handle to them.

So, can someone please tell me what the technical issue is with this?

I can let my current code keep working: but I want to understand better.

: Tony RINGSMUTH

The reason for my original post was the desire to know if there was a
BETTER way to accomplish this.
Several posts have told me that the EXECUTE FORMULA method is a
“dirty” way to do it: but no one has really told me why: the deep
technical stuff.

I don’t know in what dimension an EXECUTE FORMULA method would be better other than it takes less code. Other languages (JavaScript, PHP, Lisp) have an “EXECUTE FORMULA” equivalent and the general advice seems to be avoid it unless it is the only option. I have used EXECUTE FORMULA for a long time where it is the only option, but I avoid it if there are other alternatives.

Since PROCESS 4D TAGS works nicely in compiled databases now (parameters, local variables, etc), maybe there is no reason to worry about using EXECUTE FORMULA.

: Tony RINGSMUTH

but no one has really told me why: the deep technical stuff.

  • does it cause memory leaks?
  • Will it crash 4D eventually?
  • will it give me dandruff?

No.
No.
Could happen.

: Tony RINGSMUTH
  • will it give me dandruff?
    More probably headaches :wink:
    The doc says “In compiled mode, all processes you create (user processes) share the same definition of process variables”. I don’t know if it’s true with these “on the fly” variables. I must say that the application I mentioned was using this trick almost as being the only way to declare arrays in the web part, resulting in a bunch of obfuscated variables and a huge memory pressure on server side. It took a lot of time to clean augeas stables. It may explain why I’m a bit upset with such practices.