{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Loops"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In `Julia` there are two types of loops, `for` and `while`.\n",
"As of `Julia 1.5` ([here](https://docs.julialang.org/en/v1/manual/variables-and-scoping/) you can find a longer discussion on the implemented changes), the behavior of those loops are very similar to loops known in other programming languages.\n",
"\n",
"`for` loops repeat a finite number evaluations, which is equal to the number of elements of the provided iterable object. \n",
"Ranges and arrays are examples of iterable objects.\n",
"One very simple `for` loop:\n",
"\n",
"`````{margin}\n",
"````{note}\n",
"Instead of `in` we can also use `∈` (`\\in` and `<tab>`) to get exactly the same results:\n",
"\n",
"```\n",
"for i ∈ [1 2 3 4]\n",
" println(\"$i=i\")\n",
"end\n",
"```\n",
"````\n",
"`````"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i=1\n",
"i=2\n",
"i=3\n",
"i=4\n"
]
}
],
"source": [
"for i in [1 2 3 4]\n",
" println(\"i=$i\")\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The loop iterates over elements of the array `[1 2 3 4]`. For each iteration the value of the iterator `i` is changed to the subsequent element of the iterable object."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"if you use two-dimensional arrays, the order of elements is chosen _columnwisely_."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2×2 Matrix{Int64}:\n",
" 1 2\n",
" 3 4"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"A = [1 2; 3 4]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i=1\n",
"i=3\n",
"i=2\n",
"i=4\n"
]
}
],
"source": [
"for i in A\n",
" println(\"i=$i\")\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Loops can be nested:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x^y=1, for x=1 and y=1.\n",
"x^y=1, for x=1 and y=2.\n",
"x^y=2, for x=2 and y=1.\n",
"x^y=4, for x=2 and y=2.\n",
"x^y=3, for x=3 and y=1.\n",
"x^y=9, for x=3 and y=2.\n"
]
}
],
"source": [
"for x ∈ 1:3\n",
" for y ∈ 1:2\n",
" println(\"x^y=$(x^y), for x=$x and y=$y.\")\n",
" end \n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The same thing can be written in a more compact way:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x^y=1, for x=1 and y=1.\n",
"x^y=1, for x=1 and y=2.\n",
"x^y=2, for x=2 and y=1.\n",
"x^y=4, for x=2 and y=2.\n",
"x^y=3, for x=3 and y=1.\n",
"x^y=9, for x=3 and y=2.\n"
]
}
],
"source": [
"for x ∈ 1:3, y ∈ 1:2 \n",
" println(\"x^y=$(x^y), for x=$x and y=$y.\") \n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The conditional mapping of elements of the vector from [our previous example](elementwise-question-example), can be solved also using a `for` loop:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"y=[2, -4, 10, -16, 26, -36, 50, -64, 82, -100]\n"
]
}
],
"source": [
"x = collect(1:10)\n",
"y = similar(x) #the object of the same size and type as x \n",
"\n",
"for i ∈ 1:length(x) \n",
" y[i] = x[i]%2==0 ? -x[i]^2 : x[i]^2+1\n",
"\n",
"end\n",
"\n",
"println(\"y=$y\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Instead of using `i ∈ 1:length(x)`, we can use `(i,xᵢ) ∈ enumerate(x)`.\n",
"Using this approach, the `for` loop creates one iterator equal to a counter starting at `1` and one iterator `xᵢ` equal to subsequent values of `x`:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"y2=[2, -4, 10, -16, 26, -36, 50, -64, 82, -100]\n"
]
}
],
"source": [
"y2 = similar(x)\n",
"for (i,xᵢ) ∈ enumerate(x)\n",
" y2[i] = xᵢ%2==0 ? -xᵢ^2 : xᵢ^2+1\n",
"end\n",
"\n",
"println(\"y2=$y2\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The most compact way to perform this operation is to use an _inline `for` loop_.\n",
"This type of loops has the following structure `[operations for iterator in iterable_object ]`.\n",
"\n",
"\n",
"In our example this will be:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10-element Vector{Int64}:\n",
" 2\n",
" -4\n",
" 10\n",
" -16\n",
" 26\n",
" -36\n",
" 50\n",
" -64\n",
" 82\n",
" -100"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y = [ xᵢ%2==0 ? -xᵢ^2 : xᵢ^2+1 for xᵢ ∈ x ]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I presented several ways of solving [the discussed problem](elementwise-question-example).\n",
"Personally, I am the biggest fan of using a functional approach involving `map`: `map(arg -> arg%2==0 ? -arg^2 : arg^2+1 , x)`.\n",
"The reason for this is that this approach is easier to be nested inside [pipes](pipes), discussed later."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`while` loops are a traditional alternative to `for` loops.\n",
"This loop is executed as long as the provided condition is true. \n",
"If the condition is not met, then the execution is terminated."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i=0\n",
"i=1\n",
"i=2\n",
"i=3\n",
"i=4\n",
"i=5\n"
]
}
],
"source": [
"i = 0\n",
"while i ≤ 5 \n",
" println(\"i=$i\")\n",
" i+=1;\n",
" \n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `for` loop can imitate this behavior by combination of `break` and conditional statement. \n",
"The main difference is that it has the maximum number of iterations equal to the size of the iterable object, in the case below equal to $1000.$"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i=0\n",
"i=1\n",
"i=2\n",
"i=3\n",
"i=4\n",
"i=5\n"
]
}
],
"source": [
"i = 0\n",
"for κ ∈ 1:1000\n",
" println(\"i=$i\")\n",
" i+=1;\n",
" if i>5 #termination condition\n",
" break\n",
" end \n",
"end\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Command `break` terminates the current iteration of the loop and executes further code."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example we take negation of `i≤5`. To directly use this condition, we can use `continue` and `break`. `continue` tells `Julia` to finish the current iteration of the loop (in the current line!) and to start a new iteration.\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i=0\n",
"i=1\n",
"i=2\n",
"i=3\n",
"i=4\n",
"i=5\n"
]
}
],
"source": [
"i = 0\n",
"for κ ∈ 1:1000\n",
" println(\"i=$i\")\n",
" i+=1;\n",
" if i≤5 \n",
" continue \n",
" else\n",
" break\n",
" end \n",
" \n",
" 1+2+3 #this part of the loop is never executed.\n",
" \n",
"end\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Last and maybe the least, we can use short-circuit evaluations discussed [here](short-circuit) to make the code more compact."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 0\n",
"for κ ∈ 1:1000\n",
" println(\"i=$i\")\n",
" i+=1;\n",
" \n",
" i≤5 || break #termination condition. `break` is executed when `i≤5` is false\n",
" \n",
"end"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.6.0",
"language": "julia",
"name": "julia-1.6"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.6.0"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}