NahaJuliaLib.jl

NahaJuliaJib is a library of small utilities that I wish Julia had, but, near as I can tell, doesn't yet.

Type Hierarchy

Defining Object Properties

Rather than use a condirional tree to determine which peoperty is being queried by getproperty, we can method specialize on Val types. We should then be able to automate propertynames based on the defined methods.

A struct might have fields, which are exposed as properties. The Val methods will not shadow the method that implements that.

NahaJuliaLib.@njl_getpropMacro
@njl_getprop MyStruct

Define the methods necessary so that Val specialized getproperty methods for MyStruct will find Val specialized properties.

source

Here's a trivial, but illustrative example:

using NahaJuliaLib

struct MyStruct
    a::Int
end

@njl_getprop MyStruct

function Base.getproperty(o::MyStruct, prop::Val{:b})
    o.a * 2
end

ms = MyStruct(3)
MyStruct(3)

ms.a

ms.b

propertynames(ms)
2-element Vector{Symbol}:
 :a
 :b

Tracing functions

Sometimes when debugging one wants to track the call and return of certain specified functions.

NahaJuliaLib.@traceMacro
@trace(global_flag, definition)

Cause the call arguments and return values of the function defined by definition to be logged if global_flag is true at run time. definition should define a method.

source
NahaJuliaLib.analyze_tracesFunction
analyze_traces(log::VectorLogger)

Given a log containinig log records produced by @trace, return a vector of TraceRecords. Each of those TraceRecords is the root of a tree of TraceRecords that represent the call tree.

Use show_trace to print the call hierarchy in a human readable form.

source
using Logging
using VectorLogging
using NahaJuliaLib

@trace(trace_hanoi,
       function hanoi(from, to, other, count)
           if count == 0
               return nothing
           else
               hanoi(from, other, to, count - 1)
               println("move 1 from $from to $to")
               hanoi(other, to, from, count - 1)
               return (from, to)   # arbitrary result to show
           end
       end
       )

trace_hanoi = true

logger = VectorLogger()

with_logger(logger) do
    hanoi(:a, :b, :c, 3)
end

begin
    traces = analyze_traces(logger)
    show_trace(traces[1])
end
move 1 from a to b
move 1 from a to c
move 1 from b to c
move 1 from a to b
move 1 from c to a
move 1 from c to b
move 1 from a to b
(Main.hanoi)(a, b, c, 3) => (:a, :b)
  (Main.hanoi)(a, c, b, 2) => (:a, :c)
    (Main.hanoi)(a, b, c, 1) => (:a, :b)
      (Main.hanoi)(a, c, b, 0) => nothing
      (Main.hanoi)(c, b, a, 0) => nothing
    (Main.hanoi)(b, c, a, 1) => (:b, :c)
      (Main.hanoi)(b, a, c, 0) => nothing
      (Main.hanoi)(a, c, b, 0) => nothing
  (Main.hanoi)(c, b, a, 2) => (:c, :b)
    (Main.hanoi)(c, a, b, 1) => (:c, :a)
      (Main.hanoi)(c, b, a, 0) => nothing
      (Main.hanoi)(b, a, c, 0) => nothing
    (Main.hanoi)(a, b, c, 1) => (:a, :b)
      (Main.hanoi)(a, c, b, 0) => nothing
      (Main.hanoi)(c, b, a, 0) => nothing