433 lines
10 KiB
Markdown
433 lines
10 KiB
Markdown
---
|
|
Title: G Examples & Tutorials
|
|
Prev: Memory Management
|
|
Next:
|
|
---
|
|
|
|
## Appendix G: Examples & Tutorials
|
|
|
|
### G.1 Tutorial: First Steps
|
|
|
|
**Hello World**:
|
|
```
|
|
"Hello, World!" print
|
|
```
|
|
|
|
**Basic Arithmetic**:
|
|
```
|
|
// Simple calculations
|
|
3 4 + // => 7
|
|
10 3 - // => 7
|
|
5 6 * // => 30
|
|
20 4 / // => 5
|
|
|
|
// Chaining operations
|
|
2 3 + 4 * // => 20 (addition happens first due to postfix order)
|
|
|
|
// Using the stack
|
|
10 dup * // => 100 (duplicate 10, then multiply)
|
|
```
|
|
|
|
**Simple Functions**:
|
|
```
|
|
// Square function
|
|
(Number -- Number) { dup * } ::square fn
|
|
5 square // => 25
|
|
|
|
// Absolute value
|
|
(Number -- Number) {
|
|
dup 0 >
|
|
{ } // If positive, do nothing
|
|
{ 0 swap - } // If negative, negate
|
|
if
|
|
} ::abs fn
|
|
|
|
-5 abs // => 5
|
|
```
|
|
|
|
**Stack Manipulation Practice**:
|
|
```
|
|
// Basic stack operations
|
|
5 dup // => 5 5
|
|
5 10 swap // => 10 5
|
|
5 10 over // => 5 10 5
|
|
1 2 3 rot // => 2 3 1
|
|
|
|
// More complex example - swap two items below top
|
|
// Stack: a b c
|
|
// Want: b a c
|
|
rot rot // First rot: b c a, Second rot: c a b... wait, that's wrong!
|
|
|
|
// Better approach:
|
|
// Stack: a b c
|
|
swap rot rot // swap: a c b, rot: c b a, rot: b a c (correct!)
|
|
```
|
|
|
|
### G.2 Tutorial: Working with Traits
|
|
|
|
**Implementing a Trait for a Custom Type**:
|
|
|
|
```
|
|
// Step 1: Define a struct
|
|
(Number Number --) { x: y: } ::Point struct
|
|
|
|
// Step 2: Implement Addable trait
|
|
::Addable {
|
|
// Add two points
|
|
(Self Self -- Self) {
|
|
over ::x get over ::x get + // Add x coordinates
|
|
swap ::y get swap ::y get + // Add y coordinates
|
|
Point // Construct new point
|
|
} +:
|
|
|
|
// Subtract two points
|
|
(Self Self -- Self) {
|
|
over ::x get over ::x get - // Subtract x coordinates
|
|
swap ::y get swap ::y get - // Subtract y coordinates
|
|
Point // Construct new point
|
|
} -:
|
|
} ::Point impl
|
|
|
|
// Step 3: Use it
|
|
3.0 4.0 Point // First point
|
|
1.0 2.0 Point // Second point
|
|
+ // => Point with x=4.0, y=6.0
|
|
```
|
|
|
|
**Using Trait Bounds**:
|
|
|
|
```
|
|
// Function that works with any Addable type
|
|
(Addable Addable Addable -- Addable) {
|
|
+ + // Add all three
|
|
} ::sum_three fn
|
|
|
|
// Works with numbers
|
|
1 2 3 sum_three // => 6
|
|
|
|
// Works with Points
|
|
1.0 2.0 Point
|
|
3.0 4.0 Point
|
|
5.0 6.0 Point
|
|
sum_three // => Point(9.0, 12.0)
|
|
```
|
|
|
|
**Understanding Standard Traits**:
|
|
|
|
```
|
|
// Number trait combines many operations
|
|
(Number Number -- Number) {
|
|
dup * swap dup * + // a² + b²
|
|
} ::pythagorean fn
|
|
|
|
3.0 4.0 pythagorean // => 25.0
|
|
|
|
// This works because Number inherits from:
|
|
// - Addable (for +)
|
|
// - Multiplyable (for *)
|
|
// - Comparable (for comparisons)
|
|
// - And more...
|
|
```
|
|
|
|
### G.3 Tutorial: Generic Programming
|
|
|
|
**Writing Generic Functions**:
|
|
|
|
```
|
|
// Generic identity - works with any type
|
|
(T -- T) { } ::identity fn
|
|
|
|
5 identity // => 5
|
|
"hello" identity // => "hello"
|
|
|
|
// Generic swap function
|
|
(T U -- U T) { swap } ::generic_swap fn
|
|
|
|
// Constrained generic - requires Comparable
|
|
(Comparable Comparable -- Comparable) {
|
|
over over >
|
|
{ } // First is larger, do nothing
|
|
{ swap } // Second is larger, swap them
|
|
if
|
|
drop // Drop the smaller value
|
|
} ::max fn
|
|
|
|
5 10 max // => 10
|
|
10 5 max // => 10
|
|
```
|
|
|
|
**Generic Data Structures**:
|
|
|
|
```
|
|
// Define a generic Pair
|
|
(T U --) { first: second: } ::Pair<T U> struct
|
|
|
|
// Use with different types
|
|
5 "hello" Pair // Pair<i64, String>
|
|
3.14 true Pair // Pair<f64, bool>
|
|
|
|
// Access fields
|
|
dup ::first get // Get first element
|
|
::second get // Get second element
|
|
|
|
// Generic Option (already defined in standard library)
|
|
(T --) { Some(T) None } ::Option<T> union
|
|
|
|
42 Option::Some // Option<i64>::Some
|
|
Option::None // Option<T>::None
|
|
```
|
|
|
|
**Trait Constraints in Generics**:
|
|
|
|
```
|
|
// This function requires the type to be Multiplyable
|
|
(T:Multiplyable -- T) {
|
|
dup *
|
|
} ::square_generic fn
|
|
|
|
// Works with any Multiplyable type
|
|
5 square_generic // => 25
|
|
3.14 square_generic // => 9.8596
|
|
|
|
// Multiple constraints using composite traits
|
|
(Number -- Number) {
|
|
dup 0 >
|
|
{ }
|
|
{ 0 swap - }
|
|
if
|
|
} ::abs_generic fn
|
|
```
|
|
|
|
### G.4 Complete Examples
|
|
|
|
#### G.4.1 Trait Implementation Example
|
|
|
|
```
|
|
// Define a trait for drawable objects
|
|
{
|
|
(Self -- ) draw:
|
|
} ::Drawable trait
|
|
|
|
// Define a Rectangle struct
|
|
(Number Number --) { width: height: } ::Rectangle struct
|
|
|
|
// Implement Drawable for Rectangle
|
|
::Drawable {
|
|
(Self -- ) {
|
|
"Drawing rectangle:" print
|
|
dup ::width get "Width: " swap concat print
|
|
::height get "Height: " swap concat print
|
|
} draw:
|
|
} ::Rectangle impl
|
|
|
|
// Use it
|
|
10.0 20.0 Rectangle draw
|
|
// Output:
|
|
// Drawing rectangle:
|
|
// Width: 10.0
|
|
// Height: 20.0
|
|
```
|
|
|
|
#### G.4.2 Trait Inheritance Example
|
|
|
|
```
|
|
// Define base traits
|
|
{
|
|
(Self Self -- Self) +:
|
|
(Self Self -- Self) -:
|
|
} ::Addable trait
|
|
|
|
{
|
|
(Self Self -- Self) *:
|
|
(Self Self -- Self) /:
|
|
} ::Multiplyable trait
|
|
|
|
// Composite trait inheriting from both
|
|
[ ::Addable ::Multiplyable ] ::BasicMath inher
|
|
{ } ::BasicMath trait
|
|
|
|
// Now any type implementing BasicMath must support +, -, *, /
|
|
// And functions can require BasicMath as a constraint
|
|
(BasicMath BasicMath -- BasicMath) {
|
|
over over * swap dup * + // (a * b) + (b * b)
|
|
} ::weird_math fn
|
|
|
|
3 4 weird_math // => 28
|
|
```
|
|
|
|
#### G.4.3 Logarithm Usage
|
|
|
|
```
|
|
// Calculate log base 10
|
|
100 log print // => 2.0
|
|
1000 log print // => 3.0
|
|
|
|
// Calculate natural logarithm
|
|
2.718 ln print // => ~1.0
|
|
7.389 ln print // => ~2.0
|
|
|
|
// Calculate with custom base
|
|
8 2 logb print // => 3.0 (2³ = 8)
|
|
27 3 logb print // => 3.0 (3³ = 27)
|
|
|
|
// Combine with other operations
|
|
10 3 ^ log print // => 3.0 (log of 1000)
|
|
|
|
// Logarithm laws verification
|
|
// log(a*b) = log(a) + log(b)
|
|
10 100 * log // log(1000) = 3.0
|
|
10 log 100 log + // log(10) + log(100) = 1.0 + 2.0 = 3.0
|
|
```
|
|
|
|
#### G.4.4 Factorial
|
|
|
|
```
|
|
(Number -- Number) {
|
|
dup 1 <=
|
|
{ drop 1 } // Base case: 0! = 1! = 1
|
|
{ dup 1 - factorial * } // Recursive case: n! = n * (n-1)!
|
|
if
|
|
} ::factorial fn
|
|
|
|
5 factorial print // => 120
|
|
10 factorial print // => 3628800
|
|
|
|
// Iterative version (more efficient)
|
|
(Number -- Number) {
|
|
1 swap // Start with accumulator = 1
|
|
1 swap // Start counter at 1
|
|
{ // While counter <= n
|
|
dup 3 pick <=
|
|
}
|
|
{ // Body: multiply accumulator by counter
|
|
2 pick over * // acc * counter
|
|
3 roll drop // Drop old accumulator
|
|
swap 1 + swap // Increment counter
|
|
}
|
|
while
|
|
drop // Drop counter
|
|
swap drop // Drop original n
|
|
} ::factorial_iter fn
|
|
|
|
5 factorial_iter print // => 120
|
|
```
|
|
|
|
#### G.4.5 FizzBuzz
|
|
|
|
```
|
|
(Number -- ) {
|
|
dup 15 % 0 ==
|
|
{ drop "FizzBuzz" print }
|
|
{
|
|
dup 3 % 0 ==
|
|
{ drop "Fizz" print }
|
|
{
|
|
dup 5 % 0 ==
|
|
{ drop "Buzz" print }
|
|
{ print }
|
|
if
|
|
}
|
|
if
|
|
}
|
|
if
|
|
} ::fizzbuzz fn
|
|
|
|
// Print FizzBuzz for 1 to 100
|
|
1 100 { fizzbuzz } for
|
|
```
|
|
|
|
#### G.4.6 Using Roll
|
|
|
|
```
|
|
// Roll rotates the top n items, times times
|
|
// Stack: 1 2 3 4 5
|
|
|
|
// Rotate top 3 items once
|
|
3 1 roll // Stack: 1 2 4 5 3
|
|
|
|
// Start fresh: 1 2 3 4 5
|
|
// Rotate top 3 items twice
|
|
3 2 roll // Stack: 1 2 5 3 4
|
|
|
|
// Start fresh: 1 2 3 4 5
|
|
// Rotate all 5 items once
|
|
5 1 roll // Stack: 2 3 4 5 1
|
|
|
|
// Start fresh: 1 2 3 4 5
|
|
// Rotate top 4 items three times
|
|
4 3 roll // Stack: 1 4 5 2 3
|
|
|
|
// Practical use: bring nth item to top
|
|
// Stack: a b c d e
|
|
// Want to bring 'b' (index 3) to top
|
|
4 3 roll // Rotates top 4 three times: a c d e b
|
|
|
|
// Or use pick for non-destructive copy
|
|
// Stack: a b c d e
|
|
3 pick // Stack: a b c d e b (copied from index 3)
|
|
```
|
|
|
|
#### G.4.7 Array Processing
|
|
|
|
```
|
|
// Sum of squares of even numbers from 1 to 10
|
|
[1 2 3 4 5 6 7 8 9 10]
|
|
{ 2 % 0 == } filter // Keep even: [2 4 6 8 10]
|
|
{ dup * } map // Square each: [4 16 36 64 100]
|
|
0 { + } reduce // Sum: 220
|
|
print
|
|
|
|
// Find maximum in array
|
|
[5 2 9 1 7 6]
|
|
dup 0 at // Start with first element
|
|
{
|
|
over over >
|
|
{ swap } // If current > max, swap
|
|
{ } // Otherwise keep max
|
|
if
|
|
drop // Drop the smaller value
|
|
} reduce
|
|
print // => 9
|
|
|
|
// Average of array
|
|
[10 20 30 40 50]
|
|
dup 0 { + } reduce // Sum: 150
|
|
swap length // Length: 5
|
|
/ // Average: 30
|
|
print
|
|
```
|
|
|
|
#### G.4.8 Identifier Literals in Practice
|
|
|
|
```
|
|
// Identifier literals are used in struct/trait definitions
|
|
// and field access
|
|
|
|
// Defining a struct requires ::StructName identifier literal
|
|
(Number Number --) { x: y: } ::Point struct
|
|
|
|
// Field access requires ::field_name identifier literal
|
|
3.0 4.0 Point
|
|
dup ::x get print // Prints: 3.0
|
|
::y get print // Prints: 4.0
|
|
|
|
// Dynamic field access (advanced)
|
|
"x" :: // Convert string to identifier
|
|
// (This would require string-to-identifier conversion, which
|
|
// may be a future feature)
|
|
|
|
// Traits use identifier literals
|
|
{ (Self -- ) draw: } ::Drawable trait
|
|
|
|
// Implementations use identifier literals
|
|
::Drawable { ... } ::Rectangle impl
|
|
|
|
// Identifier literals are NOT used inside trait/impl bodies
|
|
// (those are method names)
|
|
{
|
|
(Self -- ) { "Drawing" print } draw: // "draw:" is method name
|
|
} ::Drawable trait
|
|
```
|
|
|
|
---
|