New Release: Handcalcs.jl v0.3.0
Hello all,
There have been a few updates to Handcalcs.jl.
Quarto Integration
In light of the recent quarto advancements within Julia, I wanted to announce that recent updates allow handcalcs to be rendered using Quarto or weave! Here is a simple example.
Edit defaults
- cols - change the number of columns the expression returns (default = 1).
- spa - change the vertical line spacing between expressions (default = 10).
- h_env - change the environment (default = “aligned”); “align” and “align*” are other options.
Note: @handcalcs
macro can also take symbols of defined variables. See below.
a, b, c = 1, 2, 3
@handcalcs begin
a # see note above
b
c
x = 4
y = 5
z = 6
end cols=3 spa=0
Recursive functions
The @handcalcs
macro will now automatically try to “unroll” the expressions within a function when the expression has the following pattern: variable = function_name(args...; kwargs...)
. Note that this is recursive, so if you have a function that calls other functions where the expressions that call the function are of the format mentioned, it will continue to step into each function to “unroll” all expressions.
One issue that can arise are for the functions that you do not want to unroll. Consider the expression: y = sin(x)
or y = x + 5
. Both of these expressions match the format: variable = function_name(args...; kwargs...)
and would be unrolled. This would result in an error since these functions don’t have generic math expressions that can be latexified defining the function. You will need to use the not_funcs
keyword to manually tell the @handcalcs macro to pass over these functions. Some of the common math functions that you will not want to unroll are automatically passed over. See examples below.
function calc_Ix(b, h) # function defined in TestHandcalcFunctions
Ix = b*h^3/12
return Ix
end;
function calc_Is(b, h) # function defined in TestHandcalcFunctions
Ix = calc_Ix(b, h)
Iy = calc_Iy(h, b)
return Ix, Iy
end;
using TestHandcalcFunctions
x = 0
@handcalcs begin
y = sin(x)
z = cos(x)
I_x, I_y = TestHandcalcFunctions.calc_Is(5, 15)
end not_funcs = [sin cos]
In the above example sin
and cos
were passed over and calc_Is
was not. As you can see, the calc_Is
function was a function that called other functions, and the @handcalcs macro continued to step into each function to unroll all expressions. Please see below for a list of the current functions that are passed over automatically. Please submit a pull request if you would like to add more generic math functions that I have left out.
const math_syms = [
:*, :/, :^, :+, :-, :%,
:.*, :./, :.^, :.+, :.-, :.%,
:<, :>, Symbol(==), :<=, :>=,
:.<, :.>, :.==, :.<=, :.>=,
:sqrt, :sin, :cos, :tan]
Note: If the function has other function calls within it’s body that are not available in Main, then the macro will error.
- The problem is if I escape the macro to the calling scope and run the expressions with functions that were within the called function, it won’t have the function namespace. If I escape it within the function being called, it won’t have access to the @handcalc macro that does the latexifying. I am not sure of a way around this, but I think it isn’t too much of an inconvienience.
Handcalcs can now receive fields of structs
struct MyRec
b
h
end
rec = MyRec(5, 15)
@handcalcs Ix = calc_Ix(rec.b, rec.h)
Now you can take advantage of multiple dispatch more effectively!
Future Plans
- A way to break down a
\LaTeX
equation that is too long to multiple lines
- Maybe a symbolic mode that would essentially be like
@latexdefine
but you get function unrolling and multiline support.
- A way to disable @handcalcs macro if you are wanting to run script for multiple iterations and not worried about rendering all iterations. That way you get speed for those situations.
- I have also thought about adding a setting that you could change if you were within the REPL and instead of latex (since it is not very readable) to instead output a simple string instead. For example:
I_x = b*h^3/12 = 5*15^3/12 = 1406.25
.
Provide Feedback
I do plan to hopefully use this as a professional tool and want to provide a way for more documented calculation packages. I hope to get this to 1.0.0 and I welcome any ideas or reports of any bugs that you may find. Feel free to contribute as well!