diff --git a/code-samples/aliasing-iso-to-tag.pony b/code-samples/aliasing-iso-to-tag.pony index c7202e93..45ffb9a3 100644 --- a/code-samples/aliasing-iso-to-tag.pony +++ b/code-samples/aliasing-iso-to-tag.pony @@ -1,2 +1,8 @@ -fun test(a: Wombat iso) => - var b: Wombat tag = a // Allowed! \ No newline at end of file +actor Main + new create(env: Env) => + test(Wombat) + + fun test(a: Wombat iso) => + var b: Wombat tag = a // Allowed! + +class Wombat \ No newline at end of file diff --git a/code-samples/aliasing-multiple-references-to-an-iso-object.pony b/code-samples/aliasing-multiple-references-to-an-iso-object.pony index 8acb51c5..d076a8de 100644 --- a/code-samples/aliasing-multiple-references-to-an-iso-object.pony +++ b/code-samples/aliasing-multiple-references-to-an-iso-object.pony @@ -1,2 +1,8 @@ -fun test(a: Wombat iso) => - var b: Wombat iso = a // Not allowed! \ No newline at end of file +actor Main + new create(env: Env) => + test(Wombat) + + fun test(a: Wombat iso) => + var b: Wombat iso = a // Not allowed! + +class Wombat \ No newline at end of file diff --git a/code-samples/aliasing-trn-to-box.pony b/code-samples/aliasing-trn-to-box.pony index 443a799b..fe884f21 100644 --- a/code-samples/aliasing-trn-to-box.pony +++ b/code-samples/aliasing-trn-to-box.pony @@ -1,2 +1,8 @@ -fun test(a: Wombat trn) => - var b: Wombat box = a // Allowed! \ No newline at end of file +actor Main + new create(env: Env) => + test(Wombat) + + fun test(a: Wombat trn) => + var b: Wombat box = a // Allowed! + +class Wombat \ No newline at end of file diff --git a/code-samples/appendices-annotations-empty-with-nosupertype-annotation.pony b/code-samples/appendices-annotations-empty-with-nosupertype-annotation.pony index 10d96d82..31889564 100644 --- a/code-samples/appendices-annotations-empty-with-nosupertype-annotation.pony +++ b/code-samples/appendices-annotations-empty-with-nosupertype-annotation.pony @@ -4,4 +4,9 @@ class Foo fun foo[A: Any](a: (A | Empty val)) => match consume a | let a': A => None - end \ No newline at end of file + end + +actor Main + new create(env: Env) => + let foo: Foo = Foo + env.out.print(foo.foo[Any]("Something").string()) \ No newline at end of file diff --git a/code-samples/appendices-annotations-likely-and-unlikely-annotations.pony b/code-samples/appendices-annotations-likely-and-unlikely-annotations.pony index ea00d0af..00c802ab 100644 --- a/code-samples/appendices-annotations-likely-and-unlikely-annotations.pony +++ b/code-samples/appendices-annotations-likely-and-unlikely-annotations.pony @@ -1,16 +1,32 @@ -if \likely\ cond then - foo -end +type T is (U32|U8) -while \unlikely\ cond then - bar -end +actor Main + new create(env: Env) => + let foo = "foo" + let bar = "bar" + let baz = "baz" + var cond = true + let obj: U32 = 42 + let expr: U32 = 42 + + if \likely\ cond then + foo + end -repeat - baz -until \likely\ cond end + cond = false + while \unlikely\ cond do + bar + end -match obj -| \likely\ expr => foo -| \unlikely\ let capt: T => bar -end \ No newline at end of file + cond = true + repeat + baz + until \likely\ cond end + + let res = + match obj + | \likely\ expr => foo + | \unlikely\ let capt: T => bar + end + + env.out.print("res = " + res) \ No newline at end of file diff --git a/code-samples/appendices-annotations-packed-annotation.pony b/code-samples/appendices-annotations-packed-annotation.pony index e13d8926..e99a08fb 100644 --- a/code-samples/appendices-annotations-packed-annotation.pony +++ b/code-samples/appendices-annotations-packed-annotation.pony @@ -1,3 +1,11 @@ struct \packed\ MyPackedStruct var x: U8 - var y: U32 \ No newline at end of file + var y: U32 + + new create() => + x = 0 + y = 1 + +actor Main + new create(env: Env) => + env.out.print("{\n\t\"x\": " + MyPackedStruct.x.string() + ",\n\t\"y\": " + MyPackedStruct.y.string() + "\n}") \ No newline at end of file diff --git a/code-samples/appendices-examples-create-arrays-with-values.pony b/code-samples/appendices-examples-create-arrays-with-values.pony index 905c3859..f9206e84 100644 --- a/code-samples/appendices-examples-create-arrays-with-values.pony +++ b/code-samples/appendices-examples-create-arrays-with-values.pony @@ -1,5 +1,25 @@ -let dice: Array[U32] = [1; 2; 3 - 4 - 5 - 6 -] \ No newline at end of file +use "random" + +actor Main + new create(env: Env) => + let dice: Array[U32] = [1; 2; 3 + 4 + 5 + 6 + ] + Rand.shuffle[U32](dice) + for numberOfSpots in dice.values() do + env.out.print("You rolled a " + _ordinal(numberOfSpots)) + end + + fun _ordinal(number: U32): String => + match number + | 1 => "one" + | 2 => "two" + | 3 => "three" + | 4 => "four" + | 5 => "five" + | 6 => "six" + else + "out of range" + end \ No newline at end of file diff --git a/code-samples/appendices-examples-enumeration-with-values-with-namespace.pony b/code-samples/appendices-examples-enumeration-with-values-with-namespace.pony index 35f4c222..dafeb7c9 100644 --- a/code-samples/appendices-examples-enumeration-with-values-with-namespace.pony +++ b/code-samples/appendices-examples-enumeration-with-values-with-namespace.pony @@ -1,3 +1,20 @@ +use "format" +use "collections/persistent" + primitive Colours fun black(): U32 => 0xFF000000 - fun red(): U32 => 0xFFFF0000 \ No newline at end of file + fun red(): U32 => 0xFFFF0000 + +interface val Applyable + fun apply(): U32 + +actor Main + new create(env: Env) => + let colorMap: Map[String, Applyable] = Map[String, Applyable].concat([ + ("red", Colours~red()) + ("black", Colours~black()) + ].values()) + + for (colorName, color) in colorMap.pairs() do + env.out.print(colorName + ": #" + Format.int[U32](color(), FormatHexBare)) + end \ No newline at end of file diff --git a/code-samples/appendices-examples-enumeration-with-values.pony b/code-samples/appendices-examples-enumeration-with-values.pony index 1be5b0e2..e17df830 100644 --- a/code-samples/appendices-examples-enumeration-with-values.pony +++ b/code-samples/appendices-examples-enumeration-with-values.pony @@ -1,2 +1,19 @@ +use "format" +use "collections/persistent" + primitive Black fun apply(): U32 => 0xFF000000 -primitive Red fun apply(): U32 => 0xFFFF0000 \ No newline at end of file +primitive Red fun apply(): U32 => 0xFFFF0000 + +type Color is (Red | Black) + +actor Main + new create(env: Env) => + + let colorMap: Map[String, Color] = Map[String, Color].concat([ + ("red", Red) + ("black", Black) + ].values()) + + for (colorName, color) in colorMap.pairs() do + env.out.print(colorName + ": #" + Format.int[U32](color(), FormatHexBare)) + end \ No newline at end of file diff --git a/code-samples/appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony b/code-samples/appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony index 045ea728..a69e2399 100644 --- a/code-samples/appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony +++ b/code-samples/appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony @@ -1,2 +1,16 @@ -a --b \ No newline at end of file +use "format" +use "collections/persistent" + +primitive Black fun apply(): U32 => 0xFF000000 +primitive Red fun apply(): U32 => 0xFFFF0000 + +type Color is (Red | Black) + +actor Main + new create(env: Env) => + let a: I8 = 1 + let b: I8 = 3 + let c: I8 = + a + -b + env.out.print(c.string()) \ No newline at end of file diff --git a/code-samples/appendices-whitespace-subtract-b-from-a.pony b/code-samples/appendices-whitespace-subtract-b-from-a.pony index f76d71bf..5baa9b23 100644 --- a/code-samples/appendices-whitespace-subtract-b-from-a.pony +++ b/code-samples/appendices-whitespace-subtract-b-from-a.pony @@ -1 +1,15 @@ -a - b \ No newline at end of file +use "format" +use "collections/persistent" + +primitive Black fun apply(): U32 => 0xFF000000 +primitive Red fun apply(): U32 => 0xFFFF0000 + +type Color is (Red | Black) + +actor Main + new create(env: Env) => + let a: I8 = 1 + let b: I8 = 3 + let c: I8 = + a - b + env.out.print(c.string()) \ No newline at end of file diff --git a/code-samples/arithmetic-partial-and-check-arithmetic.pony b/code-samples/arithmetic-partial-and-check-arithmetic.pony index 14ed8b78..d089278c 100644 --- a/code-samples/arithmetic-partial-and-check-arithmetic.pony +++ b/code-samples/arithmetic-partial-and-check-arithmetic.pony @@ -1,17 +1,26 @@ -// partial arithmetic -let result = - try - USize.max_value() +? env.args.size() - else - env.out.print("overflow detected") - end +actor Main + new create(env: Env) => + partial(env) + checked(env) + + fun partial(env: Env) => + // partial arithmetic + let result = + try + USize.max_value() +? env.args.size() + else + env.out.print("overflow detected") + end -// checked arithmetic -let result = - match USize.max_value().addc(env.args.size()) - | (let result: USize, false) => - // use result - ... - | (_, true) => - env.out.print("overflow detected") - end \ No newline at end of file + fun checked(env: Env) => + // checked arithmetic + let result = + match USize.max_value().addc(env.args.size()) + | (let result: USize, false) => + // use result + env.out.print(result.string())/* + ... + */ + | (_, true) => + env.out.print("overflow detected") + end \ No newline at end of file diff --git a/code-samples/as-operator-match-statement-comparison.pony b/code-samples/as-operator-match-statement-comparison.pony index c3cd6a45..3791f57b 100644 --- a/code-samples/as-operator-match-statement-comparison.pony +++ b/code-samples/as-operator-match-statement-comparison.pony @@ -1,3 +1,13 @@ +interface Critter + fun wash(): String + +class Wombat is Critter + fun wash(): String => "I'm a clean wombat!" + +class Capybara is Critter + fun wash(): String => "I feel squeaky clean!" + fun swim(): String => "I'm swimming like a fish!" + actor Main new create(env: Env) => let anys = Array[Any ref].>push(Wombat).>push(Capybara) diff --git a/code-samples/as-operator-match-statement-without-try.pony b/code-samples/as-operator-match-statement-without-try.pony index 16d6bb73..bc167ab5 100644 --- a/code-samples/as-operator-match-statement-without-try.pony +++ b/code-samples/as-operator-match-statement-without-try.pony @@ -1,3 +1,13 @@ +interface Critter + fun wash(): String + +class Wombat is Critter + fun wash(): String => "I'm a clean wombat!" + +class Capybara is Critter + fun wash(): String => "I feel squeaky clean!" + fun swim(): String => "I'm swimming like a fish!" + actor Main new create(env: Env) => let anys = Array[Any ref].>push(Wombat).>push(Capybara) diff --git a/code-samples/as-operator-more-specific-interface-with-reference-capability.pony b/code-samples/as-operator-more-specific-interface-with-reference-capability.pony index 30960f93..e3913378 100644 --- a/code-samples/as-operator-more-specific-interface-with-reference-capability.pony +++ b/code-samples/as-operator-more-specific-interface-with-reference-capability.pony @@ -1,3 +1,13 @@ +interface Critter + fun wash(): String + +class Wombat is Critter + fun wash(): String => "I'm a clean wombat!" + +class Capybara is Critter + fun wash(): String => "I feel squeaky clean!" + fun swim(): String => "I'm swimming like a fish!" + actor Main new create(env: Env) => let anys = Array[Any ref].>push(Wombat).>push(Capybara) diff --git a/code-samples/as-operator-unrelated-type.pony b/code-samples/as-operator-unrelated-type.pony index 5102043a..2cac3a36 100644 --- a/code-samples/as-operator-unrelated-type.pony +++ b/code-samples/as-operator-unrelated-type.pony @@ -1,10 +1,25 @@ - trait Alive +trait Alive - trait Well +trait Well - class Person is (Alive & Well) +class Person is (Alive & Well) - class LifeSigns - fun is_all_good(alive: Alive)? => - // if the instance 'alive' is also of type 'Well' (such as a Person instance). raises error if not possible - let well: Well = alive as Well \ No newline at end of file +class LifeSigns + fun is_all_good(alive: Alive)? => + // if the instance 'alive' is also of type 'Well' (such as a Person instance). raises error if not possible + let well: Well = alive as Well + +class Dog is Alive + +actor Main + new create(env: Env) => + try + LifeSigns.is_all_good(Person)? + else + env.err.print("Person is alive but not well") + end + try + LifeSigns.is_all_good(Dog)? + else + env.err.print("Dog is alive but not well") + end diff --git a/code-samples/c-abi-jump-consistent-hashing.pony b/code-samples/c-abi-jump-consistent-hashing.pony index dbb9920c..daf54193 100644 --- a/code-samples/c-abi-jump-consistent-hashing.pony +++ b/code-samples/c-abi-jump-consistent-hashing.pony @@ -1,15 +1,19 @@ -// Jump consistent hashing in Pony, with an inline pseudo random generator -// https://arxiv.org/abs/1406.2294 +actor Main + new create(env: Env) => + env.out.print("jch: " + jch(U64(10), U32(20)).string()) -fun jch(key: U64, buckets: U32): I32 => - var k = key - var b = I64(0) - var j = I64(0) + // Jump consistent hashing in Pony, with an inline pseudo random generator + // https://arxiv.org/abs/1406.2294 - while j < buckets.i64() do - b = j - k = (k * 2862933555777941757) + 1 - j = ((b + 1).f64() * (I64(1 << 31).f64() / ((k >> 33) + 1).f64())).i64() - end - - b.i32() \ No newline at end of file + fun jch(key: U64, buckets: U32): I32 => + var k = key + var b = I64(0) + var j = I64(0) + + while j < buckets.i64() do + b = j + k = (k * 2862933555777941757) + 1 + j = ((b + 1).f64() * (I64(1 << 31).f64() / ((k >> 33) + 1).f64())).i64() + end + + b.i32() \ No newline at end of file diff --git a/code-samples/calling-c-from-c-struct.pony b/code-samples/calling-c-from-c-struct.pony index fccbeb2b..a9ca33d9 100644 --- a/code-samples/calling-c-from-c-struct.pony +++ b/code-samples/calling-c-from-c-struct.pony @@ -2,4 +2,14 @@ use @from_c[Rect]() struct Rect var length: U16 - var width: U16 \ No newline at end of file + var width: U16 + + new create(length': U16, width': U16) => + length = length' + width = width' + +actor Main + new create(env: Env) => + let rect = Rect(2, 3) + + env.out.print("This rect is " + rect.length.string() + " cm x " + rect.width.string() + " cm") \ No newline at end of file diff --git a/code-samples/calling-c-ioctl-struct.pony b/code-samples/calling-c-ioctl-struct.pony index b7debc8b..e104ee78 100644 --- a/code-samples/calling-c-ioctl-struct.pony +++ b/code-samples/calling-c-ioctl-struct.pony @@ -5,9 +5,11 @@ struct Winsize var width: U16 = 0 new create() => None - -let size = Winsize - -@ioctl(0, 21523, NullablePointer[Winsize](size)) - -env.out.print(size.height.string()) \ No newline at end of file + +actor Main + new create(env: Env) => + let size = Winsize + + @ioctl(0, 21523, NullablePointer[Winsize](size)) + + env.out.print(size.height.string()) \ No newline at end of file diff --git a/code-samples/calling-c-variadic-c-functions.pony b/code-samples/calling-c-variadic-c-functions.pony index f8e59f50..f252e654 100644 --- a/code-samples/calling-c-variadic-c-functions.pony +++ b/code-samples/calling-c-variadic-c-functions.pony @@ -1,5 +1,12 @@ use @printf[I32](fmt: Pointer[U8] tag, ...) // ... -let run_ns: I64 = _current_t - _last_t -let rate: I64 = (_partial_count.i64() * 1_000_000_000) / run_ns -@printf("Elapsed: %lld,%lld\n".cstring(), run_ns, rate) \ No newline at end of file + +actor Main + let _current_t: I64 = 5 + let _last_t: I64 = 1 + let _partial_count: F64 = 42.0 + + new create(env: Env) => + let run_ns: I64 = _current_t - _last_t + let rate: I64 = (_partial_count.i64() * 1_000_000_000) / run_ns + @printf("Elapsed: %lld,%lld\n".cstring(), run_ns, rate) diff --git a/code-samples/calling-c-writev-struct.pony b/code-samples/calling-c-writev-struct.pony index 125be5b2..37244865 100644 --- a/code-samples/calling-c-writev-struct.pony +++ b/code-samples/calling-c-writev-struct.pony @@ -10,8 +10,10 @@ struct IOVec var base: Pointer[U8] tag = Pointer[U8] var len: USize = 0 -let data = "Hello from Pony!" -var iov = IOVec -iov.base = data.cpointer() -iov.len = data.size() -@writev(1, iov, 1) // Will print "Hello from Pony!" \ No newline at end of file +actor Main + new create(env: Env) => + let data = "Hello from Pony!" + var iov = IOVec + iov.base = data.cpointer() + iov.len = data.size() + @writev(1, iov, 1) // Will print "Hello from Pony!" \ No newline at end of file diff --git a/code-samples/calling-c-writev-tuple.pony b/code-samples/calling-c-writev-tuple.pony index 531f5965..89bae9f5 100644 --- a/code-samples/calling-c-writev-tuple.pony +++ b/code-samples/calling-c-writev-tuple.pony @@ -1,5 +1,7 @@ use @writev[USize](fd: U32, iov: Pointer[(Pointer[U8] tag, USize)] tag, iovcnt: I32) -let data = "Hello from Pony!" -var iov = (data.cpointer(), data.size()) -@writev(1, addressof iov, 1) // Will print "Hello from Pony!" \ No newline at end of file +actor Main + new create(env: Env) => + let data = "Hello from Pony!" + var iov = (data.cpointer(), data.size()) + @writev(1, addressof iov, 1) // Will print "Hello from Pony!" \ No newline at end of file diff --git a/code-samples/classes-swap-values-sugar.pony b/code-samples/classes-swap-values-sugar.pony index 9c8eb05c..423765b7 100644 --- a/code-samples/classes-swap-values-sugar.pony +++ b/code-samples/classes-swap-values-sugar.pony @@ -1 +1,7 @@ -a = b = a \ No newline at end of file +actor Main + new create(env: Env) => + var a: U64 = 1 + var b: U64 = 2 + env.out.print("a = " + a.string() + ", b = " + b.string()) + a = b = a + env.out.print("a = " + a.string() + ", b = " + b.string()) \ No newline at end of file diff --git a/code-samples/classes-swap-values.pony b/code-samples/classes-swap-values.pony index 97937f3c..30216ebc 100644 --- a/code-samples/classes-swap-values.pony +++ b/code-samples/classes-swap-values.pony @@ -1,3 +1,9 @@ -var temp = a -a = b -b = temp \ No newline at end of file +actor Main + new create(env: Env) => + var a: U64 = 1 + var b: U64 = 2 + env.out.print("a = " + a.string() + ", b = " + b.string()) + var temp = a + a = b + b = temp + env.out.print("a = " + a.string() + ", b = " + b.string()) \ No newline at end of file diff --git a/code-samples/classes-wombat-constructors.pony b/code-samples/classes-wombat-constructors.pony index 4e9c3863..f151d095 100644 --- a/code-samples/classes-wombat-constructors.pony +++ b/code-samples/classes-wombat-constructors.pony @@ -1,3 +1,10 @@ +actor Main + new create(env: Env) => + let defaultWombat = Wombat("Fantastibat") // Invokes the create method by default + let hungryWombat = Wombat.hungry("Nomsbat", 12) // Invokes the hungry method + env.out.print("Your default wombat's name is \"" + defaultWombat.name + "\"") + env.out.print("Your hungry wombat's name is \"" + hungryWombat.name + "\"") + class Wombat let name: String var _hunger_level: U64 diff --git a/code-samples/classes-wombat.pony b/code-samples/classes-wombat.pony index 1c647876..4d240360 100644 --- a/code-samples/classes-wombat.pony +++ b/code-samples/classes-wombat.pony @@ -1,3 +1,11 @@ +actor Main + new create(env: Env) => + let defaultWombat = Wombat("Fantastibat") // Invokes the create method by default + let hungryWombat = Wombat.hungry("Nomsbat", 12) // Invokes the hungry method + defaultWombat.set_hunger(5) + env.out.print(defaultWombat.name + " has a hunger level of " + defaultWombat.hunger().string()) + env.out.print(hungryWombat.name + " has a hunger level of " + hungryWombat.hunger().string()) + class Wombat let name: String var _hunger_level: U64 diff --git a/code-samples/classes-zero-argument-constructors.pony b/code-samples/classes-zero-argument-constructors.pony index 58521846..c49825d1 100644 --- a/code-samples/classes-zero-argument-constructors.pony +++ b/code-samples/classes-zero-argument-constructors.pony @@ -1,3 +1,11 @@ +actor Main + new create(env: Env) => + let forest = Forest + +class Forest + let _owl: Owl = Owl + let _hawk: Hawk = Hawk + class Hawk var _hunger_level: U64 = 0 diff --git a/code-samples/consume-and-destructive-read-consuming-a-variable-failure.pony b/code-samples/consume-and-destructive-read-consuming-a-variable-failure.pony new file mode 100644 index 00000000..e100f4eb --- /dev/null +++ b/code-samples/consume-and-destructive-read-consuming-a-variable-failure.pony @@ -0,0 +1,9 @@ +actor Main + new create(env: Env) => + test(Wombat) + + fun test(a: Wombat iso) => + var b: Wombat iso = consume a // Allowed! + var c: Wombat tag = a // Not allowed! + +class Wombat \ No newline at end of file diff --git a/code-samples/consume-and-destructive-read-consuming-a-variable.pony b/code-samples/consume-and-destructive-read-consuming-a-variable.pony index c4134247..12b34f35 100644 --- a/code-samples/consume-and-destructive-read-consuming-a-variable.pony +++ b/code-samples/consume-and-destructive-read-consuming-a-variable.pony @@ -1,3 +1,8 @@ -fun test(a: Wombat iso) => - var b: Wombat iso = consume a // Allowed! - var c: Wombat tag = a // Not allowed! \ No newline at end of file +actor Main + new create(env: Env) => + test(Wombat) + + fun test(a: Wombat iso) => + var b: Wombat iso = consume a // Allowed! + +class Wombat \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-expression-implicit-none.pony b/code-samples/control-structures-conditionals-expression-implicit-none.pony index bb9d0837..b0afb94d 100644 --- a/code-samples/control-structures-conditionals-expression-implicit-none.pony +++ b/code-samples/control-structures-conditionals-expression-implicit-none.pony @@ -1,4 +1,8 @@ -var x: (String | None) = - if friendly then - "Hello" - end \ No newline at end of file +actor Main + new create(env: Env) => + let friendly = false + var x: (String | None) = + if friendly then + "Hello" + end + env.out.print(x.string()) \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-expression-union-type.pony b/code-samples/control-structures-conditionals-expression-union-type.pony index ee2ea45a..91969306 100644 --- a/code-samples/control-structures-conditionals-expression-union-type.pony +++ b/code-samples/control-structures-conditionals-expression-union-type.pony @@ -1,6 +1,10 @@ -var x: (String | Bool) = - if friendly then - "Hello" - else - false - end \ No newline at end of file +actor Main + new create(env: Env) => + let friendly = false + var x: (String | Bool) = + if friendly then + "Hello" + else + false + end + env.out.print(x.string()) \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-expressions.pony b/code-samples/control-structures-conditionals-expressions.pony index fb1ca3e1..b41f7c65 100644 --- a/code-samples/control-structures-conditionals-expressions.pony +++ b/code-samples/control-structures-conditionals-expressions.pony @@ -1 +1,6 @@ -x = 1 + if lots then 100 else 2 end \ No newline at end of file +actor Main + new create(env: Env) => + let lots = true + var x: U32 + x = 1 + if lots then 100 else 2 end + env.out.print("x = " + x.string() + "—that's " + (if lots then "lots" else "not a lot" end)) \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-if-else.pony b/code-samples/control-structures-conditionals-if-else.pony index 14033612..2d61737c 100644 --- a/code-samples/control-structures-conditionals-if-else.pony +++ b/code-samples/control-structures-conditionals-if-else.pony @@ -1,5 +1,9 @@ -if a > b then - env.out.print("a is bigger") -else - env.out.print("a is not bigger") -end \ No newline at end of file +actor Main + new create(env: Env) => + let a: U8 = 1 + let b: U8 = 2 + if a > b then + env.out.print("a is bigger") + else + env.out.print("a is not bigger") + end \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-if-elseif-else.pony b/code-samples/control-structures-conditionals-if-elseif-else.pony index f9d0a01f..824f8056 100644 --- a/code-samples/control-structures-conditionals-if-elseif-else.pony +++ b/code-samples/control-structures-conditionals-if-elseif-else.pony @@ -1,7 +1,11 @@ -if a == b then - env.out.print("they are the same") -elseif a > b then - env.out.print("a is bigger") -else - env.out.print("b bigger") -end \ No newline at end of file +actor Main + new create(env: Env) => + let a: U8 = 2 + let b: U8 = 1 + if a == b then + env.out.print("they are the same") + elseif a > b then + env.out.print("a is bigger") + else + env.out.print("b bigger") + end \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-if.pony b/code-samples/control-structures-conditionals-if.pony index a2a672f2..7c006a4d 100644 --- a/code-samples/control-structures-conditionals-if.pony +++ b/code-samples/control-structures-conditionals-if.pony @@ -1,3 +1,7 @@ -if a > b then - env.out.print("a is bigger") -end \ No newline at end of file +actor Main + new create(env: Env) => + let a: U8 = 2 + let b: U8 = 1 + if a > b then + env.out.print("a is bigger") + end \ No newline at end of file diff --git a/code-samples/control-structures-conditionals-nested-if-else.pony b/code-samples/control-structures-conditionals-nested-if-else.pony index df7477bd..5f796257 100644 --- a/code-samples/control-structures-conditionals-nested-if-else.pony +++ b/code-samples/control-structures-conditionals-nested-if-else.pony @@ -1,9 +1,13 @@ -if a == b then - env.out.print("they are the same") -else - if a > b then - env.out.print("a is bigger") - else - env.out.print("b bigger") - end -end \ No newline at end of file +actor Main + new create(env: Env) => + let a: U8 = 2 + let b: U8 = 2 + if a == b then + env.out.print("they are the same") + else + if a > b then + env.out.print("a is bigger") + else + env.out.print("b bigger") + end + end \ No newline at end of file diff --git a/code-samples/control-structures-loops-for-while-comparison.pony b/code-samples/control-structures-loops-for-while-comparison.pony index 91d327cb..e8acf0a9 100644 --- a/code-samples/control-structures-loops-for-while-comparison.pony +++ b/code-samples/control-structures-loops-for-while-comparison.pony @@ -1,5 +1,9 @@ -let iterator = ["Bob"; "Fred"; "Sarah"].values() -while iterator.has_next() do - let name = iterator.next()? - env.out.print(name) -end \ No newline at end of file +actor Main + new create(env: Env) => + try + let iterator = ["Bob"; "Fred"; "Sarah"].values() + while iterator.has_next() do + let name = iterator.next()? + env.out.print(name) + end + end \ No newline at end of file diff --git a/code-samples/control-structures-loops-for.pony b/code-samples/control-structures-loops-for.pony index 64d97f3a..d8ee843d 100644 --- a/code-samples/control-structures-loops-for.pony +++ b/code-samples/control-structures-loops-for.pony @@ -1,3 +1,5 @@ -for name in ["Bob"; "Fred"; "Sarah"].values() do - env.out.print(name) -end \ No newline at end of file +actor Main + new create(env: Env) => + for name in ["Bob"; "Fred"; "Sarah"].values() do + env.out.print(name) + end \ No newline at end of file diff --git a/code-samples/control-structures-loops-while-break-else.pony b/code-samples/control-structures-loops-while-break-else.pony index 357cd5c0..32ab90d0 100644 --- a/code-samples/control-structures-loops-while-break-else.pony +++ b/code-samples/control-structures-loops-while-break-else.pony @@ -1,10 +1,31 @@ -var name = - while moreNames() do - var name' = getName() - if name' == "Jack" or name' == "Jill" then - break name' - end - name' - else +actor Main + let names: Array[String] = [ + "Jack" "Herbert" - end \ No newline at end of file + "Jill" + ] + var current_name: String = "" + + new create(env: Env) => + var name = + while moreNames() do + var name' = getName() + if (name' == "Jack") or (name' == "Jill") then + break name' + end + name' + else + "Herbert" + end + env.out.print("name = " + name) + + fun ref moreNames(): Bool => + try + current_name = names.shift()? + else + return false + end + true + + fun getName(): String => + current_name \ No newline at end of file diff --git a/code-samples/control-structures-loops-while.pony b/code-samples/control-structures-loops-while.pony index 881ef4b5..cfe99ab1 100644 --- a/code-samples/control-structures-loops-while.pony +++ b/code-samples/control-structures-loops-while.pony @@ -1,6 +1,8 @@ -var count: U32 = 1 +actor Main + new create(env: Env) => + var count: U32 = 1 -while count <= 10 do - env.out.print(count.string()) - count = count + 1 -end \ No newline at end of file + while count <= 10 do + env.out.print(count.string()) + count = count + 1 + end \ No newline at end of file diff --git a/code-samples/derived-authority-restrict-then-delegate-your-authority.pony b/code-samples/derived-authority-restrict-then-delegate-your-authority.pony index 9239f4f7..335b278f 100644 --- a/code-samples/derived-authority-restrict-then-delegate-your-authority.pony +++ b/code-samples/derived-authority-restrict-then-delegate-your-authority.pony @@ -1,3 +1,18 @@ +use "net" + +class MyTCPConnectionNotify is TCPConnectionNotify + let _out: OutStream + + new iso create(out: OutStream) => + _out = out + + fun ref connected(conn: TCPConnection ref) => + _out.print("connected") + conn.close() + + fun ref connect_failed(conn: TCPConnection ref) => + _out.print("connect_failed") + actor Connect new create(out: OutStream, auth: TCPConnectAuth) => TCPConnection(auth, MyTCPConnectionNotify(out), "example.com", "80") diff --git a/code-samples/divide-by-zero-floats.pony b/code-samples/divide-by-zero-floats.pony index f608e0da..09685970 100644 --- a/code-samples/divide-by-zero-floats.pony +++ b/code-samples/divide-by-zero-floats.pony @@ -1 +1,5 @@ -let x = F64(1.5) /~ F64(0.5) \ No newline at end of file +actor Main + new create(env: Env) => + // the value of x is undefined + let x = F64(1.5) /~ F64(0.5) + env.out.print("1.5÷0.5 = " + x.string()) \ No newline at end of file diff --git a/code-samples/divide-by-zero.pony b/code-samples/divide-by-zero.pony index b0f8757f..e34ec879 100644 --- a/code-samples/divide-by-zero.pony +++ b/code-samples/divide-by-zero.pony @@ -1 +1,4 @@ -let x = I64(1) / I64(0) \ No newline at end of file +actor Main + new create(env: Env) => + let x = I64(1) / I64(0) + env.out.print("1÷0 = " + x.string()) \ No newline at end of file diff --git a/code-samples/errors-partial-functions.pony b/code-samples/errors-partial-functions.pony index 54dccb3b..72d50cd3 100644 --- a/code-samples/errors-partial-functions.pony +++ b/code-samples/errors-partial-functions.pony @@ -1,7 +1,22 @@ -fun factorial(x: I32): I32 ? => - if x < 0 then error end - if x == 0 then - 1 - else - x * factorial(x - 1)? - end \ No newline at end of file +actor Main + new create(env: Env) => + try + let fac5 = factorial(5)? + env.out.print("factorial(5) results in " + fac5.string()) + else + env.err.print("factorial(5) failed") + end + try + let facNeg5 = factorial(-5)? + env.out.print("factorial(-5) results in " + facNeg5.string()) + else + env.err.print("factorial(-5) failed") + end + + fun factorial(x: I32): I32 ? => + if x < 0 then error end + if x == 0 then + 1 + else + x * factorial(x - 1)? + end \ No newline at end of file diff --git a/code-samples/errors-try-else.pony b/code-samples/errors-try-else.pony index 551688d3..b4cad70d 100644 --- a/code-samples/errors-try-else.pony +++ b/code-samples/errors-try-else.pony @@ -1,7 +1,27 @@ -try - callA() - if not callB() then error end - callC() -else - callD() -end \ No newline at end of file +actor Main + var _err: OutStream + var _out: OutStream + + new create(env: Env) => + _err = env.err + _out = env.out + + try + callA() + if not callB() then error end + callC() + else + callD() + end + + fun callA(): Bool => + true + + fun callB(): Bool => + false + + fun callC() => + _out.print("callB() executed successfully") + + fun callD() => + _err.print("callB() resulted in an error") diff --git a/code-samples/errors-try-then.pony b/code-samples/errors-try-then.pony index 3e3db5f0..8857761f 100644 --- a/code-samples/errors-try-then.pony +++ b/code-samples/errors-try-then.pony @@ -1,9 +1,32 @@ -try - callA() - if not callB() then error end - callC() -else - callD() -then - callE() -end \ No newline at end of file +actor Main + var _err: OutStream + var _out: OutStream + + new create(env: Env) => + _err = env.err + _out = env.out + + try + callA() + if not callB() then error end + callC() + else + callD() + then + callE() + end + + fun callA(): Bool => + true + + fun callB(): Bool => + false + + fun callC() => + _out.print("callB() executed successfully") + + fun callD() => + _err.print("callB() resulted in an error") + + fun callE() => + _out.print("I don't know whether callB() was executed successfully ¯\\_ (ツ)_/¯ I get executed either way") \ No newline at end of file diff --git a/code-samples/generics-and-reference-capabilities-foo-iso-error-message.txt b/code-samples/generics-and-reference-capabilities-foo-iso-error-message.txt deleted file mode 100644 index 4c372132..00000000 --- a/code-samples/generics-and-reference-capabilities-foo-iso-error-message.txt +++ /dev/null @@ -1,7 +0,0 @@ -main.pony:5:8: right side must be a subtype of left side - _c = c - ^ - Info: - main.pony:4:17: String iso! is not a subtype of String iso: iso! is not a subtype of iso - new create(c: String iso) => - ^ \ No newline at end of file diff --git a/code-samples/generics-foo-string.pony b/code-samples/generics-foo-string.pony index 4d4fa9c5..eb599108 100644 --- a/code-samples/generics-foo-string.pony +++ b/code-samples/generics-foo-string.pony @@ -6,4 +6,9 @@ class FooString fun get(): String val => _c - fun ref set(c: String val) => _c = c \ No newline at end of file + fun ref set(c: String val) => _c = c + +actor Main + new create(env:Env) => + let c = FooString("Hello") + env.out.print(c.get()) \ No newline at end of file diff --git a/code-samples/generics-generic-class-initialization.pony b/code-samples/generics-generic-class-initialization.pony deleted file mode 100644 index fd97d742..00000000 --- a/code-samples/generics-generic-class-initialization.pony +++ /dev/null @@ -1,3 +0,0 @@ -let a = Foo[U32](42) -let b = Foo[F32](1.5) -let c = Foo[String]("Hello") \ No newline at end of file diff --git a/code-samples/generics-type-parameter-defaults-definition.pony b/code-samples/generics-type-parameter-defaults-definition.pony deleted file mode 100644 index c6f4ac5d..00000000 --- a/code-samples/generics-type-parameter-defaults-definition.pony +++ /dev/null @@ -1,9 +0,0 @@ -class Bar[A: Any box = USize val] - var _c: A - - new create(c: A) => - _c = c - - fun get(): A => _c - - fun ref set(c: A) => _c = c \ No newline at end of file diff --git a/code-samples/generics-type-parameter-defaults-initialization.pony b/code-samples/generics-type-parameter-defaults-initialization.pony deleted file mode 100644 index 94ccad6c..00000000 --- a/code-samples/generics-type-parameter-defaults-initialization.pony +++ /dev/null @@ -1,3 +0,0 @@ -let a = Bar(42) -let b = Bar[USize](42) -let c = Bar[F32](1.5) \ No newline at end of file diff --git a/code-samples/generics-type-parameter-defaults.pony b/code-samples/generics-type-parameter-defaults.pony new file mode 100644 index 00000000..6f70dcaa --- /dev/null +++ b/code-samples/generics-type-parameter-defaults.pony @@ -0,0 +1,15 @@ +class Bar[A: Any box = USize val] + var _c: A + + new create(c: A) => + _c = c + + fun get(): A => _c + + fun ref set(c: A) => _c = c + +actor Main + new create(env:Env) => + let a = Bar(42) + let b = Bar[USize](42) + let c = Bar[F32](1.5) \ No newline at end of file diff --git a/code-samples/literals-array-literals.pony b/code-samples/literals-array-literals.pony index dd3bf10d..1e24dd7b 100644 --- a/code-samples/literals-array-literals.pony +++ b/code-samples/literals-array-literals.pony @@ -1,5 +1,31 @@ -let my_literal_array = - [ - "first"; "second" - "third one on a new line" - ] \ No newline at end of file +actor Main + new create(env: Env) => + let my_literal_array = + [ + "first"; "second" + "third one on a new line" + ] + + try + env.out.print(my_literal_array(0)? + ", " + my_literal_array(1)? + ", " + my_literal_array(2)?) + end + + // or: + for entry in my_literal_array.values() do + env.out.print(entry) + end + + // or: + for pair in my_literal_array.pairs() do + env.out.write(pair._2 + (if (pair._1 + 1) < my_literal_array.size() then ", " else "" end)) + end + env.out.print("") + + // or: + env.out.print(", ".join(my_literal_array.values())) + + // or: + while my_literal_array.size() > 0 do + let entry = try my_literal_array.shift()? end + env.out.print(entry.string()) + end diff --git a/code-samples/literals-character-literals.pony b/code-samples/literals-character-literals.pony index f2ebc19b..8e60d143 100644 --- a/code-samples/literals-character-literals.pony +++ b/code-samples/literals-character-literals.pony @@ -1,3 +1,9 @@ -let big_a: U8 = 'A' // 65 -let hex_escaped_big_a: U8 = '\x41' // 65 -let newline: U32 = '\n' // 10 \ No newline at end of file +actor Main + new create(env: Env) => + let big_a: U8 = 'A' // 65 + let hex_escaped_big_a: U8 = '\x41' // 65 + let newline: U32 = '\n' // 10 + env.out.print( + "\"" + String.from_array([big_a]) + "\" (char " + big_a.string()+ ") = " + + "\"" + String.from_array([hex_escaped_big_a]) + "\" (char " + hex_escaped_big_a.string() + ") = " + + "\"" + String.from_array([newline.u8()]) + "\" (char " + newline.string() + ")") \ No newline at end of file diff --git a/code-samples/literals-number-types.pony b/code-samples/literals-number-types.pony index bd9fa719..b206a130 100644 --- a/code-samples/literals-number-types.pony +++ b/code-samples/literals-number-types.pony @@ -1,3 +1,6 @@ -let my_decimal_int: I32 = 1024 -let my_hexadecimal_int: I32 = 0x400 -let my_binary_int: I32 = 0b10000000000 \ No newline at end of file +actor Main + new create(env: Env) => + let my_decimal_int: I32 = 1024 + let my_hexadecimal_int: I32 = 0x400 + let my_binary_int: I32 = 0b10000000000 + env.out.print(my_decimal_int.string() + " = " + my_hexadecimal_int.string() + " = " + my_binary_int.string()) \ No newline at end of file diff --git a/code-samples/literals-string-literals-encoding-latin-1.pony b/code-samples/literals-string-literals-encoding-latin-1.pony new file mode 100644 index 00000000..0541cc0e --- /dev/null +++ b/code-samples/literals-string-literals-encoding-latin-1.pony @@ -0,0 +1,11 @@ +actor Main + new create(env: Env) => + let u_umlaut = "�" + + let runes = u_umlaut.runes() + try + if runes.has_next() then + let rune = u_umlaut.runes().next()? + env.out.print(u_umlaut + ": " + Format.int[U32](rune, FormatHex)) + end + end \ No newline at end of file diff --git a/code-samples/literals-string-literals-encoding.pony b/code-samples/literals-string-literals-encoding.pony index b16d5df6..4e873ace 100644 --- a/code-samples/literals-string-literals-encoding.pony +++ b/code-samples/literals-string-literals-encoding.pony @@ -1 +1,11 @@ -let u_umlaut = "ü" \ No newline at end of file +actor Main + new create(env: Env) => + let u_umlaut = "ü" + + let runes = u_umlaut.runes() + try + if runes.has_next() then + let rune = u_umlaut.runes().next()? + env.out.print(u_umlaut + ": " + Format.int[U32](rune, FormatHex)) + end + end \ No newline at end of file diff --git a/code-samples/literals-string-literals-instances.pony b/code-samples/literals-string-literals-instances.pony index ff1cbb42..cf427c20 100644 --- a/code-samples/literals-string-literals-instances.pony +++ b/code-samples/literals-string-literals-instances.pony @@ -1,5 +1,10 @@ -let pony = "🐎" -let another_pony = "🐎" -if pony is another_pony then - // True, therefore this line will run. -end \ No newline at end of file +actor Main + new create(env: Env) => + let pony = "🐎" + let another_pony = "🐎" + if pony is another_pony then + // True, therefore this line will run. + env.out.print("Same pony") + else + env.out.print("A different pony") + end \ No newline at end of file diff --git a/code-samples/match-captures.pony b/code-samples/match-captures.pony index 2d96a6ba..70a9ea99 100644 --- a/code-samples/match-captures.pony +++ b/code-samples/match-captures.pony @@ -1,8 +1,13 @@ -fun f(x: (U32 | String | None)): String => - match x - | None => "none" - | 2 => "two" - | 3 => "three" - | let u: U32 => "other integer" - | let s: String => s - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f(2)) + env.out.print(f(42)) + + fun f(x: (U32 | String | None)): String => + match x + | None => "none" + | 2 => "two" + | 3 => "three" + | let u: U32 => "other integer" + | let s: String => s + end \ No newline at end of file diff --git a/code-samples/match-guards.pony b/code-samples/match-guards.pony index 50799738..8a824fe2 100644 --- a/code-samples/match-guards.pony +++ b/code-samples/match-guards.pony @@ -1,10 +1,15 @@ -fun f(x: (String | None), y: U32): String => - match (x, y) - | (None, _) => "none" - | (let s: String, 2) => s + " two" - | (let s: String, 3) => s + " three" - | (let s: String, let u: U32) if u > 14 => s + " other big integer" - | (let s: String, _) => s + " other small integer" - else - "something else" - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f("one", 5)) + env.out.print(f("two", 42)) + + fun f(x: (String | None), y: U32): String => + match (x, y) + | (None, _) => "none" + | (let s: String, 2) => s + " two" + | (let s: String, 3) => s + " three" + | (let s: String, let u: U32) if u > 14 => s + " other big integer" + | (let s: String, _) => s + " other small integer" + else + "something else" + end \ No newline at end of file diff --git a/code-samples/match-tuples-ignore-elements.pony b/code-samples/match-tuples-ignore-elements.pony index 34f7057d..9b4be3ef 100644 --- a/code-samples/match-tuples-ignore-elements.pony +++ b/code-samples/match-tuples-ignore-elements.pony @@ -1,9 +1,13 @@ -fun f(x: (String | None), y: U32): String => - match (x, y) - | (None, _) => "none" - | (let s: String, 2) => s + " two" - | (let s: String, 3) => s + " three" - | (let s: String, _) => s + " other integer" - else - "something else" - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f("one", 42)) + + fun f(x: (String | None), y: U32): String => + match (x, y) + | (None, _) => "none" + | (let s: String, 2) => s + " two" + | (let s: String, 3) => s + " three" + | (let s: String, _) => s + " other integer" + else + "something else" + end \ No newline at end of file diff --git a/code-samples/match-tuples.pony b/code-samples/match-tuples.pony index 74e0bd0d..28e7c8ab 100644 --- a/code-samples/match-tuples.pony +++ b/code-samples/match-tuples.pony @@ -1,9 +1,13 @@ -fun f(x: (String | None), y: U32): String => - match (x, y) - | (None, let u: U32) => "none" - | (let s: String, 2) => s + " two" - | (let s: String, 3) => s + " three" - | (let s: String, let u: U32) => s + " other integer" - else - "something else" - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f("one", 2)) + + fun f(x: (String | None), y: U32): String => + match (x, y) + | (None, let u: U32) => "none" + | (let s: String, 2) => s + " two" + | (let s: String, 3) => s + " three" + | (let s: String, let u: U32) => s + " other integer" + else + "something else" + end \ No newline at end of file diff --git a/code-samples/match-type-and-value.pony b/code-samples/match-type-and-value.pony index 1a4f01ad..a83b7c10 100644 --- a/code-samples/match-type-and-value.pony +++ b/code-samples/match-type-and-value.pony @@ -1,9 +1,14 @@ -fun f(x: (U32 | String | None)): String => - match x - | None => "none" - | 2 => "two" - | 3 => "three" - | "5" => "not four" - else - "something else" - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f(2)) + env.out.print(f(42)) + + fun f(x: (U32 | String | None)): String => + match x + | None => "none" + | 2 => "two" + | 3 => "three" + | "5" => "not four" + else + "something else" + end \ No newline at end of file diff --git a/code-samples/match-values.pony b/code-samples/match-values.pony index 12050157..7e9e2c7e 100644 --- a/code-samples/match-values.pony +++ b/code-samples/match-values.pony @@ -1,9 +1,14 @@ -fun f(x: U32): String => - match x - | 1 => "one" - | 2 => "two" - | 3 => "three" - | 5 => "not four" - else - "something else" - end \ No newline at end of file +actor Main + new create(env: Env) => + env.out.print(f(2)) + env.out.print(f(42)) + + fun f(x: U32): String => + match x + | 1 => "one" + | 2 => "two" + | 3 => "three" + | 5 => "not four" + else + "something else" + end \ No newline at end of file diff --git a/code-samples/methods-constructors.pony b/code-samples/methods-constructors.pony index 0bedcff0..638ea7d6 100644 --- a/code-samples/methods-constructors.pony +++ b/code-samples/methods-constructors.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + env.out.print("create: " + Foo.get_x().string()) + env.out.print("from_int: " + Foo.from_int(42).get_x().string()) + class Foo var _x: U32 @@ -5,4 +10,7 @@ class Foo _x = 0 new from_int(x: U32) => - _x = x \ No newline at end of file + _x = x + + fun get_x(): U32 => + _x \ No newline at end of file diff --git a/code-samples/methods-functions.pony b/code-samples/methods-functions.pony index 8909482e..2d5e9551 100644 --- a/code-samples/methods-functions.pony +++ b/code-samples/methods-functions.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + env.out.print("add: " + C.add(1, 2).string()) + env.out.print("nop: " + C.nop().string()) + class C fun add(x: U32, y: U32): U32 => x + y diff --git a/code-samples/object-literals-actor-literal.pony b/code-samples/object-literals-actor-literal.pony index d914ddf5..a5855f30 100644 --- a/code-samples/object-literals-actor-literal.pony +++ b/code-samples/object-literals-actor-literal.pony @@ -1,3 +1,7 @@ -object - be apply() => env.out.print("hi") -end \ No newline at end of file +actor Main + new create(env: Env) => + let lambda = + object + be apply() => env.out.print("hi") + end + lambda() \ No newline at end of file diff --git a/code-samples/object-literals-closing-over-values.pony b/code-samples/object-literals-closing-over-values.pony index 908c47c8..79e2b96a 100644 --- a/code-samples/object-literals-closing-over-values.pony +++ b/code-samples/object-literals-closing-over-values.pony @@ -5,4 +5,9 @@ class Foo object iso is Hashable fun apply(): String => str fun hash(): USize => str.hash() - end \ No newline at end of file + end + +actor Main + new create(env: Env) => + let x = "hello world" + env.out.print(x + ": " + Foo.foo(x).hash().string()) \ No newline at end of file diff --git a/code-samples/object-literals-fields-assignment.pony b/code-samples/object-literals-fields-assignment.pony index d83fd3db..5dbfd10f 100644 --- a/code-samples/object-literals-fields-assignment.pony +++ b/code-samples/object-literals-fields-assignment.pony @@ -6,4 +6,9 @@ class Foo let s: String = str fun apply(): String => s fun hash(): USize => s.hash() - end \ No newline at end of file + end + +actor Main + new create(env: Env) => + let x = "hello world" + env.out.print(x + ": " + Foo.foo(x).hash().string()) \ No newline at end of file diff --git a/code-samples/object-literals-lambda-as-explicit-object-literal.pony b/code-samples/object-literals-lambda-as-explicit-object-literal.pony index 069efd52..e58823e3 100644 --- a/code-samples/object-literals-lambda-as-explicit-object-literal.pony +++ b/code-samples/object-literals-lambda-as-explicit-object-literal.pony @@ -1,3 +1,7 @@ -object - fun apply(s: String): String => "lambda: " + s -end \ No newline at end of file +actor Main + new create(env: Env) => + let lambda = + object + fun apply(s: String): String => "lambda: " + s + end + env.out.print(lambda("hello world")) \ No newline at end of file diff --git a/code-samples/object-literals-lambda-capture-and-rename-values.pony b/code-samples/object-literals-lambda-capture-and-rename-values.pony index ea8bd637..9cc80dbb 100644 --- a/code-samples/object-literals-lambda-capture-and-rename-values.pony +++ b/code-samples/object-literals-lambda-capture-and-rename-values.pony @@ -1,2 +1,10 @@ +actor Main new create(env: Env) => - foo({(s: String)(myenv = env) => myenv.out.print(s) }) \ No newline at end of file + Foo(env) + +class Foo + new create(env: Env) => + foo({(s: String)(myenv = env) => myenv.out.print(s) }) + + fun foo(f: {(String)}) => + f("Hello World") \ No newline at end of file diff --git a/code-samples/object-literals-lambda-capture-values.pony b/code-samples/object-literals-lambda-capture-values.pony index 86e5734d..34bfea8e 100644 --- a/code-samples/object-literals-lambda-capture-values.pony +++ b/code-samples/object-literals-lambda-capture-values.pony @@ -1,3 +1,7 @@ +actor Main + new create(env: Env) => + Foo(env) + class Foo new create(env: Env) => foo({(s: String)(env) => env.out.print(s) }) diff --git a/code-samples/object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony b/code-samples/object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony index b318098e..2ba1e315 100644 --- a/code-samples/object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony +++ b/code-samples/object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony @@ -1,3 +1,7 @@ -object iso - fun apply(s: String): String => "lambda: " + s -end \ No newline at end of file +actor Main + new create(env: Env) => + let lambda = + object iso + fun apply(s: String): String => "lambda: " + s + end + env.out.print(lambda("hello world")) \ No newline at end of file diff --git a/code-samples/object-literals-lambda-with-reference-capability.pony b/code-samples/object-literals-lambda-with-reference-capability.pony index 96f7d281..39223ab9 100644 --- a/code-samples/object-literals-lambda-with-reference-capability.pony +++ b/code-samples/object-literals-lambda-with-reference-capability.pony @@ -1 +1,5 @@ -{(s: String): String => "lambda: " + s } iso \ No newline at end of file +actor Main + new create(env: Env) => + let lambda = + {(s: String): String => "lambda: " + s } iso + env.out.print(lambda("hello world")) \ No newline at end of file diff --git a/code-samples/object-literals-lambda.pony b/code-samples/object-literals-lambda.pony index 7d74078f..15eb308a 100644 --- a/code-samples/object-literals-lambda.pony +++ b/code-samples/object-literals-lambda.pony @@ -1 +1,5 @@ -{(s: String): String => "lambda: " + s } \ No newline at end of file +actor Main + new create(env: Env) => + let lambda = + {(s: String): String => "lambda: " + s } + env.out.print(lambda("hello world")) \ No newline at end of file diff --git a/code-samples/object-literals-object-literal-with-interface.pony b/code-samples/object-literals-object-literal-with-interface.pony index 1a27f264..97088678 100644 --- a/code-samples/object-literals-object-literal-with-interface.pony +++ b/code-samples/object-literals-object-literal-with-interface.pony @@ -1,4 +1,10 @@ -object is Hashable - fun apply(): String => "hi" - fun hash(): USize => this().hash() -end \ No newline at end of file +use "collections" + +actor Main + new create(env: Env) => + let sayHi = + object is Hashable + fun apply(): String => "hi" + fun hash(): USize => this().hash() + end + env.out.print(sayHi() + ": " + sayHi.hash().string()) \ No newline at end of file diff --git a/code-samples/object-literals-object-literal.pony b/code-samples/object-literals-object-literal.pony index 602c3eab..c3abaf41 100644 --- a/code-samples/object-literals-object-literal.pony +++ b/code-samples/object-literals-object-literal.pony @@ -1,3 +1,7 @@ -object - fun apply(): String => "hi" -end \ No newline at end of file +actor Main + new create(env: Env) => + let sayHi = + object + fun apply(): String => "hi" + end + env.out.print(sayHi()) \ No newline at end of file diff --git a/code-samples/object-literals-reference-capability.pony b/code-samples/object-literals-reference-capability.pony index 99522c1e..0a39a8e7 100644 --- a/code-samples/object-literals-reference-capability.pony +++ b/code-samples/object-literals-reference-capability.pony @@ -6,4 +6,9 @@ class Foo let s: String = str fun apply(): String => s fun hash(): USize => s.hash() - end \ No newline at end of file + end + +actor Main + new create(env: Env) => + let x = "hello world" + env.out.print(x + ": " + Foo.foo(x).hash().string()) \ No newline at end of file diff --git a/code-samples/operators-add.pony b/code-samples/operators-add.pony index b577cac8..f090b5da 100644 --- a/code-samples/operators-add.pony +++ b/code-samples/operators-add.pony @@ -1,3 +1,10 @@ +actor Main + new create(env: Env) => + var x = Pair(1, 2) + var y = Pair(3, 4) + var z = x + y + env.out.print(z.string()) + // Define a suitable type class Pair var _x: U32 = 0 @@ -10,6 +17,9 @@ class Pair // Define a + function fun add(other: Pair): Pair => Pair(_x + other._x, _y + other._y) + + fun string(): String => + "(" + _x.string() + ", " + _y.string() + ")" // Now let's use it class Foo diff --git a/code-samples/operators-precedence-infix-and-unary-operators-without-parentheses.pony b/code-samples/operators-precedence-infix-and-unary-operators-without-parentheses.pony index f338bc68..e7ea5f48 100644 --- a/code-samples/operators-precedence-infix-and-unary-operators-without-parentheses.pony +++ b/code-samples/operators-precedence-infix-and-unary-operators-without-parentheses.pony @@ -1 +1,3 @@ -1 + 2 * -3 // Compilation failed. \ No newline at end of file +actor Main + new create(env: Env) => + 1 + 2 * -3 // Compilation failed. \ No newline at end of file diff --git a/code-samples/operators-precedence-without-parentheses.pony b/code-samples/operators-precedence-without-parentheses.pony index 6d6b2bf8..f84c4c74 100644 --- a/code-samples/operators-precedence-without-parentheses.pony +++ b/code-samples/operators-precedence-without-parentheses.pony @@ -1 +1,3 @@ -1 + 2 * 3 // Compilation failed. \ No newline at end of file +actor Main + new create(env: Env) => + 1 + 2 * 3 // Compilation failed. \ No newline at end of file diff --git a/code-samples/ponycheck-ponytest.pony b/code-samples/ponycheck-ponytest.pony deleted file mode 100644 index 961a19ae..00000000 --- a/code-samples/ponycheck-ponytest.pony +++ /dev/null @@ -1,9 +0,0 @@ -use "pony_test" -use "pony_check" - -actor Main is TestList - new create(env: Env) => - PonyTest(env, this) - - fun tag tests(test: PonyTest) => - test(Property1UnitTest[String](_MyFirstProperty)) \ No newline at end of file diff --git a/code-samples/ponycheck-usage.pony b/code-samples/ponycheck-usage.pony index abb56168..455fd35e 100644 --- a/code-samples/ponycheck-usage.pony +++ b/code-samples/ponycheck-usage.pony @@ -1,4 +1,5 @@ use "pony_test" +use "pony_check" class _MyFirstProperty is Property1[String] fun name(): String => @@ -8,4 +9,11 @@ class _MyFirstProperty is Property1[String] Generators.ascii() fun property(arg1: String, ph: PropertyHelper) => - ph.assert_eq[String](arg1, arg1) \ No newline at end of file + ph.assert_eq[String](arg1, arg1) + +actor Main is TestList + new create(env: Env) => + PonyTest(env, this) + + fun tag tests(test: PonyTest) => + test(Property1UnitTest[String](_MyFirstProperty)) \ No newline at end of file diff --git a/code-samples/recovering-capabilities-string-append.pony b/code-samples/recovering-capabilities-string-append.pony index 7fd53cbf..c5b0bf56 100644 --- a/code-samples/recovering-capabilities-string-append.pony +++ b/code-samples/recovering-capabilities-string-append.pony @@ -1,2 +1,5 @@ -let s = recover String end -s.append("hi") \ No newline at end of file +actor Main + new create(env: Env) => + let s = recover String end + s.append("hi") + env.out.print(consume s) \ No newline at end of file diff --git a/code-samples/recovering-capabilities-with-explicit-reference-capability.pony b/code-samples/recovering-capabilities-with-explicit-reference-capability.pony index 7a72b9b9..4adabeac 100644 --- a/code-samples/recovering-capabilities-with-explicit-reference-capability.pony +++ b/code-samples/recovering-capabilities-with-explicit-reference-capability.pony @@ -1 +1,6 @@ -let key = recover val line.substring(0, i).>strip() end \ No newline at end of file +actor Main + new create(env: Env) => + let line = "Lorem ipsum" + let i: ISize = 5 + let key = recover val line.substring(0, i).>strip() end + env.out.print("key: " + key) \ No newline at end of file diff --git a/code-samples/recursion.pony b/code-samples/recursion.pony index d2e92ce9..e0a0de48 100644 --- a/code-samples/recursion.pony +++ b/code-samples/recursion.pony @@ -1,13 +1,18 @@ -fun recursive_factorial(x: U32): U32 => - if x == 0 then - 1 - else - x * recursive_factorial(x - 1) - end +actor Main + new create(env: Env) => + env.out.print(recursive_factorial(42).string()) + env.out.print(tail_recursive_factorial(42, 24).string()) -fun tail_recursive_factorial(x: U32, y: U32): U32 => - if x == 0 then - y - else - tail_recursive_factorial(x - 1, x * y) - end \ No newline at end of file + fun recursive_factorial(x: U32): U32 => + if x == 0 then + 1 + else + x * recursive_factorial(x - 1) + end + + fun tail_recursive_factorial(x: U32, y: U32): U32 => + if x == 0 then + y + else + tail_recursive_factorial(x - 1, x * y) + end \ No newline at end of file diff --git a/code-samples/sugar-update-additional-parameters.pony b/code-samples/sugar-update-additional-parameters.pony index d638542f..f9ef90cc 100644 --- a/code-samples/sugar-update-additional-parameters.pony +++ b/code-samples/sugar-update-additional-parameters.pony @@ -1,3 +1,28 @@ -foo1(2, 3) = x -foo2() = x -foo3(37, "Hello", 3.5 where a = 2, b = 3) = x \ No newline at end of file +class Foo + var _x: (U32|F32) + + new create(x: U32) => + _x = x + + fun ref update(x: U32 = 0, y: (String|U32) = "", z: F32 = 0.0, value: U32, b: U32 = 0, a: U32 = 0) => + _x = (value * x).f32() + (a * b).f32() + z + match y + | let u: U32 => _x = _x.f32() + u.f32() + end + + fun get_value(): (U32|F32) => + _x + +actor Main + new create(env: Env) => + let foo1 = Foo(5) + let foo2 = Foo(5) + let foo3 = Foo(5) + let x: U32 = 10 + env.out.print("foo = " + foo1.get_value().string()) + foo1(2, 3) = x + foo2() = x + foo3(37, "Hello", 3.5 where a = 2, b = 3) = x + env.out.print("foo1 = " + foo1.get_value().string()) + env.out.print("foo2 = " + foo2.get_value().string()) + env.out.print("foo3 = " + foo3.get_value().string()) \ No newline at end of file diff --git a/code-samples/sugar-update-explicit.pony b/code-samples/sugar-update-explicit.pony index 4c25764c..2332422d 100644 --- a/code-samples/sugar-update-explicit.pony +++ b/code-samples/sugar-update-explicit.pony @@ -1 +1,19 @@ -foo.update(37 where value = x) \ No newline at end of file +class Foo + var _x: U32 = 0 + + new create(x: U32) => + update(x, 2) + + fun ref update(x: U32, value: U32) => + _x = value * x + + fun get_value(): U32 => + _x + +actor Main + new create(env: Env) => + let foo = Foo(5) + let x: U32 = 10 + env.out.print("foo = " + foo.get_value().string()) + foo.update(37 where value = x) + env.out.print("foo = " + foo.get_value().string()) \ No newline at end of file diff --git a/code-samples/sugar-update-implicit.pony b/code-samples/sugar-update-implicit.pony index 5e1c6311..52db1eea 100644 --- a/code-samples/sugar-update-implicit.pony +++ b/code-samples/sugar-update-implicit.pony @@ -1 +1,19 @@ -foo(37) = x \ No newline at end of file +class Foo + var _x: U32 = 0 + + new create(x: U32) => + update(x, 2) + + fun ref update(x: U32, value: U32) => + _x = value * x + + fun get_value(): U32 => + _x + +actor Main + new create(env: Env) => + let foo = Foo(5) + let x: U32 = 10 + env.out.print("foo = " + foo.get_value().string()) + foo(37) = x + env.out.print("foo = " + foo.get_value().string()) \ No newline at end of file diff --git a/code-samples/traits-and-interfaces-multiple-traits.pony b/code-samples/traits-and-interfaces-multiple-traits.pony index 88b000ba..1547fb62 100644 --- a/code-samples/traits-and-interfaces-multiple-traits.pony +++ b/code-samples/traits-and-interfaces-multiple-traits.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + let bob: Bob = Bob + env.out.print("Their name is \"" + bob.name() + "\" and they are " + (if bob.hair() then "bald" else "not bald" end)) + trait Named fun name(): String => "Bob" diff --git a/code-samples/traits-and-interfaces-nested-traits.pony b/code-samples/traits-and-interfaces-nested-traits.pony index 332cb4be..1f00a1fe 100644 --- a/code-samples/traits-and-interfaces-nested-traits.pony +++ b/code-samples/traits-and-interfaces-nested-traits.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + let bob: Bob = Bob + env.out.print("Their name is \"" + bob.name() + "\" and they are " + (if bob.hair() then "bald" else "not bald" end)) + trait Named fun name(): String => "Bob" diff --git a/code-samples/traits-and-interfaces-nominal-and-structural-subtyping.pony b/code-samples/traits-and-interfaces-nominal-and-structural-subtyping.pony index da7a2655..df867aac 100644 --- a/code-samples/traits-and-interfaces-nominal-and-structural-subtyping.pony +++ b/code-samples/traits-and-interfaces-nominal-and-structural-subtyping.pony @@ -1,3 +1,10 @@ +actor Main + new create(env: Env) => + let bob: Bob = Bob + let larry: Larry = Larry + env.out.print("Their name is \"" + bob.name() + "\"") + env.out.print("Their name is \"" + larry.name() + "\"") + interface HasName fun name(): String => "Bob" diff --git a/code-samples/traits-and-interfaces-nominal-subtyping-in-pony.pony b/code-samples/traits-and-interfaces-nominal-subtyping-in-pony.pony index e1972c2b..e364af7e 100644 --- a/code-samples/traits-and-interfaces-nominal-subtyping-in-pony.pony +++ b/code-samples/traits-and-interfaces-nominal-subtyping-in-pony.pony @@ -1,2 +1,7 @@ +actor Main + new create(env: Env) => + let larry: Larry = Larry + env.out.print("Their name is \"" + larry.name() + "\"") + class Larry fun name(): String => "Larry" \ No newline at end of file diff --git a/code-samples/traits-and-interfaces-open-world-typing.pony b/code-samples/traits-and-interfaces-open-world-typing.pony index c25cd0d7..3745207f 100644 --- a/code-samples/traits-and-interfaces-open-world-typing.pony +++ b/code-samples/traits-and-interfaces-open-world-typing.pony @@ -1,3 +1,22 @@ +actor Main + new create(env: Env) => + let compactor: Compactor = Compactor(2) + let a = [ as U64: + 1 + 2 + ] + env.out.print("size: " + a.size().string() + ", space: " + a.space().string()) + compactor.try_compacting(a) + env.out.print("size: " + a.size().string() + ", space: " + a.space().string()) + let b = [ as U64: + 1 + 2 + 3 + ] + env.out.print("size: " + b.size().string() + ", space: " + b.space().string()) + compactor.try_compacting(b) + env.out.print("size: " + b.size().string() + ", space: " + b.space().string()) + interface Compactable fun ref compact() fun size(): USize diff --git a/code-samples/traits-and-interfaces-trait.pony b/code-samples/traits-and-interfaces-trait.pony index 0237adbe..e848f934 100644 --- a/code-samples/traits-and-interfaces-trait.pony +++ b/code-samples/traits-and-interfaces-trait.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + let bob: Bob = Bob + env.out.print("Their name is \"" + bob.name() + "\"") + trait Named fun name(): String => "Bob" diff --git a/code-samples/type-aliases-complex-types-interface.pony b/code-samples/type-aliases-complex-types-interface.pony index d0c24dd7..b0089bcd 100644 --- a/code-samples/type-aliases-complex-types-interface.pony +++ b/code-samples/type-aliases-complex-types-interface.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + let bob: Person = Bob + env.out.print(bob.name() + ", aged " + bob.age().string() + ", feels \"" + bob.feeling() + "\"") + interface HasName fun name(): String @@ -7,4 +12,9 @@ interface HasAge interface HasFeelings fun feeling(): String -type Person is (HasName & HasAge & HasFeelings) \ No newline at end of file +type Person is (HasName & HasAge & HasFeelings) + +class Bob is Person + fun name(): String => "Bob" + fun age(): U32 => 42 + fun feeling(): String => "Great!" \ No newline at end of file diff --git a/code-samples/type-aliases-complex-types-trait.pony b/code-samples/type-aliases-complex-types-trait.pony index d0a2e5d4..3e8c5a07 100644 --- a/code-samples/type-aliases-complex-types-trait.pony +++ b/code-samples/type-aliases-complex-types-trait.pony @@ -1,3 +1,8 @@ +actor Main + new create(env: Env) => + let bob: Person = Bob + env.out.print(bob.name() + ", aged " + bob.age().string() + ", feels \"" + bob.feeling() + "\"") + trait HasName fun name(): String => "Bob" @@ -7,4 +12,6 @@ trait HasAge trait HasFeelings fun feeling(): String => "Great!" -type Person is (HasName & HasAge & HasFeelings) \ No newline at end of file +type Person is (HasName & HasAge & HasFeelings) + +class Bob is Person \ No newline at end of file diff --git a/code-samples/type-aliases-enumerations-apply.pony b/code-samples/type-aliases-enumerations-apply.pony index 96190412..8d4e8578 100644 --- a/code-samples/type-aliases-enumerations-apply.pony +++ b/code-samples/type-aliases-enumerations-apply.pony @@ -1,5 +1,23 @@ +use "format" +use "collections/persistent" + +actor Main + new create(env: Env) => + let colorMap = Map[U32, String].concat([ + (0xFF0000FF, "red") + (0x00FF00FF, "green") + (0x0000FFFF, "blue") + ].values()) + for colour in ColourList().values() do + env.out.print(colorMap.get_or_else(colour(), "color") + ": #" + Format.int[U32](colour(), FormatHexBare)) + end + primitive Red fun apply(): U32 => 0xFF0000FF primitive Green fun apply(): U32 => 0x00FF00FF primitive Blue fun apply(): U32 => 0x0000FFFF -type Colour is (Red | Blue | Green) \ No newline at end of file +type Colour is (Red | Blue | Green) + +primitive ColourList + fun apply(): Array[Colour] => + [Red; Green; Blue] \ No newline at end of file diff --git a/code-samples/variables-fields-constructor-assignment.pony b/code-samples/variables-fields-constructor-assignment.pony index 88263d91..6cfd9967 100644 --- a/code-samples/variables-fields-constructor-assignment.pony +++ b/code-samples/variables-fields-constructor-assignment.pony @@ -1,7 +1,14 @@ +actor Main + new create(env: Env) => + let wombat = Wombat(5) + env.out.print(wombat.name + " has a hunger level of " + wombat.get_hunger().string()) + class Wombat let name: String var _hunger_level: U32 new create(hunger: U32) => name = "Fantastibat" - _hunger_level = hunger \ No newline at end of file + _hunger_level = hunger + + fun get_hunger(): U32 => _hunger_level \ No newline at end of file diff --git a/code-samples/variables-fields-definition-assignment.pony b/code-samples/variables-fields-definition-assignment.pony index b9c7fc18..55c781a1 100644 --- a/code-samples/variables-fields-definition-assignment.pony +++ b/code-samples/variables-fields-definition-assignment.pony @@ -1,3 +1,10 @@ +actor Main + new create(env: Env) => + let wombat = Wombat + env.out.print(wombat.name + " has a hunger level of " + wombat.hunger().string()) + class Wombat let name: String = "Fantastibat" - var _hunger_level: U32 = 0 \ No newline at end of file + var _hunger_level: U32 = 0 + + fun hunger(): U32 => _hunger_level \ No newline at end of file diff --git a/code-samples/variables-fields-let-reassignment.pony b/code-samples/variables-fields-let-reassignment.pony index 4771bc4d..b13d3229 100644 --- a/code-samples/variables-fields-let-reassignment.pony +++ b/code-samples/variables-fields-let-reassignment.pony @@ -1,3 +1,7 @@ +actor Main + new create(env: Env) => + let wombat = Wombat("Fantastibat", 5) + class Wombat let name: String var _hunger_level: U64 diff --git a/code-samples/variables-let-reassignment.pony b/code-samples/variables-let-reassignment.pony index 46d96247..53bba625 100644 --- a/code-samples/variables-let-reassignment.pony +++ b/code-samples/variables-let-reassignment.pony @@ -1,3 +1,5 @@ -let x: U32 = 3 // Ok -let y: U32 // Error, can't declare a let local without assigning to it -y = 6 // Error, can't reassign to a let local \ No newline at end of file +actor Main + new create(env: Env) => + let x: U32 = 3 // Ok + let y: U32 // Error, can't declare a let local without assigning to it + y = 6 // Error, can't reassign to a let local \ No newline at end of file diff --git a/code-samples/variables-scope.pony b/code-samples/variables-scope.pony index 2b27bbbb..659a259e 100644 --- a/code-samples/variables-scope.pony +++ b/code-samples/variables-scope.pony @@ -1,6 +1,11 @@ -if a > b then - var x = "a is bigger" - env.out.print(x) // OK -end +actor Main + new create(env: Env) => + let a = 2 + let b = 1 -env.out.print(x) // Illegal \ No newline at end of file + if a > b then + var x = "a is bigger" + env.out.print(x) // OK + end + + env.out.print(x) // Illegal \ No newline at end of file diff --git a/code-samples/variables-var-vs-let.pony b/code-samples/variables-var-vs-let.pony index 285cc055..47480f45 100644 --- a/code-samples/variables-var-vs-let.pony +++ b/code-samples/variables-var-vs-let.pony @@ -1,4 +1,6 @@ -var x: U32 = 3 -let y: U32 = 4 -x = 5 // OK -y = 6 // Error, y is let \ No newline at end of file +actor Main + new create(env: Env) => + var x: U32 = 3 + let y: U32 = 4 + x = 5 // OK + y = 6 // Error, y is let \ No newline at end of file diff --git a/docs/appendices/annotations.md b/docs/appendices/annotations.md index d30175be..4d002e6e 100644 --- a/docs/appendices/annotations.md +++ b/docs/appendices/annotations.md @@ -51,7 +51,7 @@ The following annotations are recognised by the Pony compiler. Note that the Pon Recognised on a `struct` declaration. Removes padding in the associated `struct`, making it ABI-compatible with a packed C structure with compatible members (declared with the `__attribute__((packed))` extension or the `#pragma pack` preprocessor directive in many C compilers). ```pony ---8<-- "appendices-annotations-packed-annotation.pony" +--8<-- "appendices-annotations-packed-annotation.pony:1:3" ``` #### `likely` and `unlikely` @@ -59,7 +59,12 @@ Recognised on a `struct` declaration. Removes padding in the associated `struct` Recognised on a conditional expression (`if`, `while`, `until` and `|` (as a pattern matching case)). Gives optimisation hints to the compiler on the likelihood of a given conditional expression. ```pony ---8<-- "appendices-annotations-likely-and-unlikely-annotations.pony" +--8<-- +appendices-annotations-likely-and-unlikely-annotations.pony:12:14 +appendices-annotations-likely-and-unlikely-annotations.pony:17:19 +appendices-annotations-likely-and-unlikely-annotations.pony:22:24 +appendices-annotations-likely-and-unlikely-annotations.pony:27:30 +--8<-- ``` ### `nodoc` @@ -85,7 +90,7 @@ The above code won't compile because you could supply `Empty ref`. Doing so resu By adding `nosupertype` to the definition of `Empty`, we declare that `Empty` is not a subtype of `Any` and thereby allow the code to compile as there is no longer an unsafe match. ```pony ---8<-- "appendices-annotations-empty-with-nosupertype-annotation.pony" +--8<-- "appendices-annotations-empty-with-nosupertype-annotation.pony:1:7" ``` `nosupertype` is particularly valuable when constructing generic classes like collections that need a marker class to describe "lack of an item". diff --git a/docs/appendices/examples.md b/docs/appendices/examples.md index 437d0979..1a451653 100644 --- a/docs/appendices/examples.md +++ b/docs/appendices/examples.md @@ -5,13 +5,13 @@ Small _how do I_ examples for Pony. These will eventually find another home. Unt ## Enumeration with values ```pony ---8<-- "appendices-examples-enumeration-with-values.pony" +--8<-- "appendices-examples-enumeration-with-values.pony:4:5" ``` ## Enumeration with values with namespace ```pony ---8<-- "appendices-examples-enumeration-with-values-with-namespace.pony" +--8<-- "appendices-examples-enumeration-with-values-with-namespace.pony:4:6" ``` ## Enumeration which can be iterated @@ -69,7 +69,7 @@ Some assertions you can make with `TestHelper` are Single values can be separated by semicolon or newline. ```pony ---8<-- "appendices-examples-create-arrays-with-values.pony" +--8<-- "appendices-examples-create-arrays-with-values.pony:5:9" ``` ## How to modify a lexically captured variable in a closure diff --git a/docs/appendices/whitespace.md b/docs/appendices/whitespace.md index e909b432..e7bec4b0 100644 --- a/docs/appendices/whitespace.md +++ b/docs/appendices/whitespace.md @@ -19,13 +19,13 @@ There are three exceptions: That stuff may seem a little esoteric right now, but we'll explain it all later. The `-` part should make sense though. ```pony ---8<-- "appendices-whitespace-subtract-b-from-a.pony" +--8<-- "appendices-whitespace-subtract-b-from-a.pony:14:14" ``` That means "subtract b from a". ```pony ---8<-- "appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony" +--8<-- "appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony:14:15" ``` That means "first do a, then, in a new expression, do a unary negation of b". diff --git a/docs/c-ffi/c-abi.md b/docs/c-ffi/c-abi.md index cd9fc54a..04b59c77 100644 --- a/docs/c-ffi/c-abi.md +++ b/docs/c-ffi/c-abi.md @@ -9,7 +9,7 @@ Writing your own C library for use by Pony is almost as easy as using existing l Let's look at a complete example of a C function we may wish to provide to Pony. Let's consider a pure Pony implementation of a [Jump Consistent Hash](https://arxiv.org/abs/1406.2294): ```pony ---8<-- "c-abi-jump-consistent-hashing.pony" +--8<-- "c-abi-jump-consistent-hashing.pony:5:18" ``` Let's say we wish to compare the pure Pony performance to an existing C function with the following header: diff --git a/docs/c-ffi/calling-c.md b/docs/c-ffi/calling-c.md index a0e90b08..e2d41f87 100644 --- a/docs/c-ffi/calling-c.md +++ b/docs/c-ffi/calling-c.md @@ -61,13 +61,19 @@ The above example would also work if we used `Pointer[None]` for all the pointer Like we mentioned above, Pony classes and structs correspond directly to pointers to the class or struct in C. This means that in most cases we won't need to use the `addressof` operator when passing struct types to C. For example, let's imagine we want to use the `writev` function from Pony on Linux: ```pony ---8<-- "calling-c-writev-struct.pony" +--8<-- +calling-c-writev-struct.pony:1:12 +calling-c-writev-struct.pony:15:19 +--8<-- ``` As you saw, a `IOVec` instance in Pony is equivalent to `struct iovec*`. In some cases, like the above example, it can be cumbersome to define a `struct` type in Pony if you only want to use it in a single place. You can also use a pointer to a tuple type as a shorthand for a struct: let's rework the above example: ```pony ---8<-- "calling-c-writev-tuple.pony" +--8<-- +calling-c-writev-tuple.pony:1:2 +calling-c-writev-tuple.pony:5:7 +--8<-- ``` In the example above, the type `Pointer[(Pointer[U8] tag, USize)] tag` is equivalent to the `IOVec` struct type we defined earlier. That is, _a struct type is equivalent to a pointer to a tuple type with the fields of the struct as elements, in the same order as the original struct type defined them_. @@ -79,7 +85,10 @@ In the example above, the type `Pointer[(Pointer[U8] tag, USize)] tag` is equiva A common pattern in C is to pass a struct pointer to a function, and that function will fill in various values in the struct. To do this in Pony, you make a `struct` and then use a `NullablePointer`, which denotes a possibly-null type: ```pony ---8<-- "calling-c-ioctl-struct.pony" +--8<-- +calling-c-ioctl-struct.pony:1:8 +calling-c-ioctl-struct.pony:11:15 +--8<-- ``` A `NullablePointer` type can only be used with `structs`, and is only intended for output parameters (like in the example above) or for return types from C. You don't need to use a `NullablePointer` if you are only passing a `struct` as a regular input parameter. @@ -87,7 +96,7 @@ A `NullablePointer` type can only be used with `structs`, and is only intended f If you are using a C function that returns a struct, remember, that the C function needs to return a pointer to the struct. The following in Pony should be read as **returns a pointer to struct `Rect`**: ```pony ---8<-- "calling-c-from-c-struct.pony" +--8<-- "calling-c-from-c-struct.pony:1:5" ``` As we saw earlier, you can also use a `Pointer[(U16, U16)]` as well. It is the equivalent to our `Rect`. @@ -141,7 +150,10 @@ When specifying a different return type for an FFI function, make sure that the Some C functions are variadic, that is, they can take a variable number of parameters. To interact with these functions, you should also specify that fact in the FFI signature: ```pony ---8<-- "calling-c-variadic-c-functions.pony" +--8<-- +calling-c-variadic-c-functions.pony:1:2 +calling-c-variadic-c-functions.pony:10:12 +--8<-- ``` In the example above, the compiler will type-check the first argument to `printf`, but will not be able to check any other argument, since it lacks the necessary type information. It is __very__ important that you use `...` in the FFI signature if the corresponding C function is variadic: if you don't, the compiler might generate a program that is incorrect or crash on some platforms while appearing to work correctly on others. diff --git a/docs/expressions/arithmetic.md b/docs/expressions/arithmetic.md index d666abb6..1c3bf826 100644 --- a/docs/expressions/arithmetic.md +++ b/docs/expressions/arithmetic.md @@ -104,7 +104,12 @@ Here is a full list of all available conversions for numeric types: If overflow or division by zero are cases that need to be avoided and performance is no critical priority, partial or checked arithmetic offer great safety during runtime. Partial arithmetic operators error on overflow/underflow and division by zero. Checked arithmetic methods return a tuple of the result of the operation and a `Boolean` indicating overflow or other exceptional behaviour. ```pony ---8<-- "arithmetic-partial-and-check-arithmetic.pony" +--8<-- +arithmetic-partial-and-check-arithmetic.pony:7:14 +arithmetic-partial-and-check-arithmetic.pony:16:20 +arithmetic-partial-and-check-arithmetic.pony:22:22 +arithmetic-partial-and-check-arithmetic.pony:24:26 +--8<-- ``` Partial as well as checked arithmetic comes with the burden of handling exceptions on every case and incurs some performance overhead, be warned. diff --git a/docs/expressions/as.md b/docs/expressions/as.md index 08838c91..8ca90207 100644 --- a/docs/expressions/as.md +++ b/docs/expressions/as.md @@ -19,7 +19,7 @@ Note that the type requested as the `as` argument must exist as a type of the ob In addition to using `as` with a union of disjoint types, we can also express an intersected type of the object, meaning the object has a type that the alias we have for the object is not directly related to the type we want to express. For example: ```pony ---8<-- "as-operator-unrelated-type.pony" +--8<-- "as-operator-unrelated-type.pony:1:10" ``` `as` can also be used to get a more specific type of an object from an alias to it that is an interface or a trait. Let's say, for example, that you have a library for doing things with furry, rodent-like creatures. It provides a `Critter` interface which programmers can then use to create specific types of critters. @@ -37,19 +37,19 @@ The programmer uses this library to create a `Wombat` and a `Capybara` class. Bu You can do the same with interfaces as well. In the example below, we have an Array of `Any` which is an interface where we want to try wash any entries that conform to the `Critter` interface. ```pony ---8<-- "as-operator-more-specific-interface-with-reference-capability.pony" +--8<-- "as-operator-more-specific-interface-with-reference-capability.pony:11:18" ``` Note, All the `as` examples above could be written using a `match` statement where a failure to match results in `error`. For example, our last example written to use `match` would be: ```pony ---8<-- "as-operator-match-statement-comparison.pony" +--8<-- "as-operator-match-statement-comparison.pony:11:23" ``` Thinking of the `as` keyword as "an attempt to match that will error if not matched" is a good mental model to have. If you don't care about handling the "not matched" case that causes an error when using `as`, you can rewrite an `as` to use match without an error like: ```pony ---8<-- "as-operator-match-statement-without-try.pony" +--8<-- "as-operator-match-statement-without-try.pony:11:19" ``` You can learn more about matching on type in the [captures section of the match documentation](/expressions/match.md#captures). diff --git a/docs/expressions/control-structures.md b/docs/expressions/control-structures.md index b79e4116..f103d8c3 100644 --- a/docs/expressions/control-structures.md +++ b/docs/expressions/control-structures.md @@ -7,7 +7,7 @@ To do real work in a program you have to be able to make decisions, iterate thro The simplest control structure is the good old `if`. It allows you to perform some action only when a condition is true. In Pony it looks like this: ```pony ---8<-- "control-structures-conditionals-if.pony" +--8<-- "control-structures-conditionals-if.pony:5:7" ``` __Can I use integers and pointers for the condition like I can in C?__ No. In Pony `if` conditions must have type `Bool`, i.e. they are always true or false. If you want to test whether a number `a` is not 0, then you need to explicitly say `a != 0`. This restriction removes a whole category of potential bugs from Pony programs. @@ -15,19 +15,19 @@ __Can I use integers and pointers for the condition like I can in C?__ No. In Po If you want some alternative code for when the condition fails just add an `else`: ```pony ---8<-- "control-structures-conditionals-if-else.pony" +--8<-- "control-structures-conditionals-if-else.pony:5:9" ``` Often you want to test more than one condition in one go, giving you more than two possible outcomes. You can nest `if` statements, but this quickly gets ugly: ```pony ---8<-- "control-structures-conditionals-nested-if-else.pony" +--8<-- "control-structures-conditionals-nested-if-else.pony:5:13" ``` As an alternative Pony provides the `elseif` keyword that combines an `else` and an `if`. This works the same as saying `else if` in other languages and you can have as many `elseif`s as you like for each `if`. ```pony ---8<-- "control-structures-conditionals-if-elseif-else.pony" +--8<-- "control-structures-conditionals-if-elseif-else.pony:5:11" ``` __Why can't I just say "else if" like I do in C? Why the extra keyword?__ The relationship between `if` and `else` in C, and other similar languages, is ambiguous. For example: @@ -52,7 +52,7 @@ In Pony control flow statements like this are all expressions that hand back a v This means you can use `if` directly in a calculation: ```pony ---8<-- "control-structures-conditionals-expressions.pony" +--8<-- "control-structures-conditionals-expressions.pony:5:5" ``` This will give __x__ a value of either 3 or 101, depending on the variable __lots__. @@ -60,13 +60,13 @@ This will give __x__ a value of either 3 or 101, depending on the variable __lot If the `then` and `else` branches of an `if` produce different types then the `if` produces a __union__ of the two. ```pony ---8<-- "control-structures-conditionals-expression-union-type.pony" +--8<-- "control-structures-conditionals-expression-union-type.pony:4:9" ``` __But what if my if doesn't have an else?__ Any `else` branch that doesn't exist gives an implicit `None`. ```pony ---8<-- "control-structures-conditionals-expression-implicit-none.pony" +--8<-- "control-structures-conditionals-expression-implicit-none.pony:4:7" ``` The same rules that apply to the value of an `if` expression applies to loops as well. Let's take a look at what a loop value would look like: @@ -102,7 +102,7 @@ Pony `while` loops are very similar to those in other languages. A condition exp Here's an example that prints out the numbers 1 to 10: ```pony ---8<-- "control-structures-loops-while.pony" +--8<-- "control-structures-loops-while.pony:3:8" ``` Just like `if` expressions, `while` is also an expression. The value returned is just the value of the expression inside the loop the last time we go round it. For this example that will be the value given by `count = count + 1` when count is incremented to 11. Since Pony assignments hand back the _old_ value our `while` loop will return 10. @@ -120,7 +120,7 @@ Sometimes you want to stop part-way through a loop and give up altogether. Pony Let's have an example. Suppose you want to go through a list of names, looking for either "Jack" or "Jill". If neither of those appear, you'll just take the last name you're given, and if you're not given any names at all, you'll use "Herbert". ```pony ---8<-- "control-structures-loops-while-break-else.pony" +--8<-- "control-structures-loops-while-break-else.pony:10:19" ``` So first we ask if there are any more names to get. If there are then we get a name and see if it's "Jack" or "Jill". If it is we're done and we break out of the loop, handing back the name we've found. If not we try again. @@ -150,7 +150,7 @@ The Pony `for` loop iterates over a collection of items using an iterator. On ea For example, to print out all the strings in an array: ```pony ---8<-- "control-structures-loops-for.pony" +--8<-- "control-structures-loops-for.pony:3:5" ``` Note the call to `values()` on the array — this is because the loop needs an iterator, not an array. @@ -166,7 +166,7 @@ where T is the type of the objects in the collection. You don't need to worry ab You can think of the above example as being equivalent to: ```pony ---8<-- "control-structures-loops-for-while-comparison.pony" +--8<-- "control-structures-loops-for-while-comparison.pony:4:8" ``` Note that the variable __name__ is declared _let_, so you cannot assign to the control variable within the loop. diff --git a/docs/expressions/errors.md b/docs/expressions/errors.md index 1676deea..c5185805 100644 --- a/docs/expressions/errors.md +++ b/docs/expressions/errors.md @@ -9,7 +9,7 @@ An error is raised with the command `error`. At any point, the code may decide t Error handlers are declared using the `try`-`else` syntax. ```pony ---8<-- "errors-try-else.pony" +--8<-- "errors-try-else.pony:9:15" ``` In the above code `callA()` will always be executed and so will `callB()`. If the result of `callB()` is true then we will proceed to `callC()` in the normal fashion and `callD()` will not then be executed. @@ -37,7 +37,7 @@ Pony does not require that all errors are handled immediately as in our previous For example, a somewhat contrived version of the factorial function that accepts a signed integer will error if given a negative input. It's only partially defined over its valid input type. ```pony ---8<-- "errors-partial-functions.pony" +--8<-- "errors-partial-functions.pony:16:22" ``` Everywhere that an error can be generated in Pony (an error command, a call to a partial function, or certain built-in language constructs) must appear within a `try` block or a function that is marked as partial. This is checked at compile time, ensuring that an error cannot escape handling and crash the program. @@ -57,7 +57,7 @@ Behaviours are also executed asynchronously and so cannot be partial for the sam In addition to an `else` error handler, a `try` command can have a `then` block. This is executed after the rest of the `try`, whether or not an error is raised or handled. Expanding our example from earlier: ```pony ---8<-- "errors-try-then.pony" +--8<-- "errors-try-then.pony:9:17" ``` The `callE()` will always be executed. If `callB()` returns true then the sequence executed is `callA()`, `callB()`, `callC()`, `callE()`. If `callB()` returns false then the sequence executed is `callA()`, `callB()`, `callD()`, `callE()`. diff --git a/docs/expressions/literals.md b/docs/expressions/literals.md index f220d34d..8dbee81b 100644 --- a/docs/expressions/literals.md +++ b/docs/expressions/literals.md @@ -37,7 +37,7 @@ It is possible to help the compiler determine the concrete type of the literal u Integer literals can be given as decimal, hexadecimal or binary: ```pony ---8<-- "literals-number-types.pony" +--8<-- "literals-number-types.pony:3:5" ``` Floating Point literals are expressed as standard floating point or scientific notation: @@ -53,7 +53,7 @@ Character literals are enclosed with single quotes (`'`). Character literals, unlike String literals, encode to a single numeric value. Usually this is a single byte, a `U8`. But they can be coerced to any integer type: ```pony ---8<-- "literals-character-literals.pony" +--8<-- "literals-character-literals.pony:3:5" ``` The following escape sequences are supported: @@ -97,7 +97,7 @@ String Literals contain the bytes that were read from their source code file. Th Consider the following example: ```pony ---8<-- "literals-string-literals-encoding.pony" +--8<-- "literals-string-literals-encoding.pony:3:3" ``` If the file containing this code is encoded as `UTF-8` the byte-value of `u_umlaut` will be: `\xc3\xbc`. If the file is encoded with *ISO-8559-1* (Latin-1) its value will be `\xfc`. @@ -115,7 +115,10 @@ For embedding multi-line text in string literals, there are triple quoted string When a single string literal is used several times in your Pony program, all of them will be converted to a single common instance. This means they will always be equal based on identity. ```pony ---8<-- "literals-string-literals-instances.pony" +--8<-- +literals-string-literals-instances.pony:3:6 +literals-string-literals-instances.pony:10:10 +--8<-- ``` ## Array Literals @@ -123,7 +126,7 @@ When a single string literal is used several times in your Pony program, all of Array literals are enclosed by square brackets. Array literal elements can be any kind of expressions. They are separated by semicolon or newline: ```pony ---8<-- "literals-array-literals.pony" +--8<-- "literals-array-literals.pony:3:7" ``` ### Type inference diff --git a/docs/expressions/match.md b/docs/expressions/match.md index fb9c188a..07750895 100644 --- a/docs/expressions/match.md +++ b/docs/expressions/match.md @@ -37,7 +37,7 @@ The compiler recognizes a match as exhaustive when the union of the types for al The simplest match expression just matches on value. ```pony ---8<-- "match-values.pony" +--8<-- "match-values.pony:6:14" ``` For value matching the pattern is simply the value we want to match to, just like a C switch statement. The case with the same value as the operand wins and we use its expression. @@ -53,7 +53,7 @@ The compiler calls the `eq()` function on the operand, passing the pattern as th Matching on value is fine if the match operand and case patterns have all the same type. However, match can cope with multiple different types. Each case pattern is first checked to see if it is the same type as the runtime type of the operand. Only then will the values be compared. ```pony ---8<-- "match-type-and-value.pony" +--8<-- "match-type-and-value.pony:6:14" ``` In many languages using runtime type information is very expensive and so it is generally avoided whenever possible. @@ -79,7 +79,7 @@ Sometimes you want to be able to match the type, for any value of that type. For Captures look just like variable declarations within the pattern. Like normal variables, they can be declared as var or let. If you're not going to reassign them within the case expression it is good practice to use let. ```pony ---8<-- "match-captures.pony" +--8<-- "match-captures.pony:6:13" ``` __Can I omit the type from a capture, like I can from a local variable?__ Unfortunately no. Since we match on type and value the compiler has to know what type the pattern is, so it can't be inferred. @@ -105,13 +105,13 @@ does not type check. If you want to match on more than one operand at once then you can simply use a tuple. Cases will only match if __all__ the tuple elements match. ```pony ---8<-- "match-tuples.pony" +--8<-- "match-tuples.pony:5:13" ``` __Do I have to specify all the elements in a tuple?__ No, you don't. Any tuple elements in a pattern can be marked as "don't care" by using an underscore ('_'). The first and fourth cases in our example don't actually care about the U32 element, so we can ignore it. ```pony ---8<-- "match-tuples-ignore-elements.pony" +--8<-- "match-tuples-ignore-elements.pony:5:13" ``` ## Guards @@ -123,5 +123,5 @@ Guards are introduced with the `if` keyword (_was `where` until 0.2.1_). A guard expression may use any captured variables from that case, which allows for handling ranges and complex functions. ```pony ---8<-- "match-guards.pony" +--8<-- "match-guards.pony:6:15" ``` diff --git a/docs/expressions/methods.md b/docs/expressions/methods.md index 2af9c590..f5cb3001 100644 --- a/docs/expressions/methods.md +++ b/docs/expressions/methods.md @@ -11,7 +11,7 @@ __Can I have some code outside of any methods like I do in Python?__ No. All Pon Pony functions are quite like functions (or methods) in other languages. They can have 0 or more parameters and 0 or 1 return values. If the return type is omitted then the function will have a return value of `None`. ```pony ---8<-- "methods-functions.pony" +--8<-- "methods-functions.pony:6:11" ``` The function parameters (if any) are specified in parentheses after the function name. Functions that don't take any parameters still need to have the parentheses. @@ -31,7 +31,7 @@ __Can I overload functions by argument type?__ No, you cannot have multiple meth Pony constructors are used to initialise newly created objects, as in many languages. However, unlike many languages, Pony constructors are named so you can have as many as you like, taking whatever parameters you like. By convention, the main constructor of each type (if there is such a thing for any given type) is called `create`. ```pony ---8<-- "methods-constructors.pony" +--8<-- "methods-constructors.pony:6:13" ``` The purpose of a constructor is to set up the internal state of the object being created. To ensure this is done constructors must initialise all the fields in the object being constructed. diff --git a/docs/expressions/object-literals.md b/docs/expressions/object-literals.md index eafe9d00..464b50b4 100644 --- a/docs/expressions/object-literals.md +++ b/docs/expressions/object-literals.md @@ -9,19 +9,19 @@ But Pony is statically typed, so an object literal also creates an anonymous typ It basically looks like any other type definition, but with some small differences. Here's a simple one: ```pony ---8<-- "object-literals-object-literal.pony" +--8<-- "object-literals-object-literal.pony:4:6" ``` Ok, that's pretty trivial. Let's extend it so that it explicitly provides an interface so that the compiler will make sure the anonymous type fulfills that interface. You can use the same notation to provide traits as well. ```pony ---8<-- "object-literals-object-literal-with-interface.pony" +--8<-- "object-literals-object-literal-with-interface.pony:6:9" ``` What we can't do is specify constructors in an object literal, because the literal _is_ the constructor. So how do we assign to fields? Well, we just assign to them. For example: ```pony ---8<-- "object-literals-fields-assignment.pony" +--8<-- "object-literals-fields-assignment.pony:1:9" ``` When we assign to a field in the constructor, we are _capturing_ from the lexical scope the object literal is in. Pretty fun stuff! It lets us have arbitrarily complex __closures__ that can even have multiple entry points (i.e. functions you can call on a closure). @@ -29,13 +29,13 @@ When we assign to a field in the constructor, we are _capturing_ from the lexica An object literal with fields is returned as a `ref` by default unless an explicit reference capability is declared by specifying the capability after the `object` keyword. For example, an object with sendable captured references can be declared as `iso` if needed: ```pony ---8<-- "object-literals-reference-capability.pony" +--8<-- "object-literals-reference-capability.pony:1:9" ``` We can also implicitly capture values from the lexical scope by using them in the object literal. Sometimes values that aren't local variables, aren't fields, and aren't parameters of a function are called _free variables_. By using them in a function, we are _closing over_ them - that is, capturing them. The code above could be written without the field `s`: ```pony ---8<-- "object-literals-closing-over-values.pony" +--8<-- "object-literals-closing-over-values.pony:1:8" ``` ## Lambdas @@ -43,37 +43,37 @@ We can also implicitly capture values from the lexical scope by using them in th Arbitrarily complex closures are nice, but sometimes we just want a simple closure. In Pony, you can use the lambdas for that. A lambda is written as a function (implicitly named `apply`) enclosed in curly brackets: ```pony ---8<-- "object-literals-lambda.pony" +--8<-- "object-literals-lambda.pony:5:5" ``` This produces the same code as: ```pony ---8<-- "object-literals-lambda-as-explicit-object-literal.pony" +--8<-- "object-literals-lambda-as-explicit-object-literal.pony:4:6" ``` The reference capability of the lambda object can be declared by appending it after the closing curly bracket: ```pony ---8<-- "object-literals-lambda-with-reference-capability.pony" +--8<-- "object-literals-lambda-with-reference-capability.pony:4:4" ``` This produces the same code as: ```pony ---8<-- "object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony" +--8<-- "object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony:4:6" ``` Lambdas can be used to capture from the lexical scope in the same way as object literals can assign from the lexical scope to a field. This is done by adding a second argument list after the parameters: ```pony ---8<-- "object-literals-lambda-capture-values.pony" +--8<-- "object-literals-lambda-capture-values.pony:5:10" ``` It's also possible to use a _capture list_ to create new names for things. A capture list is a second parenthesised list after the parameters: ```pony ---8<-- "object-literals-lambda-capture-and-rename-values.pony" +--8<-- "object-literals-lambda-capture-and-rename-values.pony:6:7" ``` The type of a lambda is also declared using curly brackets. Within the brackets, the function parameter types are specified within parentheses followed by an optional colon and return type. The example above uses `{(String)}` to be the type of a lambda function that takes a `String` as an argument and returns nothing. @@ -101,7 +101,7 @@ The above example also notes a subtle reality of captured references. At first g Normally, an object literal is an instance of an anonymous class. To make it an instance of an anonymous actor, just include one or more behaviours in the object literal definition. ```pony ---8<-- "object-literals-actor-literal.pony" +--8<-- "object-literals-actor-literal.pony:4:6" ``` An actor literal is always returned as a `tag`. diff --git a/docs/expressions/ops.md b/docs/expressions/ops.md index 287449b8..95d9f99f 100644 --- a/docs/expressions/ops.md +++ b/docs/expressions/ops.md @@ -25,7 +25,10 @@ When defining your own `add` function there is no restriction on the types of th Here's a full example for defining a type which allows the use of `+`. This is all you need: ```pony ---8<-- "operators-add.pony" +--8<-- +operators-add.pony:8:19 +operators-add.pony:23:29 +--8<-- ``` It is possible to overload infix operators to some degree using union types or f-bounded polymorphism, but this is beyond the scope of this tutorial. See the Pony standard library for further information. @@ -115,7 +118,7 @@ In Pony, unary operators always bind stronger than any infix operators: `not a = When using infix operators in complex expressions a key question is the __precedence__, i.e. which operator is evaluated first. Given this expression: ```pony ---8<-- "operators-precedence-without-parentheses.pony" +--8<-- "operators-precedence-without-parentheses.pony:3:3" ``` We will get a value of 9 if we evaluate the addition first and 7 if we evaluate the multiplication first. In mathematics, there are rules about the order in which to evaluate operators and most programming languages follow this approach. @@ -139,7 +142,7 @@ Repeated use of a single operator, however, is fine: Meanwhile, mixing unary and infix operators do not need additional parentheses as unary operators always bind more closely, so if our example above used a negative three: ```pony ---8<-- "operators-precedence-infix-and-unary-operators-without-parentheses.pony" +--8<-- "operators-precedence-infix-and-unary-operators-without-parentheses.pony:3:3" ``` We would still need parentheses to remove the ambiguity for our infix operators like we did above, but not for the unary arithmetic negative (`-`): diff --git a/docs/expressions/sugar.md b/docs/expressions/sugar.md index 3daf4d5e..b263cde8 100644 --- a/docs/expressions/sugar.md +++ b/docs/expressions/sugar.md @@ -87,13 +87,13 @@ The `update` sugar allows any class to use an assignment to accept data. Many la In any assignment where the left-hand side is a function call, Pony will translate this to a call to update, with the value from the right-hand side as an extra argument. So: ```pony ---8<-- "sugar-update-implicit.pony" +--8<-- "sugar-update-implicit.pony:18:18" ``` becomes: ```pony ---8<-- "sugar-update-explicit.pony" +--8<-- "sugar-update-explicit.pony:18:18" ``` The value from the right-hand side of the assignment is always passed to a parameter named `value`. Any object can allow this syntax simply by providing an appropriate function `update` with an argument `value`. @@ -101,7 +101,7 @@ The value from the right-hand side of the assignment is always passed to a param __Does my update function have to have a single parameter that takes an integer?__ No, you can define update to take whatever parameters you like, as long as there is one called `value`. The following are all fine: ```pony ---8<-- "sugar-update-additional-parameters.pony" +--8<-- "sugar-update-additional-parameters.pony:23:25" ``` __Does it matter where `value` appears in my parameter list?__ Whilst it doesn't strictly matter it is good practice to put `value` as the last parameter. That way all of the others can be specified by position. diff --git a/docs/expressions/variables.md b/docs/expressions/variables.md index 740083b3..1b109f6c 100644 --- a/docs/expressions/variables.md +++ b/docs/expressions/variables.md @@ -31,7 +31,7 @@ All local variable names start with a lowercase letter. If you want to you can e The chunk of code that a variable lives in is known as its __scope__. Exactly what its scope is depends on where it is defined. For example, the scope of a variable defined within the `then` expression of an `if` statement is that `then` expression. We haven't looked at `if` statements yet, but they're very similar to every other language. ```pony ---8<-- "variables-scope.pony" +--8<-- "variables-scope.pony:6:1" ``` Variables only exist from when they are defined until the end of the current scope. For our variable `x` this is the `end` at the end of the then expression: after that, it cannot be used. @@ -41,13 +41,13 @@ Variables only exist from when they are defined until the end of the current sco Local variables are declared with either a `var` or a `let`. Using `var` means the variable can be assigned and reassigned as many times as you like. Using `let` means the variable can only be assigned once. ```pony ---8<-- "variables-var-vs-let.pony" +--8<-- "variables-var-vs-let.pony:3:6" ``` Using `let` instead of `var` also means the variable has to be assigned immediately. ```pony ---8<-- "variables-let-reassignment.pony" +--8<-- "variables-let-reassignment.pony:3:5" ``` Note that a variable having been declared with `let` only restricts reassignment, and does not influence the mutability of the object it references. This is the job of reference capabilities, explained later in this tutorial. @@ -70,13 +70,13 @@ Just like local variables, fields can be `var` or `let`. Nevertheless, rules for In the example below, the initial value of the two fields of the class `Wombat` is assigned at the definition level: ```pony ---8<-- "variables-fields-definition-assignment.pony" +--8<-- "variables-fields-definition-assignment.pony:6:8" ``` Alternatively, these fields could be assigned in the constructor method: ```pony ---8<-- "variables-fields-constructor-assignment.pony" +--8<-- "variables-fields-constructor-assignment.pony:6:12" ``` If the assignment is not done at the definition level or in the constructor, an error is raised by the compiler. This is true for both `var` and `let` fields. @@ -92,7 +92,7 @@ We will see later in the Methods section that a class can have several construct As for variables, using `var` means a field can be assigned and reassigned as many times as you like in the class. Using `let` means the field can only be assigned once. ```pony ---8<-- "variables-fields-let-reassignment.pony" +--8<-- "variables-fields-let-reassignment.pony:5:17" ``` __Can field declarations appear after methods?__ No. If `var` or `let` keywords appear after a `fun` or `be` declaration, they will be treated as variables within the method body rather than fields within the type declaration. As a result, fields must appear prior to methods in the type declaration diff --git a/docs/generics/generics-and-reference-capabilities.md b/docs/generics/generics-and-reference-capabilities.md index fa7e634b..3b99cbfd 100644 --- a/docs/generics/generics-and-reference-capabilities.md +++ b/docs/generics/generics-and-reference-capabilities.md @@ -50,7 +50,13 @@ That compiles and runs, so `ref` is valid now. The real test though is `iso`. Le This fails to compile. The first error is: ```error ---8<-- "generics-and-reference-capabilities-foo-iso-error-message.txt" +main.pony:5:8: right side must be a subtype of left side + _c = c + ^ + Info: + main.pony:4:17: String iso! is not a subtype of String iso: iso! is not a subtype of iso + new create(c: String iso) => + ^ ``` The error is telling us that we are aliasing the `String iso` - The `!` in `iso!` means it is an alias of an existing `iso`. Looking at the code shows the problem: diff --git a/docs/generics/index.md b/docs/generics/index.md index 93799b00..5311af92 100644 --- a/docs/generics/index.md +++ b/docs/generics/index.md @@ -28,13 +28,17 @@ In this case, the name is `A`, the constraint is `Any` and the reference capabil The user of the class must provide a type when referencing the class name. This is done when creating it: ```pony ---8<-- "generics-generic-class-initialization.pony" +--8<-- +generics-foo-with-any-val.pony:13:13 +generics-foo-with-any-val.pony:18:18 +generics-foo-with-any-val.pony:21:21 +--8<-- ``` That tells the compiler what specific class to create, replacing `A` with the type provided. For example, a `Foo[String]` usage becomes equivalent to: ```pony ---8<-- "generics-foo-string.pony" +--8<-- "generics-foo-string.pony:1:9" ``` ### Type parameter defaults @@ -43,13 +47,13 @@ Sometimes the same parameter type is used over and over again, and it is tedious The class `Bar` expects its type parameter to be a `USize val` by default: ```pony ---8<-- "generics-type-parameter-defaults-definition.pony" +--8<-- "generics-type-parameter-defaults.pony:1:9" ``` Now, when the default type parameter is the desired one, it can simply be omitted. But it is still possible to be explicit or use a different type. ```pony ---8<-- "generics-type-parameter-defaults-initialization.pony" +--8<-- "generics-type-parameter-defaults.pony:13:15" ``` Note that we could simply write `class Bar[A: Any box = USize]` because `val` is the default reference capability of the `USize` type. diff --git a/docs/gotchas/divide-by-zero.md b/docs/gotchas/divide-by-zero.md index 2dd35729..a6ba648f 100644 --- a/docs/gotchas/divide-by-zero.md +++ b/docs/gotchas/divide-by-zero.md @@ -9,7 +9,7 @@ In math, divide by zero is undefined. There is no answer to that question as the In Pony, *integer division by zero results in zero*. That's right, ```pony ---8<-- "divide-by-zero.pony" +--8<-- "divide-by-zero.pony:3:3" ``` results in `0` being assigned to `x`. Baffling right? Well, yes and no. From a mathematical standpoint, it is very much baffling. From a practical standpoint, it is very much not. @@ -37,5 +37,5 @@ In conformance with IEEE 754, *floating point division by zero results in `inf` If you can assert that your denominator cannot be `0`, it is possible to use [Unsafe Division](/expressions/arithmetic.md#floating-point) to gain some performance: ```pony ---8<-- "divide-by-zero-floats.pony" +--8<-- "divide-by-zero-floats.pony:4:4" ``` diff --git a/docs/gotchas/recursion.md b/docs/gotchas/recursion.md index 7448e855..68e34d5a 100644 --- a/docs/gotchas/recursion.md +++ b/docs/gotchas/recursion.md @@ -5,7 +5,7 @@ Recursive functions in Pony can cause many problems. Every function call in a pr If you have a heavy recursive algorithm, you must take some precautions in your code to avoid stack overflows. Most recursive functions can be easily transformed into tail-recursive function which are less problematic. A tail-recursive function is a function in which the recursive call is the last instruction of the function. Here is an example with a factorial function: ```pony ---8<-- "recursion.pony" +--8<-- "recursion.pony:6:18" ``` The compiler can optimise a tail-recursive function to a loop, completely avoiding call stack growth. Note that this is an _optimisation_ which is only performed in release builds (i.e. builds without the `-d` flag passed to ponyc.) If you need to avoid stack growth in debug builds as well then you have to write your function as a loop manually. diff --git a/docs/object-capabilities/derived-authority.md b/docs/object-capabilities/derived-authority.md index 9a76e44a..afe2eff4 100644 --- a/docs/object-capabilities/derived-authority.md +++ b/docs/object-capabilities/derived-authority.md @@ -37,7 +37,7 @@ The first parameter of the `TCPConnection` constructor has the type `TCPConnectA Now imagine we don't trust the `Connect` actor, so we don't want to provide it with more authority than needed. For example, there is no point in granting it filesystem access, since it is supposed to do network things (specifically, TCP), not access the filesystem. Instead of passing the entire `AmbientAuth` (the root of all authority), we "downgrade" that to a `TCPConnectAuth` (the most restrictive authority in `net`), pass it to the `Connect` actor, and have that pass it to the `TCPConnection` constructor: ```pony ---8<-- "derived-authority-restrict-then-delegate-your-authority.pony" +--8<-- "derived-authority-restrict-then-delegate-your-authority.pony:16:22" ``` Now we are sure it cannot access the filesystem or listen on a TCP or UDP port. Pay close mind to the authority that code you are calling is asking for. Never give `AmbientAuth` to __any__ code you do not trust completely both now and in the future. You should always create the most specific authority and give the library that authority. If the library is asking for more authority than it needs, __do not use the library__. diff --git a/docs/reference-capabilities/aliasing.md b/docs/reference-capabilities/aliasing.md index 98f0dd85..83f118b0 100644 --- a/docs/reference-capabilities/aliasing.md +++ b/docs/reference-capabilities/aliasing.md @@ -11,7 +11,7 @@ In Pony, that works for some reference capabilities, but not all. The reason for this is that the `iso` reference capability denies other `iso` variables that point to the same object. That is, you can only have one `iso` variable pointing to any given object. The same goes for `trn`. ```pony ---8<-- "aliasing-multiple-references-to-an-iso-object.pony" +--8<-- "aliasing-multiple-references-to-an-iso-object.pony:5:6" ``` Here we have some function that gets passed an isolated Wombat. If we try to alias `a` by assigning it to `b`, we'll be breaking reference capability guarantees, so the compiler will stop us. Instead, we can only store aliases that are compatible with the original capability. @@ -19,13 +19,13 @@ Here we have some function that gets passed an isolated Wombat. If we try to ali __What can I alias an `iso` as?__ Since an `iso` says no other variable can be used by _any_ actor to read from or write to that object, we can only create aliases to an `iso` that can neither read nor write. Fortunately, we have a reference capability that does exactly that: `tag`. So we can do this and the compiler will be happy: ```pony ---8<-- "aliasing-iso-to-tag.pony" +--8<-- "aliasing-iso-to-tag.pony:5:6" ``` __What about aliasing `trn`?__ Since a `trn` says no other variable can be used by _any_ actor to write to that object, we need something that doesn't allow writing but also doesn't prevent our `trn` variable from writing. Fortunately, we have a reference capability that does that too: `box`. So we can do this and the compiler will be happy: ```pony ---8<-- "aliasing-trn-to-box.pony" +--8<-- "aliasing-trn-to-box.pony:5:6" ``` __What about aliasing other stuff?__ For both `iso` and `trn`, the guarantees require that aliases must give up on some ability (reading and writing for `iso`, writing for `trn`). For the other capabilities (`ref`, `val`, `box` and `tag`), aliases allow for the same operations, so such a reference can just be aliased as itself. diff --git a/docs/reference-capabilities/consume-and-destructive-read.md b/docs/reference-capabilities/consume-and-destructive-read.md index f5dd126a..8b525cff 100644 --- a/docs/reference-capabilities/consume-and-destructive-read.md +++ b/docs/reference-capabilities/consume-and-destructive-read.md @@ -9,13 +9,13 @@ Sometimes, you want to _move_ an object from one variable to another. In other w You can do this by using `consume`. When you `consume` a variable you take the value out of it, effectively leaving the variable empty. No code can read from that variable again until a new value is written to it. Consuming a local variable or a parameter allows you to move it to a new location, most importantly for `iso` and `trn`. ```pony ---8<-- "consume-and-destructive-read-consuming-a-variable.pony:1:2" +--8<-- "consume-and-destructive-read-consuming-a-variable.pony:5:6" ``` The compiler is happy with that because by consuming `a`, you've said the value can't be used again and the compiler will complain if you try to. ```pony ---8<-- "consume-and-destructive-read-consuming-a-variable.pony" +--8<-- "consume-and-destructive-read-consuming-a-variable-failure.pony:5:7" ``` Here's an example of that. When you try to assign `a` to `c`, the compiler will complain. diff --git a/docs/reference-capabilities/recovering-capabilities.md b/docs/reference-capabilities/recovering-capabilities.md index 842d1e11..80b09347 100644 --- a/docs/reference-capabilities/recovering-capabilities.md +++ b/docs/reference-capabilities/recovering-capabilities.md @@ -31,7 +31,7 @@ That's from `format/_FormatInt`. It creates a `String ref`, does a bunch of stuf You can also give an explicit reference capability: ```pony ---8<-- "recovering-capabilities-with-explicit-reference-capability.pony" +--8<-- "recovering-capabilities-with-explicit-reference-capability.pony:5:5" ``` That's from `net/http/_PayloadBuilder`. We get a substring of `line`, which is a `String iso^`, then we call strip on it, which returns itself. But since strip is a `ref` function, it returns itself as a `String ref^` - so we use a `recover val` to end up with a `String val`. @@ -55,7 +55,7 @@ Notice that this technique looks mostly at the call-site, rather than at the def This may sound a little complicated, but in practice, it means you can write code that treats an `iso` mostly like a `ref`, and the compiler will complain when it's wrong. For example: ```pony ---8<-- "recovering-capabilities-string-append.pony" +--8<-- "recovering-capabilities-string-append.pony:3:4" ``` Here, we create a `String iso` and then append some text to it. The append method takes a `ref` receiver and a `box` parameter. We can automatically recover the `iso` receiver since we pass a `val` parameter, so everything is fine. diff --git a/docs/testing/ponycheck.md b/docs/testing/ponycheck.md index fc01ec8f..8bcc7575 100644 --- a/docs/testing/ponycheck.md +++ b/docs/testing/ponycheck.md @@ -19,7 +19,7 @@ PonyCheck is heavily inspired by QuickCheck and other great property based testi Writing property based tests in PonyCheck is done by implementing the trait [`Property1`](https://stdlib.ponylang.io/pony_check-Property1). A [`Property1`](https://stdlib.ponylang.io/pony_check-Property1) needs to define a type parameter for the type of the input sample, a [`Generator`](https://stdlib.ponylang.io/pony_check-Generator) and a property function. Here is a minimal example: ```pony ---8<-- "ponycheck-usage.pony" +--8<-- "ponycheck-usage.pony:2:12" ``` A `Property1` needs a name for identification in test output. We created a `Generator` by using one of the many convenience factory methods and combinators defined in the [`Generators`](https://stdlib.ponylang.io/pony_check-Generators) primitive and we used [`PropertyHelper`](https://stdlib.ponylang.io/pony_check-PropertyHelper) to assert on a condition that should hold for all samples @@ -35,7 +35,10 @@ Below are two classic list reverse properties from the QuickCheck paper adapted PonyCheck properties need to be executed. The test runner for PonyCheck is [PonyTest](https://stdlib.ponylang.io/pony_test--index). To integrate [`Property1`](https://stdlib.ponylang.io/pony_check-Property1) into [PonyTest](https://stdlib.ponylang.io/pony_test--index), `Property1` needs to be wrapped inside a [`Property1UnitTest`](https://stdlib.ponylang.io/pony_check-Property1UnitTest) and passed to the PonyTest `apply` method as a regular PonyTest [`UnitTest`](https://stdlib.ponylang.io/pony_test-UnitTest): ```pony ---8<-- "ponycheck-ponytest.pony" +--8<-- +ponycheck-usage.pony:1:3 +ponycheck-usage.pony:14:19 +--8<-- ``` It is also possible to integrate any number of properties directly into one diff --git a/docs/types/classes.md b/docs/types/classes.md index be9f22dd..8a6dd00e 100644 --- a/docs/types/classes.md +++ b/docs/types/classes.md @@ -3,7 +3,7 @@ Just like other object-oriented languages, Pony has __classes__. A class is declared with the keyword `class`, and it has to have a name that starts with a capital letter, like this: ```pony ---8<-- "classes-wombat.pony:1:1" +--8<-- "classes-wombat.pony:9:9" ``` __Do all types start with a capital letter?__ Yes! And nothing else starts with a capital letter. So when you see a name in Pony code, you will instantly know whether it's a type or not. @@ -21,7 +21,7 @@ A class is composed of: These are just like fields in C structures or fields in classes in C++, C#, Java, Python, Ruby, or basically any language, really. There are three kinds of fields: `var`, `let`, and `embed` fields. A `var` field can be assigned to over and over again, but a `let` field is assigned to in the constructor and never again. Embed fields will be covered in more detail in the documentation on [variables](/expressions/variables.md). ```pony ---8<-- "classes-wombat.pony:1:3" +--8<-- "classes-wombat.pony:9:11" ``` Here, a `Wombat` has a `name`, which is a `String`, and a `_hunger_level`, which is a `U64` (an unsigned 64-bit integer). @@ -35,13 +35,13 @@ Pony constructors have names. Other than that, they are just like constructors i Constructors are introduced with the __new__ keyword. ```pony ---8<-- "classes-wombat-constructors.pony" +--8<-- "classes-wombat-constructors.pony:8:18" ``` Here, we have two constructors, one that creates a `Wombat` that isn't hungry, and another that creates a `Wombat` that might be hungry or might not. Unlike some other languages that differentiate between constructors with method overloading, Pony won't presume to know which alternate constructor to invoke based on the arity and type of your arguments. To choose a constructor, invoke it like a method with the `.` syntax: ```pony ---8<-- "classes-wombat-constructor-invocation.pony" +--8<-- "classes-wombat.pony:3:4" ``` __What's with the single quote thing, i.e. name'?__ You can use single quotes in parameter and local variable names. In mathematics, it's called a _prime_, and it's used to say "another one of these, but not the same one". Basically, it's just convenient. @@ -51,7 +51,7 @@ Every constructor has to set every field in an object. If it doesn't, the compil Sometimes it's convenient to set a field the same way for all constructors. ```pony ---8<-- "classes-wombat.pony:1:12" +--8<-- "classes-wombat.pony:9:20" ``` Here, every `Wombat` begins a little bit thirsty, regardless of which constructor is called. @@ -59,7 +59,7 @@ Here, every `Wombat` begins a little bit thirsty, regardless of which constructo ### Zero Argument Constructors ```pony ---8<-- "classes-zero-argument-constructors.pony" +--8<-- "classes-zero-argument-constructors.pony:9:16" ``` Here we have two classes, because the `Hawk` class defines no constructors, a default constructor with zero arguments called `create` is generated. The `Owl` defines its own constructor that sets the `_hunger_level`. @@ -67,7 +67,7 @@ Here we have two classes, because the `Hawk` class defines no constructors, a de When constructing instances of classes that have zero-argument constructors, they can be constructed with just the class name: ```pony ---8<-- "classes-zero-argument-constructors-invocation.pony" +--8<-- "classes-zero-argument-constructors.pony:5:7" ``` This is explained later, in more detail in the [sugar](/expressions/sugar.md) section. @@ -77,7 +77,7 @@ This is explained later, in more detail in the [sugar](/expressions/sugar.md) se Functions in Pony are like methods in Java, C#, C++, Ruby, Python, or pretty much any other object oriented language. They are introduced with the keyword `fun`. They can have parameters like constructors do, and they can also have a result type (if no result type is given, it defaults to `None`). ```pony ---8<-- "classes-wombat.pony" +--8<-- "classes-wombat.pony:9:24" ``` The first function, `hunger`, is pretty straight forward. It has a result type of `U64`, and it returns `_hunger_level`, which is a `U64`. The only thing a bit different here is that no `return` keyword is used. This is because the result of a function is the result of the last expression in the function, in this case, the value of `_hunger_level`. @@ -107,13 +107,13 @@ __Wait, seriously? The _old_ value?__ Yes. In Pony, assignment is an expression __...why?__ It's called a "destructive read", and it lets you do awesome things with a capabilities-secure type system. We'll talk about that later. For now, we'll just mention that you can also use it to implement a _swap_ operation. In most languages, to swap the values of `a` and `b` you need to do something like: ```pony ---8<-- "classes-swap-values.pony" +--8<-- "classes-swap-values.pony:6:8" ``` In Pony, you can just do: ```pony ---8<-- "classes-swap-values-sugar.pony" +--8<-- "classes-swap-values-sugar.pony:6:6" ``` ### Finalisers diff --git a/docs/types/traits-and-interfaces.md b/docs/types/traits-and-interfaces.md index a78baddd..26a45f9f 100644 --- a/docs/types/traits-and-interfaces.md +++ b/docs/types/traits-and-interfaces.md @@ -43,7 +43,7 @@ Both `trait` and `interface` can establish a relationship via nominal subtyping. The primary means of doing nominal subtyping in Pony is using __traits__. A __trait__ looks a bit like a __class__, but it uses the keyword `trait` and it can't have any fields. ```pony ---8<-- "traits-and-interfaces-trait.pony" +--8<-- "traits-and-interfaces-trait.pony:6:9" ``` Here, we have a trait `Named` that has a single function `name` that returns a String. It also provides a default implementation of `name` that returns the string literal "Bob". @@ -53,19 +53,19 @@ We also have a class `Bob` that says it `is Named`. This means `Bob` is in the ` Since `Bob` doesn't have its own `name` function, it uses the one from the trait. If the trait's function didn't have a default implementation, the compiler would complain that `Bob` had no implementation of `name`. ```pony ---8<-- "traits-and-interfaces-multiple-traits.pony" +--8<-- "traits-and-interfaces-multiple-traits.pony:6:12" ``` It is possible for a class to have relationships with multiple categories. In the above example, the class `Bob` _provides both Named and Bald_. ```pony ---8<-- "traits-and-interfaces-nested-traits.pony" +--8<-- "traits-and-interfaces-nested-traits.pony:6:12" ``` It is also possible to combine categories together. In the example above, all `Bald` classes are automatically `Named`. Consequently, the `Bob` class has access to both hair() and name() default implementation of their respective trait. One can think of the `Bald` category to be more specific than the `Named` one. ```pony ---8<-- "traits-and-interfaces-nominal-subtyping-in-pony.pony" +--8<-- "traits-and-interfaces-nominal-subtyping-in-pony.pony:6:7" ``` Here, we have a class `Larry` that has a `name` function with the same signature. But `Larry` does __not__ provide `Named`! @@ -75,7 +75,7 @@ __Wait, why not?__ Because `Larry` doesn't say it `is Named`. Remember, traits a You can also do nominal subtyping using the keyword `interface`. __Interfaces__ in Pony are primarily used for structural subtyping. Like traits, interfaces can also have default method implementations, but in order to use default method implementations, an interface must be used in a nominal fashion. For example: ```pony ---8<-- "traits-and-interfaces-nominal-and-structural-subtyping.pony" +--8<-- "traits-and-interfaces-nominal-and-structural-subtyping.pony:8:14" ``` Both `Bob` and `Larry` are in the category `HasName`. `Bob` because it has declared that it is a `HasName` and `Larry` because it is structurally a `HasName`. @@ -123,7 +123,7 @@ In our trait based example, we can add new colors at any time. With the type uni Interfaces can't be used for open world enumerations. If we defined `Color` as an interface: ```pony ---8<-- "traits-and-interfaces-open-world-interface.pony" +--8<-- "traits-and-interfaces-marker-methods.pony:1:1" ``` Then literally everything in Pony would be a `Color` because everything matches the `Color` interface. You can however, do something similar using "marker methods" with an interface: @@ -141,7 +141,7 @@ We've covered a couple ways that traits can be better than interfaces, let's clo Here's a contrived example: ```pony ---8<-- "traits-and-interfaces-open-world-typing.pony" +--8<-- "traits-and-interfaces-open-world-typing.pony:20:36" ``` The flexibility of `interface` has allowed us to define a type `Compactable` that we can use to allow our `Compactor` to accept a variety of data types including `Array`, `Map`, and `String` from the standard library. diff --git a/docs/types/type-aliases.md b/docs/types/type-aliases.md index 7b7fc9ad..97bab5a9 100644 --- a/docs/types/type-aliases.md +++ b/docs/types/type-aliases.md @@ -22,7 +22,7 @@ You can also declare constants like in C or Go like this, making use of `apply`, which can be omitted during call (will be discussed further in [Sugar](/expressions/sugar.md)), ```pony ---8<-- "type-aliases-enumerations-apply.pony" +--8<-- "type-aliases-enumerations-apply.pony:15:19" ``` or namespace them like this @@ -34,7 +34,11 @@ or namespace them like this You might also want to iterate over the enumeration items like this to print their value for debugging purposes ```pony ---8<-- "type-aliases-enumerations-iteration.pony" +--8<-- +type-aliases-enumerations-apply.pony:21:23 + +type-aliases-enumerations-apply.pony:11:13 +--8<-- ``` ## Complex types @@ -42,13 +46,13 @@ You might also want to iterate over the enumeration items like this to print the If a type is complicated, it can be nice to give it a mnemonic name. For example, if we want to say that a type must implement more than one interface, we could say: ```pony ---8<-- "type-aliases-complex-types-interface.pony" +--8<-- "type-aliases-complex-types-interface.pony:6:15" ``` This use of complex types applies to traits, not just interfaces: ```pony ---8<-- "type-aliases-complex-types-trait.pony" +--8<-- "type-aliases-complex-types-trait.pony:6:15" ``` There's another new concept here: the type has a `&` in it. This is similar to the `|` of a __union__ type: it means this is an __intersection__ type. That is, it's something that must be _all_ of `HasName`, `HasAge` _and_ `HasFeelings`. diff --git a/mkdocs.yml b/mkdocs.yml index caed243a..5ba20cb9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -25,6 +25,7 @@ markdown_extensions: - pymdownx.snippets: base_path: ['code-samples'] check_paths: true + dedent_subsections: true - smarty - toc: permalink: true