About two ours to get this: /////////////////////////////////////////////////////////////// // An OO experiment
interface AA { setx: int -> void; sety: int -> void; getx:1 -> int; gety:1 -> int; sum: 1 -> int; } // omethod temporarily to avoid conflict with http_request // which happens to use a field named "method" object makeX (var x:int, var y:int) implements AA = { omethod proc setx(a:int) { x = a; } omethod proc sety(a:int) { x = a; } fun getxx => x; omethod fun getx() => x; omethod fun gety () => y; omethod fun sum () => x + y; } var anX = makeX (23, 42); println$ anX.getx(); /////////////////////////////////////////////////////// We use "object" instead of "class" because class is already used for Haskell style typeclasses. Also this suggests that Felix objects are very much more flexible than Java ones. Could change to just "obj" in keeping with shorter names in Felix. We use "omethod" instead of "method" because accidentally, Mike has a field "method" in a struct in http_request. Could change this to "meth" although that sounds like a cheap drunk or crack addict. How it works: interface is a synonym for typedef of a record. It's that simple. object is slightly tricker. It's just a function which returns a record of all the functions and procedures (ONLY) inside it marked "omethod", with the same names. Duplication of names isn't allowed. Obviously the functions cannot be polymorphic, however the record and object can be.**** POWER ===== Felix objects as implemented by object syntax are much more powerful than Java ones. For a start, every such function is a closure over the object representation, which is the context of the method definitions: the function body AND its context. Like any other function. Although records are immutable you can make them any way you like. Remember, "object" is just sugar for a function that makes a record. You can always write any kind of factory function you like. Although it looks like Java .. the power is much closer to Python. [For inheritance it will turn out the objects are more prototype based I suspect .. we'll see] I will not in passing a *dynamic* version of this using JudySL array which maps a string name to an object could be quite interesting :) [Getting the types right is the tricky bit: dynamic typing. But quite possible using our RTTI I guess, not sure: we could also use C++ dynamic_cast provided all the objects were derived from some base "object" type] TODO ==== Obviously we want "extends" in interfaces. This will be a fairly minor patch. The rule will be: from left to right, then in the body of the extension, collect fields into a set. Later fields replace earlier ones if they have the same name. We could also make an error if there were a conflict in the bases, unless resolved in the extension, or consider also some consistency in the types of the fields with the same name. The patch isn't entirely trivial, because of polymorphism: interface A[T] { .. } interface B[U,V] extends A[U * V] { ... The specialisation has to be resolved at binding time, as well as the lookup. Of course you must note again, the binding stuff knows nothing about objects or interfaces. So the actual technology will apply to records in general. I will also note: exactly the same idea could be applied to structs. After all they're just a set of fields like a record, with a name thrown in. [Actually .. Felix record type internally has provision for a name to enhance the structural typing to include an "extra" identifier] Similarly unions could be extended for the same reason, and that includes enums. *** Existential types *** We need to understand "universal quantification and existential quantification", for all and exists, in respect of types. In a function: fun f[T] (x:T) = { var a : T = x; return a; } FROM THE OUTSIDE the function is universally quantified by type variable T. FROM THE INSIDE the function is existentially quantified. This means that inside the function, T is NOT a type variable. It's an unknown type constant. It can't vary. It's exactly as if there were a typedef to something we didn't know. So the variable 'a' in the function is not polymorphic, it's monomorphic. It could be "int" or "long" we don't know, its "some particular type". This means for a record type: typedef X[T] = (f:T->T); that X is polymorphic. However f is not. If we had: (f: T. T->T) then the field f would be polymorphic. Ocaml can do this in a record. Felix can't. It's saying f is a polymorphic function. -- 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