Compatibility of the tricky dynamic arrays with dynamic arrays - arrays

Considering the old trick to make an array
Type
IntArray = Array Of Integer;
PIntArray = ^IntArray
PTDynIntArray = ^TDynIntArray;
TDynIntArray = Array[0..0] Of Integer;
{later...}
GetMem(APTDynIntArray,100*SizeOf(Integer));
APTDynIntArray^[49] := 50
Is There a way to make this tricky array compatible with a standard dynamic array ?
For example, If I want to translate an old (lets say from 1999) unit with
Procedure DoSomething(Data: PTDynIntArray);
And considering that the data will be processed using the above syntax (dataname-dereference-index in brackets), Delphi compiler will not stop if I pass a PIntArray as argument, however I get an AV at run-time (I guess that Delphi considers, in this case, that PIntArray Is the same as PTDynIntArray)
So can these two types (PIntArray and PTDynIntArray) be combined, type casted, inter-changed ? How ?

You can convert an IntArray (note: not PIntArray) to a PTDynIntArray. The reverse is not generally possible.
An IntArray is stored as a pointer to the first element of the array. The array is preceded by information about the array's length and such, but if your procedure only accesses the array elements, they won't do any harm.
You may, to be explicit, also write it as #IntArray[0].

Related

Statically allocate array with struct containing a string

I am writing a program that has an array which size I know, it is a fixed instruction set. Each entry in the array maps to an struct of the opcode and some metadata, such as the function that implements the opcode and its name, a String.
I need to allocate the array before I actually compute and fill the instruction set on each opcode.
Rust won't let me allocate such array statically, even if I know the size and when the initialized state does NOT require ANY pointers, as I would like all strings to be empty, which means no allocations and you could have a "zero value" of the string that is preferably fine to be copied.
Any suggestions? Is there anyway to do it?
Seems Rust really likes to you use a Vec for everything? Even when static memory, which should be preferable on a non GC program language, would have been possible in many cases such as this? This is confusing.
From the rust reference:
If the length operand has a value greater than 1 then this requires that the type of the repeat operand is Copy or that it must be a path to a constant item.
Therefore, to initialize an array using [VALUE; NUM] syntax, either the type implements the Copy trait or that VALUE is a const.
As pointed out by Chayim Friedman, you can use code like below:
const EMPTY: Instruction = Instruction { name: String::new() };
static ARRAY: [Instruction; 5] = [EMPTY; 5];
However, if you are working with a fixed set of data, it might be easier to just populate the list with predefined names, using &'static str.
If there is a need to create an array from a value that cannot be made to a constant and is not Copy, you can use std::array::from_fn like so:
let value = String::new();
let array: [_; 6] = std::array::from_fn(|_| value.clone());

How to declare a static array with variable length in delphi?

