To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

This notebook takes about 20 seconds to run.

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1

Testing

👀 Reading hidden code
172 μs
👀 Reading hidden code
abstract type TestResult end
369 μs
Any
👀 Reading hidden code
const Code = Any
112 μs
👀 Reading hidden code
struct Pass <: TestResult
expr::Code
end
1.2 ms
👀 Reading hidden code
abstract type Fail <: TestResult end
371 μs
👀 Reading hidden code
struct Wrong <: Fail
expr::Code
result
arg_results
end
1.3 ms
👀 Reading hidden code
struct Error <: Fail
expr::Code
error
end
1.2 ms
👀 Reading hidden code
function Base.show(io::IO, mime::MIME"text/html", value::Pass)
show(io, mime, HTML("""
<div
style="
display: flex;
flex-direction: row;
align-items: center;
/*background-color: rgb(208, 255, 209)*/
"
>
<div
style="
width: 12px;
height: 12px;
border-radius: 50%;
background-color: green;
"
></div>
<div style="min-width: 12px"></div>
<code
class="language-julia"
style="
flex: 1;
background-color: transparent;
filter: grayscale(1) brightness(0.8);
"
>$(value.expr)</code>
</div>
"""))
end
610 μs
function Base.show(io::IO, mime::MIME"text/html", value::Wrong)
show(io, mime, HTML("""
<div
style="
display: flex;
flex-direction: row;
align-items: center;
/*background-color: rgb(208, 255, 209)*/
"
>
<div
style="
width: 12px;
height: 12px;
border-radius: 50%;
background-color: red;
"
></div>
<div style="min-width: 12px"></div>
<code
class="language-julia"
style="
flex: 1;
background-color: transparent;
filter: grayscale(1) brightness(0.8);
"
>$(value.expr)</code>
<div style="
font-family: monospace;
font-size: 12px;
color: red;
padding-left: 8px;
">Evaluated: $(string(Expr(value.expr.head, value.arg_results...)))</div>
</div>
"""))
end
👀 Reading hidden code
722 μs
function Base.show(io::IO, mime::MIME"text/html", value::Error)
show(io, mime, HTML("""
<div
style="
display: flex;
flex-direction: row;
align-items: center;
/*background-color: rgb(208, 255, 209)*/
"
>
<div
style="
width: 12px;
height: 12px;
border-radius: 50%;
background-color: red;
"
></div>
<div style="width: 12px"></div>
<div>
<code
class="language-julia"
style="
background-color: transparent;
filter: grayscale(1) brightness(0.8);
"
>$(value.expr)</code>
<div style="
font-family: monospace;
font-size: 12px;
color: red;
padding-left: 8px;
">Error: $(sprint(showerror, value.error))</div>
</div>
</div>
"""))
end
👀 Reading hidden code
3.8 ms
# Only define this in Pluto - assume we are `using Test` otherwise
begin
@skip_as_script macro test(expr)
quote
expr_raw = $(expr |> QuoteNode)
try
arg_results = $([esc(a) for a in expr.args])
# result = eval(Expr($(expr.head |> QuoteNode), arg_results...))
# if result == true
# Pass(expr_raw)
# else
# Wrong(expr_raw, result)
# end
catch e
Error(expr_raw, e)
end
# Base.@locals()
end
end
# Do nothing inside pluto (so we don't need to have Test as dependency)
# test/Firebasey is `using Test` before including this file
@only_as_script ((@isdefined Test) ? nothing : macro test(expr) quote nothing end end)
end
👀 Reading hidden code
4.2 ms
Expr
  head: Symbol block
  args: Array{Any}((2,))
    1: LineNumberNode
      line: Int64 2
      file: Symbol /home/runner/work/disorganised-mess/disorganised-mess/testing and debugging 1.jl#==#7c35f88d-7740-4bc3-9ab6-855cc78223e2
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol ==
        2: Symbol a
        3: QuoteNode
          value: Symbol a
