An elegant, EUPHORIA solution
- Posted by "Boehme, Gabriel" <gboehme at MUSICLAND.COM> Feb 04, 1999
- 402 views
One of the complaints from people who want structures in Euphoria is the ugly way we're forced to write our type-check routines. For example, a structure like this in pseudocode... --structure my_structure -- integer NUMBER -- string NAME -- user_defined_type WHO_KNOWS_WHAT --end structure ..must be type-defined like this... constant NUMBER = 1, NAME = 2, WHO_KNOWS_WHAT = 3 type my_structure(sequence x) if length(x) != 3 then return 0 elsif not integer(x[NUMBER]) then return 0 elsif not string(x[NAME]) then return 0 elsif not user_defined_type(x[WHO_KNOWS_WHAT]) then return 0 end if return 1 end type ..and if we want to type-check a sequence of these values, we always have to write a "for" loop each time: type list_of_my_structure(sequence x) for z = 1 to length(x) do if not my_structure(x[z]) then return 0 end if end for return 1 end type As you can see, this is hardly an "elegant" way of doing things. The problem with the constants is more of a namespace issue, though -- the PRIMARY objection I'm focusing on is the inelegant, *ugly* code we're forced to write to type-check everything. To solve this, I propose the following library: -- struct.e -- written by Gabriel Boehme -- free for anybody and everybody to use global function type_structure(sequence types, sequence data) -- this function verifies that each element of a sequence is of the correct type if length(types) != length(data) then -- data is the wrong length for this structure return 0 else for z = 1 to length(data) do if not call_func(types[z], {data[z]}) then -- the called type-check function failed return 0 end if end for end if -- everything fits! return 1 end function global function type_all(integer id, sequence x) -- this function verifies that every element of a sequence is of the same type for z = 1 to length(x) do if not call_func(id, {x[z]}) then -- type-check failed return 0 end if end for -- they're all right! return 1 end function -- end of struct.e Now, all we have to do now is define our "structure" like this: constant MY_STRUCTURE = {routine_id("integer"), routine_id("string"), routine_id("user_defined_type")} type my_structure(sequence x) return type_structure(MY_STRUCTURE, x) end type constant NUMBER = 1, NAME = 2, WHO_KNOWS_WHAT = 3 You see? Euphoria is more than capable of handling these things in an "elegant" way. Yes, we still have to define constants for sequence index values, and yes, this *is* a pain, but we have now eliminated the need for big, ugly type-check functions. This also applies to sequences of "structures", too: constant LIST_OF_MY_STRUCTURE = routine_id("my_structure") type list_of_my_structure(sequence x) return type_all(LIST_OF_MY_STRUCTURE, x) end type Of course, having to define all these extra constants goes back once again to the namespace issue. But never mind that for now, look at how much more elegant this is than the type of code I had to write at the beginning of this post! And we don't even have to introduce any new structure syntax to do it. Gabriel Boehme P.S. I got the inspiration for this idea from Michael Sabal, so he deserves a share of the credit. Many thanks, Michael!