Last call for new features
- Posted by Ralf Nieuwenhuijsen <nieuwen at XS4ALL.NL> Jan 14, 1999
- 431 views
This is my last attempt to convience Robert and the rest of the Euphorians, we need some new features, will any big program be ever _easily_ possible with Euphoria. The order is not of importance, rather of implementation: (though I did number them from 1 to 10) 1) Direct initialization. Simple: integer x = 5, y = 6 2) Arrays. Why? We have sequences. Yes, I know, but sometimes I want to be able to have a sequence of fixed-length. type char (integer x) return x >= 0 and x <= 255 end type char text[20] -- Allocate room for 20 characters Speed benefits: graphics in native Euphoria will now match up with things like mem_copy () and mem_set (). The dynamic allocation and deallocation is great, but when I dont need then, they slow everything down with every slice. Example: image[y][x] First it checks the boundries for y, then it looks up the pointer it points to. Then it checks the boundries for x, then it looks up the value that points to. That value is returned. Now the same with arrays. One multiplication, one boundry check, one value looked up. With hard-typed constants or values, the speed benefit is even more. For example: image[102][203] It can then, during pre-proccesing, lookup the exact memory address and check the boundry. It would be as fast as a normal variable. And it off course increases readability, stability, and it saves us a lot of time. Compare these two: -- Currently with Euphoria you need to do: constant TRUE = 1, FALSE = 0 type char (integer x) return x <= 0 and x >= 255 end type type text (sequence s) if length(s) != 20 then return FALSE end if for index = 1 to 20 do if not char(s[index]) then return FALSE end if end for return TRUE end type text name name = repeat (' ', 20) -- I want to be able to do: type char (integer x) return x <= 0 and x >= 255 end type char name[20] = repeat (' ',20) 3) Structures, though no special tricks, just the plain simple and readable: -- Example of how I would like to see structures implemented structure person do char name[] = "" integer age = -1 end structure Now, I will explain a few things of what you see. First of all, char name[]. It looks like an array, and it is. But its a non-fixed length array. (a sequence thus, every says, irritated: yes, true, a sequence, however still a fixed number of dimensions and one generic type associated to each *element* of the sequence. Secondly, you must have noticed that I initialize all elements of the structures. This is because its a pain, to initialize a structure yourself. This is thus the default initialization. However to use the structure, you must first use it as if it was a type: (actually, it is) person client client[name] = "Ralf Nieuwenhuijsen" client[age] = 16 Again, like with arrays, structures have the advantage they speed things up alot. They are more readable. Prevent half of all the scope problems and enable an easy way to have seperate type-checking-functions for several elements of a sequence. 4) Length should be assumed when its not used in an slice operation. Example: image[4][10..] -- Should read as: image[4][10..length(image[4])] This also prevents many issues, that arise when you would introduce this slicing syntax: image[10..][10..] Crops the image from (10,10) to (end, end) 5) We should be able to assign an sequence to a sequence: {x, y, c} = cursor () Even, the & operator should be supported: {{x,y}} & text = get_text_and_location () This enables much faster proccesing. Its much more readable. And prevents the need for extra variables, and thus prevents scope issues. 6) The scope rules. First of all, there is no person on this planet who started with Euphoria and realized/knew that indirectly half the world included, when you use include. If I used include, only those global identifers in that include files should be available to me. When I include graphics.e but not machine.e, the global routines, constants and variables of machine.e should not be available to me. Overriding of any identifer not defined in my the same include file should only produce a warning. Thus overriding of constants, variables and of routines. When two files include each other, all global indentifers of both files should be available to both files. Mutal recursion between two routines from seperate include files should thus be natively possible, without using routine pointers thus. 7) Euphoria can be faster. Esspecially IO is not as fast as it can be. A simple built-in function like "read_textfile ()" (vs read_bitmap) would be very clean, and fast. Secondly, all input and output that Euphoria does, is better off handeling natively with atoms, than using standard watcom routines, and give them converted data. A puts () should have no need to convert its datatype. A gets () as well. How to achieve that ? By using less watcom routines and more euphoria libraries. I mean, many 'built-in' things could just as easily have been Euphoria files. An great example is the dir95, that is actually better than the one stored in one of the watcom libraries linked with the interpreter. In other cases, just avoiding translation of atoms into bytes can be an huge speed gain. I esspecially mean file IO in this light. Built-in (read: fast) support for ports, wouldnt hurt any one either. Wait retrace is for example a full machine code piece, because using the 'constructed' ports routines were just too slow. Another reason to avoid watcom routines are errors. Things like puts (1, "Hello" & 0 " & " you there") where " you there" is not displayed, since a zero is used to indicate an end-of-line in C. 8) Rather than short-cirquiting, I would like to see smart support for lazy routines. Whenever a function does not *set* any local variable (variables declared in the space of the include file), it should be marked as 'lazy'. Which means, that, when that function is called, rather than actually executing the code, a pointer to the code is stored, until the value is really needed. Example: proceduer display_text (sequence text, boolean should_i) if should_i then for index = 1 to length(text) do puts (1, text & '\n') end for end if end procedure display_text (read_textfile ("readme.txt"), FALSE) It doesnt even attempt to open "readme.txt" since the return value of the function read_textfile is assigned to 'text' in the procedure "display_text". However, during run-time the value is not 'looked'-up. If I say: display_text (read_textfile ("readme.txt), TRUE) Just before the first puts () statement in "display_text", the function read_textfile () is called and the file is opened. This could be done for Euphoria routines, but also for the built-in routines, like find () and operational and math operators. We do not need to perform a multiplication, when there result will be never used anyway. However, this nifty lazy routine system, does not have to complicate anything for the programmer. The interpreter can determine by itself, when a function can be safely marked as 'lazy'. All functions that do not *modify* external variables(variables declared outside of the scope of the function) can be marked 'lazy' without any possible problem or conflict. Off course it may not call non-lazy function as well. Those functions that do call non-lazy routines are non-lazy themselves. But if it is supported, why not, give the programmer the freedom ? Yes, it should be able. But only for those interested in the issues that it may give you (and the power). Just a special keyword can force either mode: lazy function blabla () -- only called when value is read -- you can now keep track of the amount of times, the return value of this function is actually used. end function .. and .. strict function blabla () -- immidiately called -- we might not use any external variables, but we do a windows call for a message (for example), so we want it to be executed immidiately. end function With all other functions, the interpreter can determine wether or not it is safe or not. The speed gain will be great for certain programs. 9) Bind and shroud should have NO issue whatsoever. Even at the cost of run-time speed, may they never ever have any issue. 99% of all programs that people sell, give and/or spread is binded. The whole point of programming is making a program. There should be no issue whatsoever. 10) Whenever *possible* routines should be platform-generic. I mean: mouse-routines, graphics, message-boxes, etc. can have a counterpart on the other platform.... and there _should_ be one. Thats all I can come up with. I would love to see more ideas of other users. So please respond, or post your ideas. (maybe enumeration.. although Im not sure how I would like to see it implemented). And Robert, of all of the above points, as I know some (like structures) are supported by many, could you explain the direction you want Euphoria to take, and why we can or can not expect the above changes to actually happen ? Also, what will the new version offer ? And can we pre-register, when you release the alpha version ? My excues for any language error in the above. Im not a native English spoken person, however do appriciate comments. Ralf Nieuwenhuijsen nieuwen at xs4all.nl ralf_n at email.com