"GLOBAL ARRAYS... start with a caret symbol. Stored on disk, available
to all processes"

"You see, because MUMPS has a rather small routine limit, developers
had to spread code across several routines... and “chain” them
together with a GOTO at the end."


This is now my favorite programming language ever.
-->Seth



On Fri, Nov 26, 2010 at 6:59 PM, Mike Caron <[email protected]> wrote:
> On 11/26/2010 5:34, Ralph Versteegen wrote:
>>
>> QB/FB arrays are the worst designed feature in any programming
>> language I know of (except for *possibly* some of the stuff in MUMPS
>> http://thedailywtf.com/Articles/A_Case_of_the_MUMPS.aspx)
>> (A quick rant:
>> -not 1st class: you can't return them or even place them in types!
>> -uninitialised dynamic arrays are indistinguishable and will crash
>> your program. You must initialise them.
>> -to figure out whether an array is static or dynamic you have to check
>> the dialect, the OPTION statements in effect, and whether the index in
>> the DIM statement is a variable or a constant
>> -unlike the rest of the language, arrays aren't properly statically
>> typed: the compiler will let you REDIM a static array and crash your
>> program
>> -zero-length arrays not supported
>> -almost zero support for arrays in the standard library: just REDIM,
>> LBOUND, UBOUND, ERASE. You can't even copy an array, or get a pointer
>> to the array descriptor.
>> )
>> A couple days ago I had finally had enough, and started on a library
>> of array utility functions written in C, effectively extending libfb
>> (addressing just the last 2 complaints above). The idea is they act on
>> 1D arrays starting at -1, with the -1 element ignored so we can have
>> zero-length arrays. Here are a few prototypes (you use a macro to
>> declare overloaded versions for each type T you want to support):
>>
>>   declare sub array_copy overload (array() as T, source() as T)
>>   'Append an element or an array
>>   declare sub array_append overload (array() as T, value as T)
>>   declare sub array_append overload (array() as T, appendlist() as T)
>>   'Removes index n from array
>>   declare sub array_delete overload (array() as T, byval n as integer)
>>   'Insert a value/array at an index. Negative indices count from end
>> (-1 appends)
>>   declare sub array_insert overload (array() as T, byval insertbefore
>> as integer, value as T)
>>   declare sub array_insert overload (array() as T, byval insertbefore
>> as integer, insertlist() as T)
>>   declare sub array_sort overload (array() as T)
>>
>> A couple nights into implementing them (expected to be done by now,
>> but the libfb array code is horribly over-complex, eg. there are about
>> 8 different implementations of REDIM) I suddenly realised: if FB
>> arrays are so horrible, why am I using them at all? It would be FAR
>> easier to create a new array structure and write an extensive library
>> for it in C. The code would be much simple, faster, there'd be no
>> worry about keeping up with changes to libfb, and I can fix more of
>> the problems with FB arrays. The disadvantages would be having to
>> manually allocate and free them, and no bounds checking when compiled
>> with -exx. However when we finally switch to -lang fb we'll get those
>> back.
>>
>> I would implement these arrays like this: array objects would just be
>> pointers of the desired type, which can be indexed like a normal
>> pointer. The array descriptor (containing length and other stuff)
>> would be stored before the 0th element. These pointers can of course
>> be embedded in UDTs or returned from functions. Because code should be
>> self documenting, to avoid confusion with normal pointers I'd do this:
>> #define array ptr
>> Example code:
>>
>> FUNCTION generate_test_array() as string array
>>   DIM arr as string array
>>   array_new arr    ' allocate zero-length array
>>   array_append arr, "test"
>>   array_append arr, array_of("foo", "bar")   ' I think I'll manage this
>>   array_sort arr
>>   RETURN arr
>> END FUNCTION
>>
>> DIM arr as string array
>> arr = generate_test_array  ' Can only do this as arr is a NULL pointer
>> array_set arr, generate_test_array  ' Safe way to assign an array
>> print arr[length(arr) - 1]
>> array_free arr
>>
>> So the question to the other developers is: would you rather have a
>> library for FB arrays, or use these new arrays? I am definitely in
>> favour of the new arrays, and would start using them and, where
>> beneficial, converting code I'm working on to use them as soon as
>> possible (tomorrow?).
>
> I'm curious about one thing. Would these new arrays be dynamic or statically
> sized? I assume the former. In which case, you do you handle the
> realloc()/Reallocate() semantics?
>
> Specifically, when you use realloc(), you have to use the return value as
> the new pointer (if it's not null), since the memory block may have moved to
> accommodate the new size.
>
> However, the syntax you're proposing does not allow for the re-assignment of
> the variable containing the array. (Unless you intend for some preprocessor
> trickery, in which case foo on you.)
>
> The best way to replace FB's arrays would be to create an array object which
> overloads the [] operator, and keeps the memory buffer internal. Ideally, it
> supports templates for maximum efficiency.
>
> Class Array<T>
>    length as uinteger
>    data as T ptr
>    Public Constructor Array(size as uinteger)
>        length = size
>        data = new T[size]
>    End Constructor
>
>    Public Operator[](index as uinteger) as T ref
>        if index < 0 or index >= length throw new ArgumentException()
>
>        return &data[index]
>    End Operator
>
>    public sub Resize(newsize as uinteger)
>        ...
>    end sub
> End Class
>
> However, since I don't think this possible in FB (and, especially not in
> -lang deprecated), you would have to settle for a C-style api:
>
> TYPE IntArrayUDT
>    length as uinteger
>    data as integer ptr
> End Type
>
> TYPE IntArray as IntArrayUDT ptr
>
> Function NewIntArray(size as uinteger) as IntArray
> Sub DeleteArray(a as IntArray)
> Function ResizeArray(a as IntArray, newsize as IntArray) as integer 'boolean
> Function GetArray(a as IntArray, index as uinteger) as integer
> Sub SetArray(a as IntArray, index as uinteger, value as integer)
> 'etc.
>
> Also, I would be very tempted to use some evil preprocessor trickery to
> simulate templates, since this is very silly.
>
> Or, the final option would just to use regular pointers as arrays. It's
> worked for almost 40 years so far :D
> _______________________________________________
> Ohrrpgce mailing list
> [email protected]
> http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org
>
_______________________________________________
Ohrrpgce mailing list
[email protected]
http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org

Reply via email to