From 0247b30479efb6d346fbcf3a711dfe0bf01aa7b3 Mon Sep 17 00:00:00 2001 From: "Callum R. Renwick" Date: Mon, 1 Feb 2021 11:37:13 +0000 Subject: [PATCH] Add methods --- methods/main.pony | 108 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 methods/main.pony diff --git a/methods/main.pony b/methods/main.pony new file mode 100644 index 0000000..8f70f0a --- /dev/null +++ b/methods/main.pony @@ -0,0 +1,108 @@ +use "collections" + +actor Main + new create(env: Env) => + let list_of_numbers = List[U32].from([1; 2; 3; 4]) + let is_odd = {(n: U32): Bool => (n % 2) == 1} + for odd_number in list_of_numbers.filter(is_odd).values() do + env.out.print(odd_number.string()) + end + +class C + // This function returns the value of the last expression + // in the function (x + y) + fun add(x: U32, y: U32): U32 => + x + y + // This function is pointless; the return value is ignored + // Why? Because *no return type has been specified*. + // We have to specify a return type if we want functions + // to return anything + fun nop() => + add(1, 2) + + // Function notes + // Parameters cannot be assigned to within functions (they are effectively + // declared `let`) + // The whole function body itself is an expression, and the returned value + // is the value of that expression (which happens to be equal to the expression + // in the last line of the function) + // You can exit a function early using `return`; if the function has a return type + // then `return` must return the correct type, otherwise `return` should have no + // argument + +// Constructors +// Pony constructors are different because you can name them, so you can have as many +// as you like +// By convention, the main constructor for each type (if the type *has* a main constructor) +// is called `create` +class Foo + var _x: U32 + + new create() => + _x = 0 + + new from_int(x: U32) => + _x = x + +// You can exit a constructor early by using the `return` command. But keep in mind that +// all the fields on the object must have been assigned to for this to work (the constructor +// must always assign all an object's fields) + +// You can access fields and methods from inside a class like this +class Bar + fun hello(name: String): String => + "hello " + name + + fun f() => + let a = hello("Fred") + +// Constructors are normally called "on a" type, like this +class Baz + fun honk() => + let my_foo: Foo = Foo.create() + let other_foo: Foo = Foo.from_int(12) + +// Constructors can also be called on an expression, like this + fun hank() => + let my_foo: Foo = Foo.create() + let other_foo: Foo = my_foo.from_int(4) + // You can also reuse a variable name from a declaration like this + // (how does this work?) + var another_foo: Foo = another_foo.create() + + +// Functions are always called "on an" object. If the object is omitted then the current +// class is used. + +class Coord + var _x: U32 + var _y: U32 + + new create(x: U32 = 0, y: U32 = 0) => + _x = x + _y = y + +class Doer + fun f() => + var a: Coord = Coord.create(3, 4) + // Notice you can give the arguments *out of order* using + // named arguments with `where` + var b: Coord = Coord.create(where y = 4, x = 3) + // And we can combine named and positional arguments, so long as positional + // arguments are the first ones in the call + var c: Coord = Coord.create(12 where y = 0) + +// Method chaining +// Method chaining allows you to chain calls on an object without requiring the method +// to return its receiver +primitive Printer + fun print_two_strings(out: StdStream, s1: String, s2: String) => + out.>print(s1).>print(s2) + // The above is equivalent to what follows + out.print(s1) + out.print(s2) + out + // The purpose of this "method chaining" is to allow you to + // chain calls on a method but ignore intermediary return values + // You can change the final .> to just . if you want to return the + // value from the final call