quote
a == :a
end |> Dump
👀 Reading hidden code
3.9 ms
Error message

UndefVarError: to_eval#431 not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. macro expansion
    				Pass(expr_raw)			else				Wrong(expr_raw, result, to_eval)			end		catch e
  2. Show more...
@test3 sqrt.([1])
👀 Reading hidden code
---

👀 Reading hidden code
82.2 μs
Error message

UndefVarError: to_eval#459 not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. macro expansion
    				Pass(expr_raw)			else				Wrong(expr_raw, result, to_eval)			end		catch e
  2. Show more...
Try asking on Julia Discourse!
@test3 a .== a
👀 Reading hidden code
---
a == [1, 2, 3]
@test3 a == [1,2,3]
👀 Reading hidden code
19.6 ms
Error message

UndefVarError: to_eval#438 not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. macro expansion
    				Pass(expr_raw)			else				Wrong(expr_raw, result, to_eval)			end		catch e
  2. Show more...
@test3 a == :a
👀 Reading hidden code
---
iseven(234)
@test3 iseven(234)
👀 Reading hidden code
5.1 ms
Error message

MethodError: no method matching getproperty(::typeof(sqrt), ::Tuple{Vector{Int64}})

Closest candidates are:

getproperty(::Any, ::Symbol) at /opt/hostedtoolcache/julia/1.7.3/x64/share/julia/base/Base.jl:42

getproperty(::Any, ::Symbol, ::Symbol) at /opt/hostedtoolcache/julia/1.7.3/x64/share/julia/base/Base.jl:54

Stack trace

Here is what happened, the most recent locations are first:

  1. eval
  2. eval(x::Expr)
  3. 		eval(Expr(e.head, arg_results...))end
let
e = :(sqrt.([5]))
arg_results = [eval(a) for a in e.args]
eval(Expr(e.head, arg_results...))
end
👀 Reading hidden code
---
staged_eval (generic function with 1 method)
staged_eval(e) = eval(e)
👀 Reading hidden code
396 μs
staged_eval (generic function with 2 methods)
function staged_eval(e::Expr)
if e.head == :call
arg_results = Any[
if a isa QuoteNode
QuoteNode(a)
elseif i == 1
a
else
eval(a)
end
for (i,a) in enumerate(e.args)]
arg_results[1] = e.args[1]
printable_arg_results = [
if a isa QuoteNode
a.value
else
a
end
for a in arg_results]
eval(Expr(e.head, arg_results...)), arg_results, Expr(e.head, printable_arg_results...)
else
eval(e), nothing
end
end
👀 Reading hidden code
2.8 ms
eval_args (generic function with 1 method)
eval_args(x) = x
👀 Reading hidden code
339 μs
quote_again (generic function with 1 method)
quote_again(x) = x
👀 Reading hidden code
361 μs
quote_again (generic function with 2 methods)
quote_again(x::QuoteNode) = QuoteNode(x)
👀 Reading hidden code
380 μs
eval_args (generic function with 2 methods)
function eval_args(e::Expr)
if e.head == :call
arg_results = Any[
if a isa QuoteNode
QuoteNode(a)
elseif i == 1
a
else
eval(a)
end
for (i,a) in enumerate(e.args)]
arg_results[1] = e.args[1]
printable_arg_results = [
if a isa QuoteNode
a.value
else
a
end
for a in arg_results]
Expr(e.head, printable_arg_results...)
else
eval(e)
end
end
👀 Reading hidden code
3.1 ms
onestep (generic function with 1 method)
onestep(x; m) = []
👀 Reading hidden code
1.3 ms
onestep (generic function with 2 methods)
function onestep(e::Expr; m=Module())
results = Any[]
# push!(results, e)
arg_results = Any[a for a in e.args]
for (i,a) in enumerate(e.args)
arg_results[i] = if a isa QuoteNode
a
elseif (e.head === :call || e.head === :let) && i == 1
a
elseif a isa Expr
inner_results = onestep(a; m=m)
for ir in inner_results
arg_results[i] = ir
push!(results, Expr(e.head, arg_results...))
end
inner_results[end]
else
a
end
# push!(results, Expr(e.head, arg_results...))
end
push!(results, Core.eval(m, Expr(e.head, arg_results...)))
results
end
👀 Reading hidden code
3.7 ms
expr_debug (generic function with 1 method)
function expr_debug(x)
e = Base.remove_linenums!(deepcopy(x))
Any[e, onestep(e)...]
end
👀 Reading hidden code
561 μs
expr_debug(quote
let
end
end)
👀 Reading hidden code
6.2 ms
eval(Expr(:let, Expr(:block), nothing))
👀 Reading hidden code
230 μs
debug_result = expr_debug(:(
let
r = if rand(Bool)
20
else
16
end
y = sqrt(4)
y == sqrt(sqrt(r))
end
));
👀 Reading hidden code
14.3 ms
👀 Reading hidden code
366 ms
let
    r = if rand(Bool)
            20
        else
            16
        end
    y = sqrt(4)
    y == sqrt(sqrt(r))