I need an array, that is optimized for one-time-initialization at runtime, with a given length. So memory should be allocated at runtime, but I don't need to change its length.
Is there a array-type other than the pure dynamic array? (it seems to be not the optimal choice for this task)
Bonus would be, if the initialized array is indexable via pointer-iteration, so all it's elements are allocated consecutive in memory.
Is this all just a daydream of a non-experienced programmer, or is there a possibility to achieve this?
I could imagine to do this with manual memory allocation, but maybe there's another way.
Edit:
My main concern is the reading and writing speed of the array.
Just use an external Count: integer variable, and use the dynamic array length as the "capacity" of the array. It would avoid most memory allocation, if the initial capacity of the array is well defined.
In practice, TList<T>, as defined in the System.Generics.Collections unit, is using this scheme: it stores internally an array, but it has its own Count property. I suspect this is what you were looking for.
For a more low-level stuff, with more features (like JSON or binary serialization, or fast lookup via a hash of one or several properties), you may take a look at our TDynArray dynamic array wrapper. Those are just wrappers on existing dynamic arrays, not data holder like TList<T>. And they work from Delphi 5 or older, and also FPC.
You can encapsulate what you desire in a generic type. Like this:
type
TFixedLengthArray<T> = record
strict private
FItems: TArray<T>;
FLength: Integer;
function GetItem(Index: Integer): T; inline;
procedure SetItem(Index: Integer; const Value: T); inline;
public
property Length: Integer read FLength;
property Items[Index: Integer]: T read GetItem write SetItem; default;
class function New(const Values: array of T): TFixedLengthArray<T>; static;
end;
{ TFixedLengthArray<T> }
class function TFixedLengthArray<T>.New(const Values: array of T): TFixedLengthArray<T>;
var
i: Integer;
begin
Result.FLength := System.Length(Values);
SetLength(Result.FItems, Result.FLength);
for i := 0 to Result.FLength-1 do begin
Result.FItems[i] := Values[i];
end;
end;
function TFixedLengthArray<T>.GetItem(Index: Integer): T;
begin
Result := FItems[Index];
end;
procedure TFixedLengthArray<T>.SetItem(Index: Integer; const Value: T);
begin
FItems[Index] := Value;
end;
Create a new one like this:
var
MyArray: TFixedLengthArray<Integer>;
....
MyArray: TFixedLengthArray<Integer>.New([1, 42, 666]);
Access items like this:
for i := 0 to MyArray.Length-1 do
Writeln(MyArray[i]);
This just wraps a dynamic array. Elements are contiguous. The length of the array is determined once and for all then a new instance is created.
One thing to watch out for here is that the type will behave like a reference type since its data is stored in a reference type. That is, the assignment operator on this type will behave in the same manner as dynamic array assignment.
So if we have two variables of this type, arr1 and arr2 then the following occurs:
arr1 := arr2;
arr1[0] := 42;
Assert(arr2[0] = 42);
If you wanted to make the type behave like a true value then you would implement copy-on-write inside SetItem.
Update
Your edit to the question changes is significantly. It seems that you are in fact concerned more with performance than encapsulation.
The inlining of the item accessor methods in the above type means that the performance characteristics should be close to that of an array. The access will still be O(1), but it is quite plausible that the inliner/optimiser is weak and fails to emit the most optimal code.
Before you decide that you must use arrays to obtain the absolute ultimate performance, do some real world benchmarking. It seems to me to be quite unlikely that the code to read/write from an array is really a bottleneck. Most likely the bottleneck will be what you then do with the values in the array.

Can Ada functions return arrays?

I read somewhere that Ada allows a function only to return a single item. Since an array can hold multiple items does this mean that I can return the array as a whole or must I return only a single index of the array?
Yes, an Ada function can return an array - or a record.
There can be a knack to using it, though. For example, if you are assigning the return value to a variable, the variable must be exactly the right size to hold the array, and there are two common ways of achieving that.
1) Fixed size array - cleanest way is to define an array type, e.g.
type Vector is new Array(1..3) of Integer;
function Unit_Vector return Vector;
A : Vector;
begin
A := Unit_Vector;
...
2) Unconstrained array variables.
These are arrays whose size is determined at runtime by the initial assignment to them. Subsequent assignments to them will fail unless the new value happens to have the same size as the old. The trick is to use a declare block - a new scope - so that each assignment to the unconstrained variable is its first assignment. For example:
for i in 1 .. last_file loop
declare
text : String := Read_File(Filename(i));
-- the size of "text" is determined by the file contents
begin
-- process the text here.
for j in text'range loop
if text(j) = '*' then
...
end loop;
end
end loop;
One warning : if the array size is tens of megabytes or more, it may not be successfully allocated on the stack. So if this construct raises Storage_Error exceptions, and you can't raise the stack size, you may need to use access types, heap allocation via "new" and deallocation as required.
Yes, an Ada function can return an array. For example, an Ada String is "A one-dimensional array type whose component type is a character type." Several of the functions defined in Ada.Strings.Fixed—including Insert, Delete, Head, Tail and Trim—return a String.

How to allocate a non-constant sized array in Go

