0 Members and 3 Guests are viewing this topic.
interface Printer { Print(); }struct Foo { []Printer data; }
interface Printer { Print(); }struct Foo<T:Printer> { []T data; }
Foo<int> list; // list may only work with ints (and stores an int.Print pointer)Foo<Bar> list2; // list2 only works with Bars (stores a single Bar.Print pointer)
interface Printer { Print(); }struct Foo<Printer> { []Printer data; }
If it's my understanding, then "struct Foo<T:Printer> { []T data; }" and "struct Foo<Printer> { []Printer data; }" are basically the same. ... Not every Print() method would be the same for every Printer.
interface Printer { Print(); }// Using "mixed" Printers ("<>" is unnecessary)struct Mixed { []Printer data; }Mixed m = {{someBar, someCar, someDar}};//m is: {{Printer{someBar,Bar.Print}, Printer{someCar,Car.Print}, Printer{someDar,Dar.Print}}}m.data[i].Print(); // Calls the "Print" of data[i] on the Printer-object of data[i]// Using only same-typed Printers:struct Same<T:Printer> { []T data; }Same<Bar> s = {{bar1, bar2, bar3}};// s is: {{bar1,bar2,bar3}, Bar.Print}s.data[i].Print(); // Calls the single embedded Bar.Print on data[i]
1) you could just make Printer an abstract class with a default method2) Also, are you sure Foo and Foo<T> would have the same methods?3) Foo<T>'s type would probably be something like IEnumerable<T>.
struct abstract { int x, y; meth := func(this, int a, int b) { x=a; y=b; };}a1 = abstract{1, 2}; // uses defualt methoda2 = abstract{1, 2, someOtherMethod};
struct Foo<T> { *T value; } // always the same sizefunc Foo<T>.Bar<T>() { ... } // always the same everythingfunc Foo<int>.Bar() { ... } // THIS one is specific to ints.c := Foo<char>{'5'};b := Foo<bool>{true};i := Foo<int>{123};c.Bar(); // inferred as c.Bar<char>, or Foo<T>.Bar<T> where T = charb.Bar(); // inferred as b.Bar<bool>, or Foo<T>.Bar<T> where T = booli.Bar(); // inferred as i.Bar<int>, or the separate Foo<int>.Bar// --- Another just to clarify: ---func A<T>(T arg) { ... } // Different per type-size (and per differing operations on T)func B<T>(*T arg) { ... } // Same per type, so long as nothing type-specific happens
struct Tree<T> { T value; *Tree<T> left, right; }cofunc Tree<T>.InOrder<T>():T { if(left != null) for(int i : new left.InOrder{}) { yield i; } yield value; if(right != null) for(int i : new right.InOrder{}) { yield i; }}Tree<int> tree; // Tree of int values...for(int i : tree.InOrder{}) { Print(i); }
struct Tree<T> { T value; *Tree<T> left, right; }func Tree<T>.InOrder<T>(func(T) process) { if(left != null) { left.InOrder(process); } process(value); if(right != null) { right.InOrder(process); }}Tree<int> tree;...tree.InOrder(Print);// Or: tree.InOrder(i => somethingElse(i));
// Old setup:struct Counter { int n; cofunc( ):int { n++; return n; } }c := Counter{5};c(); c(); c(); // 6, 7, 8// New setup:cofunc Counter { int n; } ( ):int { n++; return n; }c := Counter{5};c(); c(); c(); // 6, 7, 8
struct Link<T> { T value; *Link<T> next = null; }struct List<T> { *Link<T> head = null, tail = null; length = 0; }func Tree<T>.Size<T>():int { return length; }func Tree<T>.add<T>(T val) { l := new Link<T>{val}; if(head == null) { head = tail = l; } else { tail = tail.next = l; } length++;}List<int> list; // an int listlist.add(1); ist.add(1); ist.add(3);
List<int> list;cofunc List<T>.Iterator<T>():*T { for(l := head; l != null; l = l.next) yield l.value;}func List<T>.Each<T>(func(*T) process) { for(l := head; l != null; l = l.next) process(l.value);}// Cofunc iteration (uses two loops!)for(int i: list.Iterator{}) { ...do stuff with i... }// Func-pointer iteration (much more efficient)list.Each(i => {...do stuff with i...});
- No more embedding of funcs or cofuncs within structs or cofuncs (enforces clarity)
struct Foo { ... }func Foo::Bar() : byte { ... }
Does this mean we have to use C++ style method declaration? I.e. struct Foo { ... } func Foo::Bar() : byte { ... }
struct Foo { ... } func Foo::Bar() : byte { ... }
struct Foo { func(*Foo,...) fp; // embedded function pointer func(this,...) mp; // just like fp, but counts as a "method"}func f(*Foo,...) { ... } // function (not embedded in Foo)func Foo.m(...) { ... } // method (same as f, but is a method)Foo foo, foo2;foo.fp(foo,...); // foo EXPLICITLY passed as 1st argfoo.fp(foo2,...); // same deal (can pass ANY Foo)foo.mp(...); // "method" = foo IMPLICITLY passed as 1st arg ("this")f(foo,...); // same deal as fp, but not a func-pointerfoo.m(...); // same deal as mp, but not a func-pointer// They all STORED as func(*Foo,...) though;// and since fp and mp are pointers, you can do this:foo.fp = foo.mp = f; foo.fp = foo.mp = m;
Cool. I like the preprocessor directives especially since I'm starting to understand their usefulness (remember, I have mostly confined myself to C# where they are largely unnecessary). Do you plan to add #pragma, or would that not be needed?
PSUEDO-JAVA/C# | | ANTELOPE (new syntax) | | ANTELOPE (old syntax) ========================================================================class Fooer { | | struct Fooer { | | ... void Foo() { <1> func Foo() { <1> func(this) Foo = func(this) { Print("Foo "); | | Print("Foo"); | | ... } | | } | | } } | | } | | ... | | | | ... class FooID : Fooer { <2> struct FooID { <2> ... int id; | | int id; | | ... | | | | ... <3> Fooer { <3> Fooer = Fooer { void Foo() { <4> func Foo() { <4> func(this) { Print("Foo "); | | Print("Foo "); | | ... Print(id); | | Print(id); | | ... } | | } | | } | | } | | } } | | } | | ...
PSUEDO-JAVA/C# | | ANTELOPE (new syntax) | | ANTELOPE (old syntax) ======================================================================Fooer foo = Fooer(); <5> Fooer foo = Fooer{}; <5> ... FooID fid = FooID(5); | | FooID fid = FooID{5}; | | ... | | | | ... Fooer moo = Fooer() { <6> Fooer moo = Fooer { <6> ... void Foo() { | | func Foo() { | | func(*Fooer f) { super.Foo(); | | Fooer.Foo(this); | | Fooer.Foo(f); Print(" Moo!"); | | Print(" Moo!"); | | ... } | | } | | } } | | } | | ...
PSUEDO-JAVA/C# | | ANTELOPE (nothing new here) =============================================================void FooFooer(Foo f) { <7> func FooFooer(*Foo f) { f.Foo(); | | f.Foo(); } | | } | | FooFooer(foo); // "Foo" <8> FooFooer(foo); // "Foo" FooFooer(fid); // "Foo 5" | | FooFooer(fid); // "Foo 5" FooFooer(moo); // "Foo Moo!" | | FooFooer(moo); // "Foo Moo!"
trait Wargler { Foo(int); Bar():int; Wargle() { Foo(Bar()); } Talk() { Print("Wargle!"); }}trait Fargler { Boo(); Bar() = Moo(5); // { return Moo(5); } Fargle() { Moo(Bar()); } Talk() { Print("Fargle!"); }}struct A : Wargler { ... }struct B : Fargler { ... }struct C : Wargler, Fargler { ... }
func A.Foo(int) { ... }func A.Bar():int { ... }func B.Boo() { ... }func C.Foo(int) { ... }func C.Bar():int { ... }func C.Boo() { ... }func C.Talk() { ... } // Overlaps both traits
func A.Wargle() { Foo(Bar()); } // func Wargle(A* a) { A.Foo(a, A.Bar(a)); }func C.Wargle() { Foo(Bar()); } // ...etc...func B.Fargle() { Moo(Bar()); }func C.Fargle() { Moo(Bar()); }func A.Talk() { Print("Wargle!"); }func B.Talk() { Print("Fargle!"); }
func Warg(Wargler w) { w.Wargle(); }func Farg(Fargler f) { f.Fargle(); }(a,b,c) := (A{...}, B{...}, C{...});Warg(a); // wa := Wargler{a}; Warg(wa);Farg(b); // ...etc...Warg(c);Farg(c);