Hi, I am still grappling with this problem: Felix has a rule for concrete data types, in particular products. We have quite a few product type: tuples, records, structs, arrays.
Products are characterised by projection functions. Each product type has a different way of naming them. We like for a record type: typedef r_t = (p1:int, p2:int); val r : r_t = (p1=1, p2=2); to express projections like: r.p1 in the OO tradition. Felix says p1 is an ordinary function thingo, and x . f means exactly the same as f x so we can also write: p1 r Consequently you can write this too: 1 (1,2) == 2 because (1,2).1 == 2. Of course 1 isn't a projection but an integer, but Felix translates the application of an integer to a tuple to the application of the corresponding projection. So far so good. Now we also have this notation: p <- v; which means, store the value v into the location p. We require the type of p and v to be &T and T respectively for some T. So now if you have var x : int; you can assigned to x like: x = 1; but this is just sugar: Felix translates it to: &x <- 1; It is important to note here that & is NOT an operator. Rather &x is the real name of the variable, that it, it is the machine address of the associated storage. &x is a name. The syntax x is actually short hand for *(&x) Note we could have made "x" the name of the address, but to make Felix look like C we don't. Nevertheless there is something very important going on here: WE HAVE GOTTEN RID OF THE CONCEPT OF LVALUES [Except in C bindings where we still need them but lets gloss over that :] Now, in C you can write: s.x = 1; where s is of a struct type with a field x. In Felix this would translate to &(s.x) <- 1; which is nonsense!! Remember, & is not an operator. It is just part of the name of a variable. So this would be OK: (&s).x <-1 But how do we make that work? Isn't the "x" here a projection? And don't projections apply to product types? But &s is not of a product type, it's a POINTER to a product. So the solution? Make projections apply to pointers to products as well! In particular, if p: P -> V then P: &P -> &V as well, in other words, if you apply a projection to a pointer to a product you get a pointer to the corresponding field. This in turn makes it possible to store a value into a PART of a product. In particular, this makes a GOLDEN RULE (at least for products): VALUES ARE IMMUTABLE If you want to store into a value, stick it into a variable! VARIABLES HOLD MUTABLE OBJECTS The key thing is ALL product values can be made mutable by simply sticking them into a variable, then using the required chain of projections on the variable's address: var x = (1,2); 1 &x <- 42; Yep. That works! It has to. The projection 1 applied to the tuple object x returns a pointer to the second component which can then be stored into. The symmetry is very nice! THE PROBLEM ============ This all works just great! For concrete data types. That is, one where the compiler knows about the projections. But for an ABSTRACT data type, it doesn't work automatically. Suppose you have an array abstraction A, and some value a and a method: a.get 1; to get the second component. So find we can write: fun apply (p:int, a:A) => a.get p; and NOW we can indeed write a.1 because that means 1 a, and "apply" methods are a way to teach the compiler how to apply non-functions to values. We can even do this: provide a method: (&a).get 1; // returns a POINTER and then an apply function can be used again to allow this: (&a).1 <- 42; But there's a problem! That's not how a varray works. A varray is literally a pointer underneath. So it is intrinsically mutable. Like many mutable data structures, you don't need to store it in a variable to store into its parts. A varray acts like a value AND like an object. There's also a major safety problem. With a concrete data type var x = 1,2; var p = &x.1; we have a pointer interior to the tuple, which can hang about. In this case that's just fine, it cannot dangle, and it can only point into a specific variable. But that's not true for mutable data types. In particular for a varray, a pointer into one cannot dangle, but it certainly can point past the end of the used part of the array (just point to the last element, then pop it off the end with pop_back). It's much worse if the data structure is hiding a C++ one! It is essential to use a pointer to store a value. get/set methods DO NOT WORK. This is an OO stupidity. Assignment isn't the only mutator. Increment is another one. And if you have say, an array then set (a, index, value) looks fine until you consider that the value could be another product which a component that is another product... you then get a complete mess of sets and gets because you have to do a modification to a temporary and store it back (because a get returns a value ..). What works is get/ref: get a value, get a reference. But the reference must be transient (linearly typed, so it must only be used once, and immediately). Note that get/set DOES enforce this (by hiding the store address). So there's the conundrum. In particular in my recent code I had to write: set (a,index,v) even for a varray. The old notation a&.index <- v doesn't work because the &, function is never invoked because now the PARSER translates x*.y ==> (*x).y // which equals *(x.y) x&.y ==> (&x).y to enforce the interpretation above. The problem is i want both a . 1 // second component of varray a a . 1 <- 42; // assign 42 to first component to work, the first because that's how ordinary arrays work and the second because a is really a pointer already so we do NOT want to have to take the address of "a" to store into it. -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ Dive into the World of Parallel Programming The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language