How do you allocate an array in Go with a run-time size?
The following code is illegal:
n := 1
var a [n]int
you get the message prog.go:12: invalid array bound n (or similar), whereas this works fine:
const n = 1
var a [n]int
The trouble is, I might not know the size of the array I want until run-time.
(By the way, I first looked in the question How to implement resizable arrays in Go for an answer, but that is a different question.)
The answer is you don't allocate an array directly, you get Go to allocate one for you when creating a slice.
The built-in function make([]T, length, capacity) creates a slice and the array behind it, and there is no (silly) compile-time-constant-restriction on the values of length and capacity. As it says in the Go language specification:
A slice created with make always allocates a new, hidden array to which the returned slice value refers.
So we can write:
n := 12
s := make([]int, n, 2*n)
and have an array allocated size 2*n, with s a slice initialised to be the first half of it.
I'm not sure why Go doesn't allocate the array [n]int directly, given that you can do it indirectly, but the answer is clear: "In Go, use slices rather than arrays (most of the time)."

When to use array and when to use cell array?

In Matlab, I was trying to put anonymous functions in an array:
>> a=[#(k)0.1/(k+1) #(k)0.1/(k+1)^0.501]
??? Error using ==> horzcat
Nonscalar arrays of function handles are not allowed; use cell arrays
instead.
So I wonder what kinds of elements are allowed in an array, and in a cell array?
For example, I know that in an array, the elements can be numerical or strings. What else?
In short: Cell array is a heterogeneous container, regular array is homogeneous. This means that in a regular array all of the elements are of the same type, whereas in cell array, they can be different. You can read more about cell array here.
Use cell array when:
You have different types in your array
You are not sure whether in the future you might extend it to another types
You are working with objects that have an inheritance pattern
You are working with an array of strings - almost in any occasion it is preferable to char(n,m)
You have a large array, and you often update a single element in a function - Due to Matlabs copy-on-write policy
You are working with function handles (as #Pursuit explained)
Prefer regular array when:
All of the elements have the same type
You are updating the whole array in one shot - like mathematical operations.
You want to have type safety
You will not change the data type of the array in the future
You are working with mathematical matrices.
You are working with objects that have no inheritance
More explanation about copy-on-write:
When you pass an array to a function, a pointer/reference is passed.
function foo(x)
disp(x);
end
x= [1 2 3 4 5];
foo(x); %No copy is done here! A pointer is passed.
But when you change it (or a part of it), a copy is created.
function foo(x)
x(4) = x(4) + 1;
end
x= [1 2 3 4 5];
foo(x); %x is being copied! At least twice memory amount is needed.
In a cell array, only the cell is copied.
function foo(x)
x{4} = x{4} + 1;
end
x= {1 2 3 4 5}; %Only x{4} will be copied
Thus, if you call a function that changes a single element on a large array, you are making a lot of copies - that makes it slower. But in a cell array, it is not the case.
Function handles are actually the exception here, and the reason is that the Matlab syntax becomes surprising if you allow function handles to be a part of non-cell array. For example
a = #(x)x+1;
a(2); %This returns 2
But, if arrays of function handles were supported, then
b = [#(x)x+1, #(x)x+2];
b(2); %This would return #(x)x+2
b(3) = #(x)x+3; %This would extend the size of the array
So then would this be allowed?
a(2) = #(x)x+2; %Would this extend the size of the previously scalar array
Longwinded edit: This is documented in the release notes accompanying release R14, which was the first release allowing anonymous functions. Prior to R14 you could create function handles as references to m-file functions, and they could be placed in non-cell arrays. These could only be called using feval (e.g.: fnSin = #sin; output = feval(fnSin, pi)).
When anonymous functions were introduced, the Mathworks updated the syntax to allow a simpler calling convention (e.g. fnSin = #sin; output = fnSin(pi)) which had the effect of causing an ambiguity when using non-cell array of function handles. It looks like they did their best to grandfather this new behavior in, but those grandfathered conditions have certainly expired (this was 2004).
The arrays can store only data with a fixed length. For instance, double, single, char, logical, integer.
The reason is that (I guess) they are stored directly in a block of memory. On the other hand cells are stored as a list of pointers, each pointer can point to a data of different size.
That's why arrays cannot store strings, function handle, arrays, and multiple data types.
Those type can have different length. For instance 'bla' has 3 bytes, 'blabla' has 6 bytes. Therefore if they are stored in the same memory block, if you want to change 'bla' into 'blabla' you would have to shift all the rest of the memory, which would be very slow, and so it's not handled.

Resources