end
debug_result[step] |> prettycolors
👀 Reading hidden code
46.9 ms

















👀 Reading hidden code
112 μs
prettycolors (generic function with 1 method)
prettycolors(e) = Markdown.MD([Markdown.Code("julia", string(e))])
👀 Reading hidden code
533 μs
Expr
  head: Symbol let
  args: Array{Any}((2,))
    1: Expr
      head: Symbol block
      args: Array{Any}((0,))
    2: Expr
      head: Symbol block
      args: Array{Any}((3,))
        1: Expr
          head: Symbol =
          args: Array{Any}((2,))
            1: Symbol r
            2: Expr
              head: Symbol if
              args: Array{Any}((3,))
                1: Expr
                  head: Symbol call
                  args: Array{Any}((2,))
                    1: Symbol rand
                    2: Symbol Bool
                2: Expr
                  head: Symbol block
                  args: Array{Any}((1,))
                    1: Int64 20
                3: Expr
                  head: Symbol block
                  args: Array{Any}((1,))
                    1: Int64 16
        2: Expr
          head: Symbol =
          args: Array{Any}((2,))
            1: Symbol y
            2: Expr
              head: Symbol call
              args: Array{Any}((2,))
                1: Symbol sqrt
                2: Int64 4
        3: Expr
          head: Symbol call
          args: Array{Any}((3,))
            1: Symbol ==
            2: Symbol y
            3: Expr
              head: Symbol call
              args: Array{Any}((2,))
                1: Symbol sqrt
                2: Expr
                  head: Symbol call
                  args: Array{Any}((2,))
                    1: Symbol sqrt
                    2: Symbol r
Dump(debug_result[step]; maxdepth=999)
👀 Reading hidden code
6.4 ms
using PlutoUI
👀 Reading hidden code
182 ms
Error message

UndefVarError: a not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. from :0
  2. eval
  3. eval
  4. staged_eval
    				a			else				eval(a)			end 				for (i,a) in enumerate(e.args)]
  5. Show more...
Keep calm, you got this!
staged_eval(:(a == :a))
👀 Reading hidden code
---
Error message

UndefVarError: a not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. from :0
  2. eval
  3. eval
  4. staged_eval
    				a			else				eval(a)			end 				for (i,a) in enumerate(e.args)]
  5. Show more...
staged_eval(:(a == a))
👀 Reading hidden code
---
Error message

UndefVarError: a not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. from :0
  2. eval
  3. eval
  4. staged_eval
    				a			else				eval(a)			end 				for (i,a) in enumerate(e.args)]
  5. Show more...
