{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## 01 Julia Introduction for EECS 551\n", "\n", "2018-08-11 Jeff Fessler (based on 2017 version by David Hong) \n", "Julia 0.7.0 \n", "2019-01-20 Julia 1.0.3 and add note about line breaks \n", "2020-08-05 Julia 1.5.0\n", "2021-08-23 Julia 1.6.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Numbers and arithmetic (and thinking about types!)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make a real number!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r = 3.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variables in Julia have a type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(r)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(i)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = 3. + 2im" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can add, subtract, multiply and divide like usual." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "4. + 5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "4. - 5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "4. * 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2. / 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dividing `Int` values with `\\` produces a `Float`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2/3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "4/2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is different from Python 2, but similar to Python 3." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To divide integers with rounding, use `÷` instead. Type `\\div` then hit tab." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "5 ÷ 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More info about numbers here:\n", "+ https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers\n", "+ https://docs.julialang.org/en/v1/manual/mathematical-operations\n", "+ https://docs.julialang.org/en/v1/manual/complex-and-rational-numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vector and matrices (i.e., arrays)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make a vector of real numbers:\n", "\n", "$x = \\begin{bmatrix} 1.0 \\\\ 3.5 \\\\ 2 \\end{bmatrix}$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = [1, 3.5, 2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the type: `Array{Float64,1}`. \n", "Having just one real number in the array sufficed\n", "for the array have all `Float64` elements.\n", "\n", "This is a true **one**-dimensional array of **`Float64`**'s. \n", "(Matlab does not have 1D arrays; it fakes it using 2D arrays of size N × 1.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "size(x) # returns a tuple" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x_ints = [1,3,2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a **one**-dimensional array of **`Int64`**'s.\n", "We'll use these less often in 551." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "size(x_ints)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length(x_ints)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make a matrix using a semicolon to separate rows:\n", "\n", "$ A = \\begin{bmatrix}\n", "1.1 & 1.2 & 1.3 \\\\\n", "2.1 & 2.2 & 2.3\n", "\\end{bmatrix}$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = [1.1 1.2 1.3; 2.1 2.2 2.3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a **two**-dimensional array (aka a matrix) of **`Float64`** values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "size(A)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Different from Matlab! `length` always returns the total number of elements." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make vectors and matrices of all zeros." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "zeros(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Different from Matlab!\n", "Do not write `zeros(3,1)` because Julia has proper 1D arrays. \n", "`zeros(3,1)` and `zeros(3)` are different!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "zeros(2,3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And ones:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ones(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ones(2,3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The \"identity matrix\" ``I`` in Julia's `LinearAlgebra` package is sophisticated. \n", "Look at the following examples:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "using LinearAlgebra\n", "ones(3,3) - I" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ones(2,2) * I" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If that ``I`` seems too fancy, then you could make your own \"eye\" command\n", "akin to Matlab as follows\n", "(but it should not be needed and it uses unnecessary memory):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "eye = n -> Matrix(1.0*I(n))\n", "eye(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make diagonal matrices using the `Diagonal` function in `LinearAlgebra`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Diagonal(3:6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is far more memory efficient than Matlab's `diag` command\n", "or Julia's `LinearAlgebra.diagm` method. Avoid using those!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make random vectors and matrices.\n", "\n", "$ x = \\begin{bmatrix} \\mathcal{N}(0,1) \\\\ \\mathcal{N}(0,1) \\\\ \\mathcal{N}(0,1) \\end{bmatrix}\n", "\\qquad \\text{i.e.,} \\quad x_i \\overset{\\text{iid}}{\\sim} \\mathcal{N}(0,1)$\n", "\n", "$ A = \\begin{bmatrix}\n", "\\mathcal{N}(0,1) & \\mathcal{N}(0,1) & \\mathcal{N}(0,1) \\\\\n", "\\mathcal{N}(0,1) & \\mathcal{N}(0,1) & \\mathcal{N}(0,1)\n", "\\end{bmatrix}\n", "\\qquad \\text{i.e., } \\quad A_{ij} \\overset{\\text{iid}}{\\sim} \\mathcal{N}(0,1)$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = randn(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = randn(2,3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Matrix operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indexing is done with **square** brackets and begins at **1**\n", "(like in Matlab and counting) not **0** (like in C or Python)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = [1.1 1.2 1.3; 2.1 2.2 2.3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A[1,1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A[1,2:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This row-slice is a one-dimensional slice! Not a `1×2` matrix." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A[1:2,1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A[2,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vector dot product" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = randn(3)\n", "xdx = x'x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xdx = dot(x,x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xdx = x'*x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Different from Matlab! The output is a scalar, **not** a `1×1` \"matrix.\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(xdx)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrix times vector" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = randn(2,3)\n", "x = randn(3)\n", "A*x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrix times matrix" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = randn(2,3)\n", "B = randn(3,4)\n", "A*B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrix transpose (conjugate and non-conjugate)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = 10*reshape(1:6, 2, 3) + im * reshape(1:6, 2, 3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A' # conjugate transpose, could also use adjoint(A)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# For complex arrays, rarely do we need a non-conjugate transpose.\n", "# Usually we need A' instead. But if we do:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "transpose(A) # essentially sets a flag about transpose without reordering data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrix determinant" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = Diagonal(2:4)\n", "det(A)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "B = randn(3,3)\n", "[det(A*B) det(A)*det(B)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrix trace" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = ones(3,3)\n", "tr(A) # in Matlab would be \"trace(A)\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More info here: https://docs.julialang.org/en/v1/manual/arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Important Aside: Getting help!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Julia analogue of Matlab's `help` is `?`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "?pwd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Full documentation online: https://docs.julialang.org/en/stable/ \n", "Searching their Github repo can sometimes also uncover folks with similar issues: https://github.com/JuliaLang/julia\n", "\n", "Also lots of neat talks on their Youtube Channel: https://www.youtube.com/user/JuliaLanguage \n", "Especially encourage this very interesting one about vector transposes! https://www.youtube.com/watch?v=C2RO34b_oPM" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Aside: Creating ranges\n", "It's different from (and much more efficient than) Matlab!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myrange = -2:3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(myrange)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Not an Array! But can be indexed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myrange[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Used often in `for` loops." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for a in myrange\n", " println(a)\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Form an array by using `collect` if needed (use rarely):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "collect(myrange)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other ways to make ranges." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "srange =1:-1:-5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(srange)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#lrange = linspace(0,10,6) # deprecated in 0.7\n", "lrange = range(0, step=2, stop=10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(lrange)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "LinRange(0,10,6) # yet another option that looks the most like linspace !" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Aside: Comprehensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A convenient way to create arrays!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "comp = [i+0.1 for i in 1:5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "comp = [i+0.1*j for i in 1:5, j in 1:4]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Way 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "function f1(x,y)\n", " z = x+y\n", " return z\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Way 2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f2(x,y) = x+y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Way 3: Anonymous function" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f3 = (x,y) -> x+y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can return multiple outputs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "function f_mult(x,y)\n", " add = x+y\n", " sub = x-y\n", " return add,sub\n", "end" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f_mult(2,3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "out_tuple = f_mult(2,3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "typeof(out_tuple)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Output is a `Tuple` of the outputs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convenient way to split out the outputs." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "out1,out2 = f_mult(2,3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "out1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "out2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any function can be \"vectorized\" using \"broadcast\" capability." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myquad = x -> (x+1)^2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myquad(1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myquad([1,2,3]) # this does not work! but see next cell!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This particular function was not designed to be applied to vector input arguments! \n", "But it can be used with vectors by adding a \".\" to tell Julia to apply it element-wise.\n", "This is called a \"broadcast\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myquad.([1,2,3])" ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 2 }, "source": [ "More info here: https://docs.julialang.org/en/v1/manual/functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Conditionals: If, Else, End, For" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Generally similar to Matlab. Optional use of `in` instead of `=` in the for loop." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for j in 1:3\n", " if j == 2\n", " println(\"This is a two! ^^\")\n", " else\n", " println(\"This is not a two. :(\")\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Julia has the convenient ternary operator." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "mystring = 2 > 3 ? \"2 is greater than 3\" : \"2 is not greater than 3\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting\n", "Suggested package: `Plots.jl` with its default `gr` backend.\n", "\n", "**Note:** Usually slower the first time you plot due to precompiling. \n", "You must `add` the \"Plots\" package first.\n", "In a regular Julia REPL you do this by using the `]` key to enter the package manager REPL, and then type `add Plots` then wait. \n", "In a Jupyter notebook, type `using Pkg` then `add Plots` and wait." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "using Plots\n", "backend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot values from a vector. (The labels are optional arguments.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = LinRange(-5,5,101)\n", "y = x.^2\n", "plot(x, y, xlabel=\"x\", ylabel=\"y\", label=\"parabola\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Revisiting the heatmap\n", "cf example in `n-01-matrix` notes" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = LinRange(-2, 2, 101)\n", "y = LinRange(-1.1, 1.1, 103)\n", "A = x.^2 .+ 30 * (y.^2)'\n", "F = exp.(-A)\n", "heatmap(x, y, F, transpose=true, # for F(x,y)\n", " color=:grays, aspect_ratio=:equal, xlabel=\"x\", ylabel=\"y\", title=\"bump\")" ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 2 }, "source": [ "Using the `jim` function the `MIRTjim.jl` package simplifies\n", "the display of 2D images, among other features. See:\n", "https://jefffessler.github.io/MIRTjim.jl/stable/examples/1-examples/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A convenient way to plot functions\n", "\n", "`Plots.jl` allows you to pass in the domain and a function. It does the rest. :) \n", "This is one many examples of how Julia exploits \"multiple dispatch.\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot(LinRange(0,1,100), x -> x^2, label=\"x^2\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "heatmap(LinRange(-2,2,102), LinRange(-1.1,1.1,100),\n", " (x,y) -> exp(-x^2-30*y^2), aspect_ratio=1)" ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 2 }, "source": [ "More info about plotting here: https://juliaplots.github.io" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Caution about line breaks (newlines) \n", "If you want an expression to span multiple lines,\n", "then be sure to enclose it in parentheses." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Compare the following 3 (actually 4) expressions before `@show`\n", "x = 9\n", " - 7\n", "\n", "y = 9 -\n", " 7\n", "\n", "z = (9\n", " - 7)\n", "\n", "@show (x,y,z);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Submitting homework" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A quick example to try submitting problems." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Task:** Implement a function that takes two inputs and outputs them in reverse order." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "function template1(x,y)\n", " return (y,x)\n", "end" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "template1(2,3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Copy the above function code into a file named `template1.jl`\n", "and email to `eecs551@autograder.eecs.umich.edu`.\n", "\n", "Make sure that:\n", "+ All reasonable input types can be handled. Internally trying to convert a `Float64` to an `Int64` can produce `InexactError`\n", "+ File extension is \".jl\". Watch out for hidden extensions!\n", "+ File has just the Julia function.\n", "(Your HW solutions can also contain `using` statements.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An undocumented function is bad programming practice. \n", "Julia supports `docstrings` for comments like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"\n", " template2(x,y)\n", "This function reverses the order of the two input arguments.\n", "\"\"\"\n", "function template2(x,y)\n", " return (y,x)\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can see the docstring by using the `?` key:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "?template2" ] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.6.2", "language": "julia", "name": "julia-1.6" } }, "nbformat": 4, "nbformat_minor": 4 }