feat: alter classes syntax and add docs
This commit is contained in:
parent
62cc887797
commit
4dcfc72c58
@ -29,6 +29,15 @@ val surname = "Doe"
|
||||
val year_of_birth = 1984
|
||||
`} />
|
||||
|
||||
It's a compile error to attempt to modify it
|
||||
|
||||
<Code level={2} thpcode={`
|
||||
val surname = "Doe"
|
||||
surname = "Dane" // Error
|
||||
`} />
|
||||
|
||||
|
||||
|
||||
### Datatype annotation
|
||||
|
||||
Written after the `val` keyword but before the variable name.
|
||||
@ -64,6 +73,8 @@ Defined with `var`, followed by a variable name and a value.
|
||||
<Code level={2} thpcode={`
|
||||
var name = "John"
|
||||
var age = 32
|
||||
|
||||
age = 33
|
||||
`} />
|
||||
|
||||
### Datatype annotation
|
||||
|
@ -67,6 +67,21 @@ class Dog(String name)
|
||||
}
|
||||
`} />
|
||||
|
||||
This would be equilavent to the following PHP code:
|
||||
|
||||
```php
|
||||
class Dog {
|
||||
public string $name;
|
||||
private int $name_len;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->name = $name;
|
||||
$this->name_len = size($name);
|
||||
print("Dog created: $name");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@ -115,41 +130,33 @@ print(a2.name_length) //: 3
|
||||
|
||||
### Constructor that may fail
|
||||
|
||||
A constructor may only fail if there is code
|
||||
that can fail on the `init` block.
|
||||
|
||||
|
||||
|
||||
TBD
|
||||
|
||||
Proposal 1:
|
||||
|
||||
<Code thpcode={`
|
||||
class PrayingMantis(String name) -> self!Error
|
||||
`} />
|
||||
|
||||
Proposal 2:
|
||||
|
||||
<Code thpcode={`
|
||||
class PrayingMantis(String name)
|
||||
throws Error
|
||||
`} />
|
||||
|
||||
Proposal 3:
|
||||
|
||||
<Code thpcode={`
|
||||
class PrayingMantis(String name)
|
||||
{
|
||||
init -> self!Error
|
||||
init -> Error!
|
||||
{
|
||||
// Something that may fail
|
||||
// Initialization code that may fail
|
||||
}
|
||||
}
|
||||
`} />
|
||||
|
||||
|
||||
|
||||
## Destructor
|
||||
|
||||
The destructor in THP is the same as PHP.
|
||||
|
||||
<Code thpcode={`
|
||||
class Owl
|
||||
class Owl()
|
||||
{
|
||||
pub fun __destruct()
|
||||
{
|
||||
|
@ -15,11 +15,13 @@ Classes in THP are significantly different than PHP.
|
||||
A class is defined as follows:
|
||||
|
||||
<Code thpcode={`
|
||||
class Animal
|
||||
class Animal() {}
|
||||
`} />
|
||||
|
||||
The name of the class **MUST** begin with an uppercase letter.
|
||||
|
||||
Classes have a parameter list even if they have no parameters
|
||||
for consistency sake.
|
||||
|
||||
|
||||
## Instanciation
|
||||
@ -38,7 +40,7 @@ Properties are declared with `var`/`val` inside a block.
|
||||
They **must** explicitly declare their datatype.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
// This is an error. Properties must declare their datatype,
|
||||
// even if the compiler can infer it.
|
||||
@ -55,7 +57,7 @@ class Person
|
||||
**Properties are private by default**, but can be made public with `pub`.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
// Properties are private by default
|
||||
val String name = "John Doe"
|
||||
@ -86,7 +88,7 @@ in the Constructor page.
|
||||
Methods are declared with `fun`, as regular functions.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
fun greet()
|
||||
{
|
||||
@ -98,7 +100,7 @@ class Person
|
||||
**Methods are private by default**, and are made public with `pub`.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
// This method is private
|
||||
fun private_greet()
|
||||
@ -123,7 +125,7 @@ in THP a method cannot have the same name as a property and viceversa.
|
||||
Doing so is a compile error.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
String name = "Rose"
|
||||
|
||||
@ -141,7 +143,7 @@ THP uses the dollar sign `$` as this inside classes.
|
||||
It is **required** when using a class property/method.
|
||||
|
||||
<Code thpcode={`
|
||||
class Person
|
||||
class Person()
|
||||
{
|
||||
val String name = "Jane Doe"
|
||||
|
||||
@ -168,7 +170,7 @@ class Animal(var String name)
|
||||
{
|
||||
pub fun set_name(String new_name)
|
||||
{
|
||||
$name = new_name // Error: Cannot mutate $
|
||||
$name = new_name // Error: Cannot mutate $name
|
||||
}
|
||||
}
|
||||
`} />
|
||||
@ -189,21 +191,3 @@ var michi = Animal("Michifu")
|
||||
michi.set_name("Garfield")
|
||||
`} />
|
||||
|
||||
## Class constructor that may return an error
|
||||
|
||||
Working theory:
|
||||
|
||||
<Code thpcode={`
|
||||
class Fish(
|
||||
val String name,
|
||||
var Int lives = 9,
|
||||
)
|
||||
extends Animal(name)
|
||||
throws Error
|
||||
|
||||
val fish_result = Fish("bubble") // fish_result will be a \`Result[Fish,Error]\`
|
||||
val fish = try fish_result
|
||||
`} />
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ import Code from "../../../components/Code.astro"
|
||||
|
||||
# Inheritance
|
||||
|
||||
|
||||
A class inherits from another using the `extends` keyword.
|
||||
|
||||
<Code thpcode={`
|
||||
// Base class
|
||||
@ -20,7 +20,34 @@ class Animal(var String name)
|
||||
|
||||
// Child class
|
||||
class Cat(String name, Int lives)
|
||||
extends Animal(name)
|
||||
extends Animal(name) {}
|
||||
|
||||
Cat("Michi", 9).say_name()
|
||||
`} />
|
||||
|
||||
The call to the parent constructor is done right there, after
|
||||
the parent class name.
|
||||
|
||||
<Code thpcode={`
|
||||
class Dog(String name)
|
||||
extends Animal(name) {}
|
||||
// |----|
|
||||
// This is the call to the parent constructor
|
||||
`} />
|
||||
|
||||
You must always call super, even if the parent doesn't
|
||||
define any parameters:
|
||||
|
||||
<Code thpcode={`
|
||||
class Parent() {}
|
||||
|
||||
class Child()
|
||||
extends Parent() {}
|
||||
`} />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,10 @@ import Code from "../../../components/Code.astro"
|
||||
|
||||
# Arrays
|
||||
|
||||
Use square brackets as usual.
|
||||
Arrays in THP use exclusively square brackets.
|
||||
|
||||
More importantly, Arrays and Maps are different.
|
||||
Arrays only store values of a single datatype.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -16,7 +19,7 @@ val apple = fruits[0]
|
||||
|
||||
print(apple) // apple
|
||||
|
||||
|
||||
// To mutate an array, you need to declare it as var
|
||||
var numbers = [0, 1, 2, 3]
|
||||
|
||||
numbers[3] = 5
|
||||
|
@ -35,6 +35,8 @@ val result = if condition { value1 } else { value2 }
|
||||
|
||||
## Check for datatypes
|
||||
|
||||
TBD
|
||||
|
||||
<Code thpcode={`
|
||||
if variable is Datatype
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ import Code from "../../../components/Code.astro"
|
||||
# Higher Order functions
|
||||
|
||||
|
||||
## Function as parameter
|
||||
## Function as parameters
|
||||
|
||||
<Code thpcode={`
|
||||
fun map[A, B](Array[A] input, (A) -> (B) function) -> Array[B]
|
||||
|
@ -9,18 +9,48 @@ import Code from "../../../components/Code.astro"
|
||||
|
||||
## Anonymous function
|
||||
|
||||
An anonymous function is declared with `fn`.
|
||||
Other than not having a name, it can declare parameter
|
||||
and return types.
|
||||
|
||||
<Code thpcode={`
|
||||
fun(Int x, Int y) -> Int {
|
||||
fn(Int x, Int y) -> Int {
|
||||
x + y
|
||||
}
|
||||
`} />
|
||||
|
||||
Anonymous function can omit declaring those types as well:
|
||||
|
||||
<Code thpcode={`
|
||||
numbers.map(fun(x) {
|
||||
x * 2
|
||||
})
|
||||
`} />
|
||||
|
||||
|
||||
## Anonymous function short form
|
||||
|
||||
If you need an anonymous function that returns a single
|
||||
expression you can write it like this:
|
||||
|
||||
<Code thpcode={`
|
||||
fun(x, y) = x + y
|
||||
`} />
|
||||
|
||||
It uses an equal `=` instead of an arrow. It can contain
|
||||
only a single expression.
|
||||
|
||||
This is common when declaring functions that immediately
|
||||
return a map.
|
||||
|
||||
<Code thpcode={`
|
||||
fn(value) = .{
|
||||
value
|
||||
}
|
||||
`} />
|
||||
|
||||
|
||||
|
||||
|
||||
## Closure types
|
||||
|
||||
|
@ -41,10 +41,11 @@ Placing a `mut` before the type makes the parameter a mutable
|
||||
reference. Mutable methods can be used, and the original
|
||||
data **can** be mutated.
|
||||
|
||||
The caller *must* also use `mut`.
|
||||
The caller must define the value as `var`, and when calling
|
||||
must use `mut`.
|
||||
|
||||
<Code thpcode={`
|
||||
val numbers = Array(0, 1, 2, 3)
|
||||
var numbers = Array(0, 1, 2, 3)
|
||||
|
||||
push_25(mut numbers) // Pass \`numbers\` as reference.
|
||||
|
||||
@ -64,6 +65,8 @@ fun add_25(clone Array[Int] numbers) {
|
||||
Using the `clone` keyword before the type creates a mutable copy
|
||||
of the parameter (CoW). The original data will **not** be mutated.
|
||||
|
||||
The caller must also use `clone` when calling the function.
|
||||
|
||||
|
||||
<Code thpcode={`
|
||||
val numbers = Array(1, 2, 3, 4)
|
||||
|
Loading…
Reference in New Issue
Block a user