Skip to content

Commit

Permalink
Make "control structures" runnable
Browse files Browse the repository at this point in the history
  • Loading branch information
shaedrich authored May 24, 2024
1 parent 24fe11e commit 8306f56
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
var x: (String | None) =
if friendly then
"Hello"
end
actor Main
new create(env: Env) =>
let friendly = false
var x: (String | None) =
if friendly then
"Hello"
end
env.out.print(x.string())
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
var x: (String | Bool) =
if friendly then
"Hello"
else
false
end
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())
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
x = 1 + if lots then 100 else 2 end
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))
14 changes: 9 additions & 5 deletions code-samples/control-structures-conditionals-if-else.pony
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
if a > b then
env.out.print("a is bigger")
else
env.out.print("a is not bigger")
end
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
18 changes: 11 additions & 7 deletions code-samples/control-structures-conditionals-if-elseif-else.pony
Original file line number Diff line number Diff line change
@@ -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
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
10 changes: 7 additions & 3 deletions code-samples/control-structures-conditionals-if.pony
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
if a > b then
env.out.print("a is bigger")
end
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
22 changes: 13 additions & 9 deletions code-samples/control-structures-conditionals-nested-if-else.pony
Original file line number Diff line number Diff line change
@@ -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
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
14 changes: 9 additions & 5 deletions code-samples/control-structures-loops-for-while-comparison.pony
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
let iterator = ["Bob"; "Fred"; "Sarah"].values()
while iterator.has_next() do
let name = iterator.next()?
env.out.print(name)
end
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
8 changes: 5 additions & 3 deletions code-samples/control-structures-loops-for.pony
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
for name in ["Bob"; "Fred"; "Sarah"].values() do
env.out.print(name)
end
actor Main
new create(env: Env) =>
for name in ["Bob"; "Fred"; "Sarah"].values() do
env.out.print(name)
end
39 changes: 30 additions & 9 deletions code-samples/control-structures-loops-while-break-else.pony
Original file line number Diff line number Diff line change
@@ -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
"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
12 changes: 7 additions & 5 deletions code-samples/control-structures-loops-while.pony
Original file line number Diff line number Diff line change
@@ -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
while count <= 10 do
env.out.print(count.string())
count = count + 1
end
22 changes: 11 additions & 11 deletions docs/expressions/control-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ 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.

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:
Expand All @@ -52,21 +52,21 @@ 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__.

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:
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down

0 comments on commit 8306f56

Please sign in to comment.