Silly computer!
staged_eval(:(a .== a))
👀 Reading hidden code
---
staged_eval(:(sqrt(sqrt(4))))
👀 Reading hidden code
43.0 ms
staged_eval(:(sqrt.(5)))
👀 Reading hidden code
16.2 ms
:(sqrt.(5))
e = :(sqrt.(5))
👀 Reading hidden code
23.3 μs
Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol sqrt
    2: Expr
      head: Symbol tuple
      args: Array{Any}((1,))
        1: Int64 5
Dump(e)
👀 Reading hidden code
11.7 μs
Base.Broadcast.BroadcastFunction(==)
.==
👀 Reading hidden code
197 μs
Base.Broadcast.BroadcastFunction(==)
eval(Meta.parse(".=="))
👀 Reading hidden code
321 μs
Error message

UndefVarError: .== not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. from :0
  2. eval
  3. eval(x::Symbol)
  4. eval(Symbol(".=="))
eval(Symbol(".=="))
👀 Reading hidden code
---
2.23606797749979
eval(e)
👀 Reading hidden code
222 μs
Error message

UndefVarError: a not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. eval
  2. eval(x::Expr)
  3. eval(Expr(:call, Symbol(".=="), :a, :a))
eval(Expr(:call, Symbol(".=="), :a, :a))
👀 Reading hidden code
---
@test3 (macro with 1 method)
@skip_as_script macro test3(expr)
quote
expr_raw = $(expr |> QuoteNode)
try
result, arg_results = staged_eval(expr_raw)
if result === true
Pass(expr_raw)
else
Wrong(expr_raw, result, to_eval)
end
catch e
rethrow(e)
Error(expr_raw, e)
end

# Base.@locals()
end
end

👀 Reading hidden code
608 μs
quote
    var"#491#expr_raw" = $(QuoteNode(:(a .== :a)))
    try
        (var"#492#result", var"#493#arg_results") = Main.workspace#4.staged_eval(var"#491#expr_raw")
        if var"#492#result" === true
            Main.workspace#4.Pass(var"#491#expr_raw")
        else
            Main.workspace#4.Wrong(var"#491#expr_raw", var"#492#result", Main.workspace#4.to_eval)
        end
    catch var"#496#e"
        Main.workspace#4.rethrow(var"#496#e")
        Main.workspace#4.Error(var"#491#expr_raw", var"#496#e")
    end
end
(@macroexpand @test3 a .== :a) |> Base.remove_linenums!
👀 Reading hidden code
1.9 ms
true
eval(Expr(:call, QuoteNode(.<), 1, 2))
👀 Reading hidden code
46.9 ms
quote_if_needed (generic function with 1 method)
quote_if_needed(x) = x
👀 Reading hidden code
352 μs
quote_if_needed (generic function with 2 methods)
quote_if_needed(x::Union{Expr,Symbol}) = QuoteNode(x)
👀 Reading hidden code
422 μs
a = [1,2,3]
👀 Reading hidden code
14.8 μs

👀 Reading hidden code
67.9 μs

👀 Reading hidden code
65.6 μs
@test2 (macro with 1 method)
macro test2(expr)
quote nothing end
end
👀 Reading hidden code
435 μs
@skip_as_script @test notebook1 == deepcopy(notebook1)
👀 Reading hidden code
133 μs

DisplayOnly

👀 Reading hidden code
171 μs
skip_as_script (generic function with 1 method)
function skip_as_script(m::Module)
if isdefined(m, :PlutoForceDisplay)
return m.PlutoForceDisplay
else
isdefined(m, :PlutoRunner) && parentmodule(m) == Main
end
end
👀 Reading hidden code
571 μs
@skip_as_script
@displayonly expression

Marks a expression as Pluto-only, which means that it won't be executed when running outside Pluto. Do not use this for your own projects.

"""
@displayonly expression

Marks a expression as Pluto-only, which means that it won't be executed when running outside Pluto. Do not use this for your own projects.
"""
macro skip_as_script(ex) skip_as_script(__module__) ? esc(ex) : nothing end
👀 Reading hidden code
884 μs
@only_as_script

