You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using `@show` or `println`, you can print local variables inside of a function:
344
+
345
+
```julia:debugshow
346
+
function sum_of_divisors(n)
347
+
divisors = filter(x -> n % x == 0, 1:n)
348
+
@show divisors
349
+
return sum(divisors)
350
+
end
351
+
```
352
+
```>
353
+
sum_of_divisors(6)
354
+
```
355
+
356
+
> The problem with `sum_of_divisors` is the range `1:n`,
357
+
> which includes `n` in the list of computed divisors.
358
+
> We can fix the function by changing the range to `1:n-1`.
359
+
360
+
While printing might suffice to debug simple problems, we can do better.
361
+
Julia offers the logging macros `@debug`, `@info`, `@warn` and `@error` that have several advantages over printing. They:
362
+
- show the line number they were called from
363
+
- label arguments, similar to `@show`
364
+
- can be disabled and filtered according to their source module and severity level
365
+
- work well in multithreaded code
366
+
- can be written to a file
367
+
368
+
By default, `@debug` messages are suppressed.
369
+
You can enable them through the `JULIA_DEBUG` environment variable
370
+
by specifying the source module name, e.g. `Main`.
371
+
372
+
```julia:debuglogging
373
+
function sum_of_divisors(n)
374
+
divisors = filter(x -> n % x == 0, 1:n)
375
+
@debug "sum_of_divisors" n divisors
376
+
return sum(divisors)
377
+
end
378
+
```
379
+
380
+
<!-- Live REPL mode doesn't print debug output -->
381
+
```julia-repl
382
+
julia> ENV["JULIA_DEBUG"] = Main # enable @debug logs
383
+
Main
384
+
385
+
julia> sum_of_divisors(6)
386
+
┌ Debug: sum_of_divisors
387
+
│ n = 6
388
+
│ divisors =
389
+
│ 4-element Vector{Int64}:
390
+
│ 1
391
+
│ 2
392
+
│ 3
393
+
│ 6
394
+
└ @ Main REPL[1]:3
395
+
12
396
+
```
397
+
398
+
For scripts, you can prefix your command-line call to `julia` with environment variables,
399
+
e.g. `JULIA_DEBUG=Main julia myscript.jl`.
400
+
Refer the [Julia documentation on logging][julia-docs-logging] for more information.
401
+
402
+
### VSCode Debugger
403
+
404
+
Using the [Julia VSCode extension][julia-vscode-repo],
405
+
click left of a line number in a VSCode editor pane to add a *breakpoint*,
406
+
which is visualized by a red circle.
407
+
In the debugging pane of the Julia VSCode extension,
408
+
click *Run and Debug* to start the debugger.
409
+
The program will automatically halt when it hits a breakpoint.
410
+
411
+
Using the toolbar at the top of the editor, you can
412
+
*continue*, *step over*, *step into* and *step out* of your code.
413
+
The debugger will open a pane showing information about the code
414
+
such as local variables inside of the current function,
415
+
their current values and the call stack.
416
+
417
+
For more information including explanatory screenshots,
418
+
refer to the [Julia VSCode documentation][vscode-debugger].
419
+
420
+
### Infiltrator.jl
421
+
422
+
[Infiltrator.jl's][infiltrator-repo]`@infiltrate` macro allows you to directly set breakpoints in your code.
423
+
Calling a function which hits a breakpoint will activate the Infiltrator REPL-mode
424
+
and change the prompt to `infil>`.
425
+
426
+
Typing `?` in this mode will summarize available commands.
427
+
For example, typing `@locals` in Infiltrator-mode will print local variables:
428
+
429
+
```julia
430
+
using Infiltrator
431
+
432
+
functionsum_of_divisors(n)
433
+
divisors =filter(x -> n % x ==0, 1:n)
434
+
@infiltrate
435
+
returnsum(divisors)
436
+
end
437
+
```
438
+
```julia-repl
439
+
julia> sum_of_divisors(6)
440
+
Infiltrating (on thread 1) sum_of_divisors(n::Int64)
441
+
at REPL[4]:3
442
+
443
+
infil> @locals
444
+
- n::Int64 = 6
445
+
- divisors::Vector{Int64} = [1, 2, 3, 6]
446
+
```
447
+
448
+
What makes Infiltrator powerful is the `@exfiltrate` macro,
449
+
which allows you to move local variables into a global storage called the `safehouse`.
450
+
451
+
```julia-repl
452
+
infil> @exfiltrate divisors
453
+
Exfiltrating 1 local variable into the safehouse.
454
+
455
+
infil> @continue
456
+
457
+
12
458
+
459
+
julia> safehouse.divisors
460
+
4-element Vector{Int64}:
461
+
1
462
+
2
463
+
3
464
+
6
465
+
```
466
+
467
+
### Debugger.jl
468
+
469
+
Using [Debugger.jl][debugger-repo]'s `@enter` macro, we can enter a function call and step through it.
470
+
The prompt changes to `1|debug>`, allowing you to use [Debugger.jl's commands][debugger-commands]
471
+
to step into and out of function calls, show local variables and set breakpoints.
472
+
473
+
Typing `` ` `` will change the prompt to `1|julia>`, indicating evaluation mode. Any expression typed in this mode will be evaluated in the local context.
474
+
This is useful to show local variables, as demonstrated in the following example:
475
+
476
+
```julia-repl
477
+
julia> @enter sum_of_divisors(6)
478
+
In sum_of_divisors(n) at REPL[3]:1
479
+
1 function sum_of_divisors(n)
480
+
>2 divisors = filter(x -> n % x == 0, 1:n)
481
+
3 return sum(divisors)
482
+
4 end
483
+
484
+
About to run: (typeof)(6)
485
+
1|debug> n # n: step to next line
486
+
In sum_of_divisors(n) at REPL[3]:1
487
+
1 function sum_of_divisors(n)
488
+
2 divisors = filter(x -> n % x == 0, 1:n)
489
+
>3 return sum(divisors)
490
+
4 end
491
+
492
+
About to run: (sum)([1, 2, 3, 6])
493
+
1|julia> divisors # type `, then variable name
494
+
4-element Vector{Int64}:
495
+
1
496
+
2
497
+
3
498
+
6
499
+
```
322
500
323
501
## Other languages
324
502
@@ -332,3 +510,13 @@ More generally, the startup file allows you to define your own favorite helper f
0 commit comments