I have change the compiler so arrays are now accessed directly by the compiler when given the correct index type, but only for unitsums. For example:
///////////// var a: int ^ 3 = (1,2,3); println$ (case 1 of 3) a; var k = case 1 of 3; println$ k a; //////////// now works and is implemented directly in the compiler. This doesn't break any code because all current access is being hacked with integers via a C binding in the library. We have safe and unsafe get methods there. Indexing with the proper index type is always safe and doesn't require any checks. The library should be changed to *coerce* an integer argument to the correct type, eliminating the need for array bounds checks. Instead, the coercion is checked. The advantage of this is that, for example, parallel access of two arrays with the same index requires only a single check converting an integer to a unitsum, instead of two for the two arrays. Some subsequent fiddling can ensure loops, iterators, etc, are safe by generating indicies of the correct type instead of hacking it with integers and then using unsafe get because "we know" the integers are in bounds by design. The purpose of all this, however, is not to improve performance although that will be one nice side-effect: the purpose is to allow multi-dimensional arrays. We already have arrays of arrays, but these are indexed in two steps: a . i . j If you map some function f over a, f has to accept an argument of the type of one of the inner arrays, so if you want to map over the matrix of values you need to make f itself a map of some value translator g. On the other hand a map over a two dimensional array can use g directly: a two dimensional array is a linear array with indices of tuple type so the access is like: a . (i,j) instead. Now, you may think this is trivial and merely fun notation. WRONG! [You knew that was coming!!] Consider an array with index type J where J is a type variable. We do not know if it is a one, two, three or four dimensional array BUT WE CAN STILL MAP OVER IT. And fold of course. This is called array polyadic programming. It means you can write code which works for arrays of ANY rank. You can test the code on a simple 2 dimensional case, eg heat transfer in a plate, and then use the code in a 3 dimensional case, eg heat transfer in a block, knowing you've tested the code. And without having to write the code out again with extra loops for the higher rank. [And I'm going to bet this has some major uses in finance too :] The way to do this was first developed by Barry Jay in his language FISh. Jay went on to generalise to all polynomial data functors (things made of sums and products), and thence to develop the pattern calculus. The additional functionality from the array polyadic behaviour comes from strictly observing the underlying categorical structure of the types. Which means we need to look at a couple of places where Felix glosses over some isomorphisms it probably shouldn't. One is the reinterpretation T * T -> T^2 which is seen in: var x = 1,2; // type is int * int = int^2 Actually the types aren't equal, just isomorphic. Similarly we trick around believing T ^ 1 -> T and I have no idea if Felix gets this one right at all: T ^ 0 -> 1 Then there's the other side of arrays. You can regularly index a tuple and return a uniform type: var x = (1, "hello") . case 1 of 2; You may think x has type string. And if we use case 0 it would be an int. That's why the index has to be a constant. Right? That's what happens now except we use an integer constant instead of a case. If we go to a case we should get the type right! The correct type of x, that works for ANY index is: int + string this is the dual of the tuple type. We have (1, "hello") . (case 1 of 2) = (case 1 of (int + string)) "hello" in other words a sum constructor an argument. Note carefully the term not only contains the string as an argument .. it also RETAINS THE INDEX VALUE. Why is this important? Because for arrays the result of indexing should be the same: case 2 of 20 (42) for the third value in an integer array (which happens to be worth 42). We currently just return 42 when the index is an integer. So not only is the index "hacked" by using the wrong type, the result has the wrong type too. We're secretly applying another function to get rid of the index and switch the type to the common argument type (namely int in this case). All these things can be justified. That doesn't mean the compiler should gloss over them, it means we should correctly define the "glossing over" bits. For example we have a term in the compiler "case_arg" which fetches the argument of a sum or union constructor. -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language