The opposite of @skip_as_script

"The opposite of `@skip_as_script`"
macro only_as_script(ex) skip_as_script(__module__) ? nothing : esc(ex) end
👀 Reading hidden code
851 μs
2
@skip_as_script x = 2
👀 Reading hidden code
13.5 μs
@skip_as_script @test 1 + 1 == x
👀 Reading hidden code
148 μs
@skip_as_script @test 1 + 1 + 1 == x
👀 Reading hidden code
31.3 ms
@skip_as_script @test error("Oh my god") == x
👀 Reading hidden code
156 μs

Track

👀 Reading hidden code
169 μs
sleep(0.1)
101.0 ms
20 frames in @code_typed
@skip_as_script @track sleep(0.1)
👀 Reading hidden code
391 ms
Tracked
begin
Base.@kwdef struct Tracked
expr
value
time
bytes
times_ran = 1
which = nothing
code_info = nothing
end
function Base.show(io::IO, mime::MIME"text/html", value::Tracked)
times_ran = if value.times_ran === 1
""
else
"""<span style="opacity: 0.5"> ($(value.times_ran)×)</span>"""
end
# method = sprint(show, MIME("text/plain"), value.which)
code_info = if value.code_info ≠ nothing
codelength = length(value.code_info.first.code)
"$(codelength) frames in @code_typed"
else
""
end
color = if value.time > 1
"red"
elseif value.time > 0.001
"orange"
elseif value.time > 0.0001
"blue"
else
"green"
end
show(io, mime, HTML("""
<div
style="
display: flex;
flex-direction: row;
align-items: center;
"
>
<div
style="
width: 12px;
height: 12px;
border-radius: 50%;
background-color: $(color);
"
></div>
<div style="width: 12px"></div>
<div>
<code
class="language-julia"
style="
background-color: transparent;
filter: grayscale(1) brightness(0.8);
"
>$(value.expr)</code>
<div style="
font-family: monospace;
font-size: 12px;
color: $(color);
">
$(prettytime(value.time * 1e9 / value.times_ran))
$(times_ran)
</div>
<div style="
font-family: monospace;
font-size: 12px;
color: gray;
">$(code_info)</div>

</div>
</div>
"""))
end
Tracked
end
👀 Reading hidden code
38.6 ms
@track (macro with 1 method)
macro track(expr)
times_ran_expr = :(1)
expr_to_show = expr
if expr.head == :for
@assert expr.args[1].head == :(=)
times_ran_expr = expr.args[1].args[2]
expr_to_show = expr.args[2].args[2]
end

Tracked # reference so that baby Pluto understands
quote
local times_ran = length($(esc(times_ran_expr)))
local value, time, bytes = @timed $(esc(expr))
local method = nothing
local code_info = nothing
try
# Uhhh
method = @which $(expr_to_show)
code_info = @code_typed $(expr_to_show)
catch nothing end
Tracked(
expr=$(QuoteNode(expr_to_show)),
value=value,
time=time,
bytes=bytes,
times_ran=times_ran,
which=method,
code_info=code_info
)
end
end
👀 Reading hidden code
1.9 ms
prettytime (generic function with 1 method)
function prettytime(time_ns::Number)
suffices = ["ns", "μs", "ms", "s"]
current_amount = time_ns
suffix = ""
for current_suffix in suffices
if current_amount >= 1000.0
current_amount = current_amount / 1000.0
else
suffix = current_suffix
break
end
end
# const roundedtime = time_ns.toFixed(time_ns >= 100.0 ? 0 : 1)
roundedtime = if current_amount >= 100.0
round(current_amount; digits=0)
else
round(current_amount; digits=1)
end
return "$(roundedtime) $(suffix)"
end
👀 Reading hidden code
1.4 ms