On 11/26/2010 7:49, Ralph Versteegen wrote:
On 26 November 2010 23:59, 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?

I forgot to mention? Yeah, always dynamic.

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.)

BYREF BYREF BYREF

Well, *expletive*. I guess I've been using other languages too long.

Don't worry, there's preprocessor trickery involved. However there's
less than required for extending FB arrays. Also, I am aware that my
attempts at inheritance, hash tables, and lists using macros turned
into a disgusting mess; I promise I won't do that again. In fact I am
thinking about porting lumpfile.bas to C++ so that I can get rid of
the macros and custom polymorphic class system.

Fun fact! C++ 1.0 was nothing more than a glorified set of macros!

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.

Yes I agree, if we had classes I would be using them. It won't be much
work to switch to classes when we get the chance to. However, it will
never be possible to switch the extended FB arrays library to classes,
which is another reason to use our own array type.

Also, I'll note I'm building in support for types with constructors,
copy constructors, compare operators, etc now, and will provide a
-lang fb test suite.

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()

Umm is this VB code?

I am 99.999% certain that no compiler would accept this snippet as valid. That's the MikeBASIC(TM) guarantee!

        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:

I thought that you could overload operator() or operator[], but I
don't see it right now. I know very little about -lang fb stuff.

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

GetArray is far too verbose for me, which is why I suggested direct
access to a pointer. I'd rather go with extended FB arrays than have
to type that.

Yeah, me too. Just being complete.

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

The whole point is that FB provides no useful functions acting on
arrays whatsoever, so I want to write a library. Otherwise I will
either go insane, or quit OHRRPGCE work and blissfully write Python
code for the rest of my life.

The only real counter argument is that it's already been written and named the standard c library.

_______________________________________________
Ohrrpgce mailing list
[email protected]
http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org

Reply via email to