Change julia promt to include evalutation numbers - julia

When debugging or running julia code in REPL, I usually see error messages showing ... at ./REPL[161]:12 [inlined].... The number 161 means the 161-th evaluation in REPL, I guess. So my question is could we show this number in julia's prompt, i.e. julia [161]> instead of julia>?

One of the advantages of Julia is its ultra flexibility. This is very easy in Julia 0.7 (nightly version).
julia> repl = Base.active_repl.interface.modes[1]
"Prompt(\"julia> \",...)"
julia> repl.prompt = () -> "julia[$(length(repl.hist.history) - repl.hist.start_idx + 1)] >"
#1 (generic function with 1 method)
julia[3] >
julia[3] >2
2
julia[4] >f = () -> error("e")
#3 (generic function with 1 method)
julia[5] >f()
ERROR: e
Stacktrace:
[1] error at .\error.jl:33 [inlined]
[2] (::getfield(, Symbol("##3#4")))() at .\REPL[4]:1
[3] top-level scope
You just need to put the first 2 lines onto your ~/.juliarc and enjoy~
Since there are several changes in the REPL after julia 0.7, these codes do not work in old versions.
EDIT: Well, actually there need a little bit more efforts to make it work in .juliarc.jl. Try this code:
atreplinit() do repl
repl.interface = Base.REPL.setup_interface(repl)
repl = Base.active_repl.interface.modes[1]
repl.prompt = () -> "julia[$(length(repl.hist.history) - repl.hist.start_idx + 1)] >"
end

Related

TypeError: in typeassert in Julia 1.6.3

I am new to Julia. I am working on a Julia package which the writer is not available.
This is the part of the code where I have a problem with:
function find_partition(model::Model, ms)
ps = Dict{Z3Expr,Vector{Int}}()
for (i, m) in enumerate(ms)
mval = Z3.eval(model, m, false)
println(ps)
println(mval)
println(typeof(mval))
if haskey(ps, mval)
push!(ps[mval], i)
else
push!(ps, mval=>Int[i])
end
end
values(ps)
end
Here is the output:
Dict{Z3.Expr, Vector{Int64}}()
1.0
Z3.ExprAllocated
ERROR: TypeError: in typeassert, expected UInt64, got a value of type UInt32
Stacktrace:
[1] hashindex(key::Z3.ExprAllocated, sz::Int64)
# Base ./dict.jl:169
[2] ht_keyindex(h::Dict{Z3.Expr, Vector{Int64}}, key::Z3.ExprAllocated)
# Base ./dict.jl:284
[3] haskey(h::Dict{Z3.Expr, Vector{Int64}}, key::Z3.ExprAllocated)
# Base ./dict.jl:550
[4] find_partition(model::Z3.ModelAllocated, ms::Vector{Z3.ExprAllocated})
# Absynth.NLSat ~/Desktop/faoc/Absynth/src/nlsat/cfinitesolver.jl:101
I tried following it and found out that somewhere inside dict.jl in Julia, there are such lines
sz = length(h.keys)
...
index = hashindex(key, sz)
And this is the hashindex written somewhere in dict.jl:
hashindex(key, sz) = (((hash(key)::UInt % Int) & (sz-1)) + 1)::Int
It seems that the version of Z3 used in this package is not compatible with the current version of Julia. I am not sure if this package was working in the beginning at all.
Is there any quick fix to this? Like rewriting this part of the code:
if haskey(ps, mval)
push!(ps[mval], i)
else
push!(ps, mval=>Int[i])
in a way that this won't happen? I tried writing like merge!(ps,Dict(mval=>Int[i])) but it's eventually reaching this hashindex function again.
If I install the older versions of Julia, would it be possible to solve this issue or the problem is somewhere else?

Julia Metaprogramming: Function for Mathematical Series

