julia> f = (x, y) -> x + y * log(y)
#11 (generic function with 1 method)

You can broadcast this function over p and q to create a grid:

julia> f.(p, q')
100×100 Array{Float64,2}:
...

But you actually don’t need to! In fact, Plots.jl already knows how to plot the contour of a function if you just pass it the input vectors p and q and the function itself:

julia> using Plots
julia> n = 100
100
julia> q = range(0, stop = 200, length = n)
0.0:2.0202020202020203:200.0
julia> p = range(0, stop = 200, length =n )
0.0:2.0202020202020203:200.0
julia> f = (x, y) -> x + y * log(y)
#11 (generic function with 1 method)
julia> contour(p, q, f)

Note that we also don’t need to generate p_grid or q_grid because Plots.jl is smart enough to work directly from the vectors.

Because of the way broadcasting works you very rarely need to define grids like p_grid and q_grid. So if you find yourself using repeat on a vector, there’s a good chance you’re doing something unnecessary.

In fact the same is true for both Matlab and numpy too, so this technique is quite outdated these days.