false
2026-03-30
The “Two Language Problem”
In many fields, researchers prototype in a slow language (Python, R, Matlab) then rewrite in a fast language (C, Fortran) for production. Julia solves this: one language for both.
for loops, comparisons, logical operators, if statementsBy the end of this lecture you should be comfortable writing simple Julia programs that store data, loop, make decisions, organize code into functions, and use packages for root solving and optimization.
pi is also a prestored constantIf you want to make sure a variable is a float, add a decimal point to the end
Char)* (not +!)$"My name is David and I am 39 years old."
parse converts a string to a numberstring converts a number to a stringArrays []
[1, 2, 3]Tuples ()
(1, 2, 3)Named Tuples
(a=1, b=2)Dictionaries
Dict("a" => 1)Vector{Any} (alias for Array{Any, 1})
Note: Any means this array can hold any type of object.
We can also make arrays which are of only one type
Davidfloat only holds floating point numbers. Julia is generally more efficient if it knows what type of objects variables are.
MethodError: Cannot `convert` an object of type String to an object of type Float64 The function `convert` exists, but no method is defined for this combination of argument types. Closest candidates are: convert(::Type{T}, ::T) where T<:Number @ Base number.jl:6 convert(::Type{T}, ::Number) where T<:Number @ Base number.jl:7 convert(::Type{T}, ::T) where T @ Base Base_compiler.jl:133 ... Stacktrace: [1] setindex!(A::Vector{Float64}, x::String, i::Int64) @ Base ./array.jl:985 [2] top-level scope @ ~/University of Oregon Dropbox/David Evans/University of Oregon/Courses/Spring 2026/EC 410/Lectures and Website/Julia/Basic Julia/JuliaBasicsLecture.qmd:319
[] operatorJulia is indexing starts at 1!
Unlike Python (which starts at 0), Julia arrays start at index 1. This is a common source of bugs when switching languages.
L[1] gives us the first element of array LL[i] gives us access to the element at index \(i\) of array LL[end] gives access to the last element, L[end-1] the second to last, etc.:L[1:4] returns the list [L[1],L[2],L[3],L[4]]Tuple{Int64, String, Float64}
MethodError: no method matching setindex!(::Tuple{Int64, String, Float64}, ::Int64, ::Int64)
The function `setindex!` exists, but no method is defined for this combination of argument types.
Stacktrace:
[1] top-level scope
@ ~/University of Oregon Dropbox/David Evans/University of Oregon/Courses/Spring 2026/EC 410/Lectures and Website/Julia/Basic Julia/JuliaBasicsLecture.qmd:383
@NamedTuple{name::String, age::Int64, height::Float64}
Dict{String, Any}
"age", "gender" and "height" are the keysDavid maps them into the values 39, “male”, and 71.5which means for each element in an iterable (array, tuple, etc.) repeat some lines of code, which can depend on the value of x
1
2
3
4
5
What does the loop actually do? It repeats the body once for each value of i:
David?Best Practice
Use enumerate when you need both the index and the value. It’s cleaner than managing a counter variable manually.
How would you compute the sum: \[\sum_{j=0}^{50} \beta^j\]
Common Mistake
Don’t confuse = (assignment) with == (equality test)!
&& for “and”|| for “or”! for “not”| Expression | Result |
|---|---|
P && Q |
True if both are True, otherwise False |
P || Q |
False if both are False, otherwise True |
!P |
Negates P |
else to evaluate code if the condition is not metFind all the primes from 2 to 500
primes = Int[] # 1: Initialize empty array of integers
for i in 2:500 # 2: Loop through candidates 2 to 500
isprime = true # 3: Assume i is prime until proven otherwise
for p in primes # 4: Check against all known primes
if i%p == 0 # 5: Does p divide evenly into i?
isprime = false # 6: Yes, so i is not prime
end # 7: End if
end # 8: End inner loop
if isprime # 9: If no prime divided i...
push!(primes, i) # 10: ...add i to our list of primes
end # 11: End if
end # 12: End outer loopmap or sort)function Keywordfunction keywordreturn keyword specifies what the function gives backHello, David!
?square in the REPL\[ x_{t} = \rho x_{t-1} + \epsilon_{t} \quad\text{where}\quad \epsilon_{t}\sim N(0,1) \]
x = [5.0, 2.422503288348839, 2.1488499979516447, 0.5741422285491362, -0.03005259718238318, -1.4017432247714985, -2.1031732859677756, -1.661706985010909, 0.12256192776636987, 0.7301335037181337]
Main.Notebook.simulateAR1
ρzeros(T) for efficiencyplot! is used to add the second and third lines to the plotNonlinearSolve.jl package provides algorithms for solving nonlinear equationsf(u, p) — takes unknowns u and parameters pNonlinearProblem(f, u0)sol = solve(prob)sol.u; check sol.retcode for convergence statusConstant-elasticity demand and supply:
\[D(p) = A\, p^{-\epsilon_d}, \quad S(p) = B\, p^{\,\epsilon_s}\]
1-element Vector{Float64}:
1.583819608766579
Two goods with constant-elasticity demand and cross-price effects (substitutes):
function two_market(p, _)
D1 = 100 * p[1]^(-2.0) * p[2]^(0.5) # good 1 demand
S1 = 20 * p[1]^(1.5) # good 1 supply
D2 = 80 * p[2]^(-1.5) * p[1]^(0.3) # good 2 demand
S2 = 15 * p[2]^(2.0) # good 2 supply
return [D1 - S1, D2 - S2]
end
prob = NonlinearProblem(two_market, [2.0, 2.0])
sol = solve(prob)
sol.u2-element Vector{Float64}:
1.7069573735223966
1.6889575066262879
Working with NonlinearSolve
sol.retcode to verify the solver found a solutionf(u, p) — use _ if you don’t need parametersOptim.jl package provides algorithms for unconstrained optimizationOptim.jl minimizes by defaultoptimize(f, lower, upper)optimize(f, x0)A consumer with CES utility over two goods and a budget constraint:
\[U(x_1, x_2) = \bigl(\alpha\, x_1^{\rho} + (1-\alpha)\, x_2^{\rho}\bigr)^{1/\rho}\]
Substituting \(x_2 = (I - p_1 x_1)/p_2\) reduces this to a scalar problem:
function neg_utility(x1; α=0.5, ρ=-1.0, p1=1.0, p2=2.0, I=100.0)
x2 = (I - p1 * x1) / p2
return -(α * x1^ρ + (1-α) * x2^ρ)^(1/ρ)
end
result = optimize(neg_utility, 1.0, 99.0)
x1_star = Optim.minimizer(result)
x2_star = (100.0 - x1_star) / 2.0
println("x₁ = $(round(x1_star, digits=2)), x₂ = $(round(x2_star, digits=2))")x₁ = 41.42, x₂ = 29.29
x1_grid = LinRange(1.0, 99.0, 100) # 100 points between 1 and 99
utility = [-neg_utility(x1) for x1 in x1_grid] # compute utility for each x1
plot(x1_grid, utility,
xlabel = "x₁", ylabel = "U(x₁, x₂(x₁))",
title = "CES Utility along the Budget Constraint",
lw = 2, legend = false)
vline!([x1_star], ls = :dash, color = :red, lw = 1.5)
annotate!(x1_star + 2, maximum(utility) - 0.1,
text("x₁* = $(round(x1_star, digits=1))", :left, 9))OptimA firm with Cobb-Douglas production chooses labor \(L\) given fixed capital \(\bar{K}\):
\[\pi(L) = p \cdot A\, \bar{K}^{\alpha}\, L^{1-\alpha} - wL\]
function neg_profit(L; A=1.0, K̄=10.0, α=1/3, p=10.0, w=5.0)
Y = A * K̄^α * L^(1-α)
return -(p * Y - w * L) # negate for minimization
end
result = optimize(neg_profit, 0.1, 1000.0)
L_star = Optim.minimizer(result)
println("Optimal labor: $(round(L_star, digits=2))")
println("Maximum profit: $(round(-Optim.minimum(result), digits=2))")Optimal labor: 23.7
Maximum profit: 59.26
Working with Optim
Optim.jl minimizes — negate your function to maximizeOptim.minimizer(result) returns the optimal \(x^*\)Optim.minimum(result) returns the optimal value \(f(x^*)\)optimize(f, x0, LBFGS())Data Types
true/false1, 2, 33.14"hello"[1, 2, 3](1, 2, 3)(a=1, b=2)Dict("a" => 1)Control Flow
for loopsif/else statements<, >, ==&&, ||, !Functions
x -> x^2f(x) = x^2function ... endNumerical Methods
NonlinearSolve.jlNonlinearProblem(f, u0)Optim.jlEC 410 | University of Oregon