UFCS
Cosmo interprets dots in restricted UFCS style. UFCS is a feature that allows you to call a method on a type that is not defined as method of the type.
class Cat { def meow1() {} def meow2(self) {} def meow3(this: Cat) {}}def meow4(cat: Cat) {}def main() = { // Legal call in Cosmo Cat.meow1() Cat().meow1() // error, require an instance: Cat.meow2() Cat().meow2() Cat.meow2(Cat()) // error, require an instance: Cat.meow3() Cat().meow3() Cat.meow3(Cat()) // error, not in namespace of the class: Cat().meow4() meow4(Cat())}
class Cat { def meow1() {} def meow2(self) {} def meow3(this: Cat) {}}def meow4(cat: Cat) {}def main() = { // Legal call in Cosmo Cat.meow1() Cat().meow1() // error, require an instance: Cat.meow2() Cat().meow2() Cat.meow2(Cat()) // error, require an instance: Cat.meow3() Cat().meow3() Cat.meow3(Cat()) // error, not in namespace of the class: Cat().meow4() meow4(Cat())}
struct Cat { static void meow1() {} void meow2() const {} static void meow3(Cat this) {}}void meow4(Cat cat) {}int main() { Cat::meow1(); Cat::meow1(); Cat().meow2(); Cat().meow2(); Cat::meow3(Cat()); Cat::meow3(Cat()); meow4(Cat());}
struct Cat { static void meow1() {} void meow2() const {} static void meow3(Cat this) {}}void meow4(Cat cat) {}int main() { Cat::meow1(); Cat::meow1(); Cat().meow2(); Cat().meow2(); Cat::meow3(Cat()); Cat::meow3(Cat()); meow4(Cat());}
For meow1meow1, both Cat.meow1()Cat.meow1() and Cat().meow1()Cat().meow1() are legal. They will be translated to Cat::meow1()Cat::meow1() in C++.
For meow2meow2 and meow3meow3, both Cat().meow2()Cat().meow2() and Cat.meow2(Cat())Cat.meow2(Cat()) are legal. They will be translated to Cat().meow2()Cat().meow2() or Cat::meow3(Cat())Cat::meow3(Cat()) in C++.
Note for meow4meow4, it is a function outside the class. It is not legal to call Cat().meow4()Cat().meow4() in Cosmo. This is because we forbid Function Overloading in Cosmo. Therefore, we have to call meow4(Cat())meow4(Cat()) in Cosmo.
The only difference between meow2meow2 and meow3meow3 is the translated C++ code. In C++, meow2meow2 (self) is translated as member function in best efforts, while meow3meow3 is translated as static function.
Note, you can also annotate type on selfself:
class Cat { def meow5(self: Ref(Self)) {} def meow6(self: RefMut(Self)) {} def meow7(self: Self) {} def meow8(self: Box(Self)) {}}
class Cat { def meow5(self: Ref(Self)) {} def meow6(self: RefMut(Self)) {} def meow7(self: Self) {} def meow8(self: Box(Self)) {}}
struct Cat { void meow5() const {} void meow6() {} static void meow7(Cat self) {} static void meow8(std::unique_ptr<Cat> self) {}}
struct Cat { void meow5() const {} void meow6() {} static void meow7(Cat self) {} static void meow8(std::unique_ptr<Cat> self) {}}
It is still unclear on how to simplify following methods:
class Cat { def meow5(self: Ref(Self)) {} def meow6(self: RefMut(Self)) {} def meow7(self: Self) {}}
class Cat { def meow5(self: Ref(Self)) {} def meow6(self: RefMut(Self)) {} def meow7(self: Self) {}}
In Rust, they are:
impl Cat { fn meow5(&self) {} fn meow6(&mut self) {} fn meow7(self) {}}
impl Cat { fn meow5(&self) {} fn meow6(&mut self) {} fn meow7(self) {}}