I'm trying to build a function that will output an expression to be assigned to a new in-memory function. I might be misinterpreting the capability of metaprogramming but, I'm trying to build a function that generates a math series and assigns it to a function such as:
main.jl
function series(iter)
S = ""
for i in 1:iter
a = "x^$i + "
S = S*a
end
return chop(S, tail=3)
end
So, this will build the pattern and I'm temporarily working with it in the repl:
julia> a = Meta.parse(series(4))
:(x ^ 1 + x ^ 2 + x ^ 3 + x ^ 4)
julia> f =eval(Meta.parse(series(4)))
120
julia> f(x) =eval(Meta.parse(series(4)))
ERROR: cannot define function f; it already has a value
Obviously eval isn't what I'm looking for in this case but, is there another function I can use? Or, is this just not a viable way to accomplish the task in Julia?
The actual error you get has to do nothing with metaprogramming, but with the fact that you are reassigning f, which was assigned a value before:
julia> f = 10
10
julia> f(x) = x + 1
ERROR: cannot define function f; it already has a value
Stacktrace:
[1] top-level scope at none:0
[2] top-level scope at REPL[2]:1
It just doesn't like that. Call either of those variables differently.
Now to the conceptual problem. First, what you do here is not "proper" metaprogramming in Julia: why deal with strings and parsing at all? You can work directly on expressions:
julia> function series(N)
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :(x ^ $i))
end
return S
end
series (generic function with 1 method)
julia> series(3)
:(x ^ 1 + x ^ 2 + x ^ 3)
This makes use of the fact that + belongs to the class of expressions that are automatically collected in repeated applications.
Second, you don't call eval at the appropriate place. I assume you meant to say "give me the function of x, with the body being what series(4) returns". Now, while the following works:
julia> f3(x) = eval(series(4))
f3 (generic function with 1 method)
julia> f3(2)
30
it is not ideal, as you newly compile the body every time the function is called. If you do something like that, it is preferred to expand the code once into the body at function definition:
julia> #eval f2(x) = $(series(4))
f2 (generic function with 1 method)
julia> f2(2)
30
You just need to be careful with hygiene here. All depends on the fact that you know that the generated body is formulated in terms of x, and the function argument matches that. In my opinion, the most Julian way of implementing your idea is through a macro:
julia> macro series(N::Int, x)
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :($x ^ $i))
end
return S
end
#series (macro with 1 method)
julia> #macroexpand #series(4, 2)
:(2 ^ 1 + 2 ^ 2 + 2 ^ 3 + 2 ^ 4)
julia> #series(4, 2)
30
No free variables remaining in the output.
Finally, as has been noted in the comments, there's a function (and corresponding macro) evalpoly in Base which generalizes your use case. Note that this function does not use code generation -- it uses a well-designed generated function, which in combination with the optimizations results in code that is usually equal to the macro-generated code.
Another elegant option would be to use the multiple-dispatch mechanism of Julia and dispatch the generated code on type rather than value.
#generated function series2(p::Val{N}, x) where N
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :(x ^ $i))
end
return S
end
Usage
julia> series2(Val(20), 150.5)
3.5778761722367333e43
julia> series2(Val{20}(), 150.5)
3.5778761722367333e43
This task can be accomplished with comprehensions. I need to RTFM...
https://docs.julialang.org/en/v1/manual/arrays/#Generator-Expressions

How do I retrieve keyword arguments out of a field of splatted kwargs?

If I have a function signature like f(args...; kwargs...), how can I get a specific keyword out of kwargs? Naïvely typing kwargs.x does not work:
julia> f(args...; kwargs...) = kwargs.x
f (generic function with 1 method)
julia> f(x=1)
ERROR: type Pairs has no field x
Stacktrace:
[1] getproperty(::Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:x,),Tuple{Int64}}}, ::Symbol) at ./Base.jl:20
[2] #f#7(::Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:x,),Tuple{Int64}}}, ::typeof(f)) at ./REPL[2]:1
[3] (::var"#kw##f")(::NamedTuple{(:x,),Tuple{Int64}}, ::typeof(f)) at ./none:0
[4] top-level scope at REPL[3]:1
This question appeared on the JuliaLang Slack channel in the #helpdesk. For an automatic invite to the very helpful julia slack, simply fill out https://slackinvite.julialang.org
The reason this happens is that splatted keyword arguments are not stored in a named tuple by default. We can see how they're stored like so:
julia> g(;kwargs...) = kwargs
g (generic function with 1 method)
julia> g(a=1)
pairs(::NamedTuple) with 1 entry:
:a => 1
julia> g(a=1) |> typeof
Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:a,),Tuple{Int64}}}
So the splatted kwargs are instead stored as some sort of iterator object. However, we can easily convert that kwargs iterator to a NamedTuple like so: (;kwargs...) and then access it in the way we'd expect, so your example would translate into
julia> f(args...; kwargs...) = (;kwargs...).x
f (generic function with 1 method)
julia> f(x=1, y=2)
1
Of course, the more idiomatic way to do this would be to instead write the function as
julia> f(args...; x, kwargs...) = x
f (generic function with 1 method)
julia> f(x=1, y=2)
1
but this assumes you know the name you want to access (x) at the time when you write the function.
A brief sidenote: If we return to our example of g(;kwargs...) = kwargs, we can ask for the fieldnames of the iterator object the was returned like so:
julia> g(x=1, y=2) |> typeof |> fieldnames
(:data, :itr)
Hm, what is this data field?
julia> g(x=1, y=2).data
(x = 1, y = 2)
Aha! so we can actually get the kwargs as a named tuple using that, i.e. f(;kwargs...) = kwargs.data.x would work, but I wouldn't recommend this approach since it seems to rely on undocumented behaviour, so it may be a mere implementation detail that is not guaranteed to be stable across julia versions.

