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
Copy file name to clipboardExpand all lines: docs/src/lectures/lecture_06/lecture.md
+49-45Lines changed: 49 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -318,17 +318,19 @@ and the output is used mainly for debugging / inspection.
318
318
Language introspection is very convenient for investigating, how things are implemented and how they are optimized / compiled to the native code.
319
319
320
320
::: note "Reminder `@which`"
321
-
Though we have already used it quite a few times, recall the very useful macro`@which`, which identifies the concrete function called in a function call. For example `@which mapreduce(sin, +, [1,2,3,4])`. Note again that the macro here is a convenience macro to obtain types of arguments from the expression. Under the hood, it calls `InteractiveUtils.which(function_name, (Base.typesof)(args...))`. Funny enough, you can call `@which InteractiveUtils.which(+, (Base.typesof)(1,1))` to inspect, where`which` is defined.
321
+
Though we have already used it quite a few times, recall the very useful macro`@which`, which identifies the concrete function called in a function call. For example `@which mapreduce(sin, +, [1,2,3,4])`. Note again that the macro here is a convenience macro to obtain types of arguments from the expression. Under the hood, it calls `InteractiveUtils.which(function_name, (Base.typesof)(args...))`. Funny enough, you can call `@which InteractiveUtils.which(+, (Base.typesof)(1,1))` to inspect, where`which` is defined.
322
322
323
-
Alternatively, you can invest time in learning `Cthulhu.jl` package, which is a tool for inspecting functions called in a function. In other words it will simplify a recursive call of which when one is interested in how internals of some function are implemented.
323
+
Alternatively, you can invest time in learning `Cthulhu.jl` package, which is a tool for inspecting functions called in a function. In other words it will simplify a recursive call of which when one is interested in how internals of some function are implemented.
324
+
:::
324
325
325
326
::: note "Effect analysis"
326
-
The compiler is analysing the code to automatically infer some properties, which can help it to create more efficient code. This is analysis id called effect analysis and you can execute it yourself using`Base.infer_effects`. For example for our `nextfib` we obtain (on 1.11.1)
327
-
```julia
328
-
julia> Base.infer_effects(nextfib, (Int,))
329
-
(+c,+e,+n,!t,+s,+m,+u,+o,+r)
330
-
```
331
-
See the documentation for (Base.@assume_effects)[https://docs.julialang.org/en/v1/base/base/#Base.@assume_effects] for details of individual fields.
327
+
The compiler is analysing the code to automatically infer some properties, which can help it to create more efficient code. This is analysis id called effect analysis and you can execute it yourself using`Base.infer_effects`. For example for our `nextfib` we obtain (on 1.11.1)
328
+
```julia
329
+
julia> Base.infer_effects(nextfib, (Int,))
330
+
(+c,+e,+n,!t,+s,+m,+u,+o,+r)
331
+
```
332
+
See the documentation for (Base.@assume_effects)[https://docs.julialang.org/en/v1/base/base/#Base.@assume_effects] for details of individual fields.
333
+
:::
332
334
333
335
### Broadcasting
334
336
Broadcasting is not a unique concept in programming languages (Python/Numpy, MATLAB), however its implementation in Julia allows to easily fuse operations. For example
`Cthulhu.jl` is a library (tool) which simplifies the above, where we want to iteratively dive into functions called in some piece of code (typically some function).`Cthulhu` is different from te normal debugger, since the debugger is executing the code, while`Cthulhu` is just lower_typing the code and presenting functions (with type of arguments inferred).
404
+
::: info Cthulhu.jl
405
+
`Cthulhu.jl` is a library (tool) which simplifies the above, where we want to iteratively dive into functions called in some piece of code (typically some function).`Cthulhu` is different from te normal debugger, since the debugger is executing the code, while`Cthulhu` is just lower_typing the code and presenting functions (with type of arguments inferred).
406
+
:::
405
407
406
408
```julia
407
409
using Cthulhu
@@ -468,57 +470,59 @@ The parsed code `p` is of type `Expr`, which according to Julia's help[^2] is *a
When manipulations of expressions, we encounter the term `Symbol`. `Symbol` is the smallest atom from which the program (in AST representation) is built. It is used to identify an element in the language, for example variable, keyword or function name. Symbol is not a string, since string represents itself, whereas `Symbol` can represent something else (a variable). An illustrative example[^3] goes as follows.
472
-
```julia
473
-
julia> eval(:foo)
474
-
ERROR: foo not defined
473
+
When manipulations of expressions, we encounter the term `Symbol`. `Symbol` is the smallest atom from which the program (in AST representation) is built. It is used to identify an element in the language, for example variable, keyword or function name. Symbol is not a string, since string represents itself, whereas `Symbol` can represent something else (a variable). An illustrative example[^3] goes as follows.
474
+
```julia
475
+
julia> eval(:foo)
476
+
ERROR: foo not defined
475
477
476
-
julia> foo = "hello"
477
-
"hello"
478
+
julia> foo = "hello"
479
+
"hello"
478
480
479
-
julia> eval(:foo)
480
-
"hello"
481
+
julia> eval(:foo)
482
+
"hello"
481
483
482
-
julia> eval("foo")
483
-
"foo"
484
-
```
485
-
which shows that what the symbol `:foo` evaluates to depends on what – if anything – the variable `foo` is bound to, whereas "foo" always just evaluates to "foo".
484
+
julia> eval("foo")
485
+
"foo"
486
+
```
487
+
which shows that what the symbol `:foo` evaluates to depends on what – if anything – the variable `foo` is bound to, whereas "foo" always just evaluates to "foo".
486
488
487
-
Symbols can be constructed either by prepending any string with `:` or by calling `Symbol(...)`, which concatenates the arguments and create the symbol out of it. All of the following are symbols
488
-
```julia
489
-
julia> :+
490
-
:+
489
+
Symbols can be constructed either by prepending any string with `:` or by calling `Symbol(...)`, which concatenates the arguments and create the symbol out of it. All of the following are symbols
Symbols therefore allows us to operate with a piece of code without evaluating it.
506
+
julia> Symbol("Symbol with blanks")
507
+
Symbol("Symbol with blanks")
508
+
```
509
+
Symbols therefore allows us to operate with a piece of code without evaluating it.
508
510
509
-
In Julia, symbols are "interned strings", which means that compiler attaches each string a unique identifier (integer), such that it can quickly compare them. Compiler uses Symbols exclusively and the important feature is that they can be quickly compared. This is why people like to use them as keys in`Dict`.
511
+
In Julia, symbols are "interned strings", which means that compiler attaches each string a unique identifier (integer), such that it can quickly compare them. Compiler uses Symbols exclusively and the important feature is that they can be quickly compared. This is why people like to use them as keys in`Dict`.
512
+
:::
510
513
511
514
[^3]: An [example](https://stackoverflow.com/questions/23480722/what-is-a-symbol-in-julia) provided by Stefan Karpinski.
512
515
513
516
::: info "Expressions"
514
-
From Julia's help[^2]:
517
+
From Julia's help[^2]:
515
518
516
-
`Expr(head::Symbol, args...)`
519
+
`Expr(head::Symbol, args...)`
517
520
518
-
A type representing compound expressions in parsed julia code (ASTs). Each expression consists of a head `Symbol` identifying which kind of expression it is (e.g. a call, for loop, conditional statement, etc.), and subexpressions (e.g. the arguments of a call).
519
-
The subexpressions are stored in a `Vector{Any}` field called args.
521
+
A type representing compound expressions in parsed julia code (ASTs). Each expression consists of a head `Symbol` identifying which kind of expression it is (e.g. a call, for loop, conditional statement, etc.), and subexpressions (e.g. the arguments of a call).
522
+
The subexpressions are stored in a `Vector{Any}` field called args.
520
523
521
-
The expression is simple yet very flexible. The head `Symbol` tells how the expression should be treated and arguments provide all needed parameters. Notice that the structure is also type-unstable. This is not a big deal, since the expression is used to generate code, hence it is not executed repeatedly.
524
+
The expression is simple yet very flexible. The head `Symbol` tells how the expression should be treated and arguments provide all needed parameters. Notice that the structure is also type-unstable. This is not a big deal, since the expression is used to generate code, hence it is not executed repeatedly.
525
+
:::
522
526
523
527
## Construct code from scratch
524
528
Since `Expr` is a Julia structure, we can construct it manually as we can construct any other structure
0 commit comments