Getting the whole AST of the file / complex code

Julia manual states:
Every Julia program starts life as a string:
julia> prog = "1 + 1"
"1 + 1"
I can easily get the AST of the simple expression, or even a function with the help of quote / code_*, or using Meta.parse / Meta.show_sexpr if I have the expression in a string.
The question: Is there any way to get the whole AST of the codepiece, possibly including several atomic expressions? Like, read the source file and convert it to AST?
If you want to do this from Julia instead of FemtoLisp, you can do
function parse_file(path::AbstractString)
code = read(path, String)
Meta.parse("begin $code end")
end
This takes in a file path, reads it and parses it to a big expression that can be evaluated.
This comes from #NHDaly's answer, here:
https://stackoverflow.com/a/54317201/751061
If you already have your file as a string and don’t want to have to read it again, you can instead do
parse_all(code::AbstractString) = Meta.parse("begin $code end")
It was pointed out on Slack by Nathan Daly and Taine Zhao that this code won't work for modules:
julia> eval(parse_all("module M x = 1 end"))
ERROR: syntax: "module" expression not at top level
Stacktrace:
[1] top-level scope at REPL[50]:1
[2] eval at ./boot.jl:331 [inlined]
[3] eval(::Expr) at ./client.jl:449
[4] |>(::Expr, ::typeof(eval)) at ./operators.jl:823
[5] top-level scope at REPL[50]:1
This can be fixed as follows:
julia> eval_all(ex::Expr) = ex.head == :block ? for e in ex eval_all(e) end : eval(e);
julia> eval_all(ex::Expr) = ex.head == :block ? eval.(ex.args) : eval(e);
julia> eval_all(parse_all("module M x = 1 end"));
julia> M.x
1
Since the question asker is not convinced that the above code produces a tree, here is a graph representation of the output of parse_all, clearly showing a tree structure.
In case you're curious, those leaves labelled #= none:1 =# are line number nodes, indicating the line on which each following expression takes place.
As suggested in the comments, one can also apply Meta.show_sexpr to an Expr object to get a more "lispy" representation of the AST without all the pretty printing julia does by default:
julia> (Meta.show_sexpr ∘ Meta.parse)("begin x = 1\n y = 2\n z = √(x^2 + y^2)\n end")
(:block,
:(#= none:1 =#),
(:(=), :x, 1),
:(#= none:2 =#),
(:(=), :y, 2),
:(#= none:3 =#),
(:(=), :z, (:call, :√, (:call, :+, (:call, :^, :x, 2), (:call, :^, :y, 2))))
)
There's jl-parse-file in the FemtoLisp implementation of the Julia parser. You can call it from the Lisp REPL (julia --lisp), and it returns an S-expression for the whole file. Since Julia's Expr is not much different from Lisp S-expressions, that might be enough for you purposes.
I still wonder how one would access the result of this from within Julia. If I understand correctly, the Lisp functions are not exported from libjulia, so there's no direct way to just use a ccall. But maybe a variant of jl_parse_eval_all can be implemented.

A simple interpolation using expressions in julia

I would like to form expressions like
julia> ex = :(a[$i,$j] + b[$i,$j])
because I am interested in writting a program that it is able to write a system of equations in which the user only gives the structure of them and then that julia writes explicitly the chunk of code involved. More generally, I would like to embed functions in a expression, something like
julia> ex = :(a[$myfunc(i,j),$j] + b[$i,$j])
Upon evaluating the first line of code, I get
ERROR: UndefVarError: i not defined
in eval(::Module, ::Any) at ./boot.jl:226
On the other hand, if I write
julia> ex = :(a[i,j] + b[i,j])
:(a[i,j] + b[i,j])
julia> for i in 1:2
for j in 1:2
println(eval(ex))
end
end
ERROR: UndefVarError: i not defined
in eval(::Module, ::Any) at ./boot.jl:226
[inlined code] from ./boot.jl:225
in anonymous at ./<no file>:4294967295
in eval(::Module, ::Any) at ./boot.jl:226
How is interpolation done in this case?
eval works at global scope, so it cannot reference any local variables. What you can do, however, is interpolate that expression into a larger chunk of code that's intended to be executed at the global scope:
julia> a = [1 2; 3 4]
b = [5 6; 7 8]
ex = :(a[i,j] + b[i,j]);
julia> #eval for i in 1:2
for j in 1:2
println($ex)
end
end
6
8
10
12
The #eval macro is a simple shorthand for quoting the passed syntax and passing it along to the eval() function. It'd probably even be better to define a custom function:
julia> #eval function f()
for i in 1:2
for j in 1:2
println($ex)
end
end
end
f (generic function with 1 method)
julia> f()
6
8
10
12
The usual caveats about eval apply: any passed code can be maliciously crafted to do nefarious or surprising things. Or just crash the program.

Resources