Can't figure out how to index a Dict with a Symbol - julia

I'm reading "Getting Started with Julia" book and it has the following example:
d3 = [:A => 100, :B => 200]
d3[:C] = 300
When I run it, I get an error
ERROR: ArgumentError: invalid index: C
Stacktrace:
[1] setindex!(::Array{Pair{Symbol,Int64},1}, ::Int64, ::Symbol) at .\abstractarray.jl:967
The book is for an earlier version of Julia, but I can't find anywhere in the manuals how to address Dict items by Symbol correctly in the current version.

Related

Julia: how to get an error message and stacktrace as string?

I am trying to get an error message of a caught exception for use in a warning.
For example, while following
julia> a = 3+b
ERROR: UndefVarError: b not defined
Stacktrace:
[1] top-level scope
# REPL[1]:1
says that the problem is that b is not defined, the following method of handling exception has much less helpful message:
julia> try
a = 3+b
catch e
#warn "Bad thing happend: $e"
end
┌ Warning: Bad thing happend: UndefVarError(:b)
└ # Main REPL[2]:4
How do I get the error message and stacktrace from the exception as String?
While a bit wordy, the answer seems to be by using the Base.showerror(io::IO, err::MyException) function defined for builtin exceptions:
julia> try
a = 3+b
catch e
io = IOBuffer();
showerror(io, e)
error_msg = String(take!(io))
#warn "Trouble doing things:\n$(error_msg)"
end
┌ Warning: Trouble doing things:
│ UndefVarError: b not defined
└ # Main REPL[3]:7
To also get the stacktrace:
use stacktrace(catch_backtrace()) to get the stacktrace vector from the place exception was thrown (see docs)
use show(io, mime, x) to format the vector nicely (see this SO answer)
Combining the two with the sprint that handles the IOBuffer for us, we get to:
julia> try
a = 3+b
catch e
error_msg = sprint(showerror, e)
st = sprint((io,v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
#warn "Trouble doing things:\n$(error_msg)\n$(st)"
end
┌ Warning: Trouble doing things:
│ UndefVarError: b not defined
│ 13-element Vector{Base.StackTraces.StackFrame}:
│ top-level scope at REPL[4]:2
│ eval at boot.jl:373 [inlined]
│ ...
└ # Main REPL[4]:6

ERROR: LoadError: UndefVarError: type not defined

I am working in Julia and I'm trying to use Documenter.jl to create a documentation page for Examples.jl and I keep getting this error when I try to run my make.jl file:
ERROR: LoadError: UndefVarError: type not defined
Here is my code for the make.jl file:
using Documenter
using Examples
makedocs(
sitename = "Examples.jl",
pages = Any[
"About" => "index.md",
"Main" => "main.md",
"Graphs" => "graphs.md",
"Utilities" => "utilities.md",
"Tutorial" => "tutorial.md"
]
)
Any ideas how to fix this error? Thanks
As #Matt B. pointed out, type is no longer a valid keyword. In Julia 0.x you used to define types as:
type foo
bar
end
Now we use struct or mutable struct instead. e.g.
struct foo
bar
end
Go through your code and see if you see type anywhere.

Why I cannot create a simple dictionary here

I am trying to create and use a simple dictionary using TFPGmap:
program rnTFPGmap;
{$mode objfpc}
uses fgl;
var
mydict: specialize TFPGmap<string, string>;
key: string;
i: longint;
begin
mydict.create;
mydict.add('k1','v1');
mydict.add('k2','v2');
mydict.add('k3','v3');
//for key in mydict.keys do {does not work either;}
for i := 1 to length(mydict) do {line 17: first error from here. }
writeln(mydict[i]);
end.
However, it is giving following error:
$ fpc soq_rntfpgmap
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling soq_rntfpgmap.pas
soq_rntfpgmap.pas(17,16) Error: Type mismatch
soq_rntfpgmap.pas(18,19) Error: Incompatible type for arg no. 1: Got "LongInt", expected "ShortString"
soq_rntfpgmap.pas(22) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Edit: I tried to modify the code according to documentation and came up with following version:
program rnTFPGmap;
{$mode objfpc}
uses fgl;
type
tuple = specialize TFPGmap<string, string>;
mydict = Array of tuple;
var
dict: mydict;
i: tuple;
item: string;
begin
setlength(dict, length(dict)+3);
dict.add('k1','v1'); {error on this line: "CREATE" expected but "ADD" found}
dict.add('k2','v2');
dict.add('k3','v3');
writeln('dict.count: ', dict.count);
for i in dict do
writeln(i);
end.
But I am now getting following error:
$ fpc soq_rntfpgmap
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling soq_rntfpgmap.pas
soq_rntfpgmap.pas(13,25) Warning: Variable "dict" of a managed type does not seem to be initialized
soq_rntfpgmap.pas(14,7) Fatal: Syntax error, "CREATE" expected but "ADD" found
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Not able to sort this out.
Following code works. See comments for some explanations:
program rnTFPGmap;
{$mode objfpc}
uses fgl;
type
Rndict = specialize TFPGmap<string, string>;{define type under type}
var
dict: Rndict; {define object under var}
i: integer;
{main: }
begin
dict := Rndict.Create; {create object in main}
dict.add('k1','v1');
dict.add('k2','v2');
dict.add('k3','v3');
for i := 0 to (dict.count-1) do begin
writeln('i: ',i, '; key: ', dict.getkey(i), '; value: ', dict.getdata(i));
end;
end.
Output:
i: 0; key: k1; value: v1
i: 1; key: k2; value: v2
i: 2; key: k3; value: v3
I thank #DavidHeffernan for his guidance.

Bugzilla throws error when migrating from an old version

I am trying to migrate from an old bugzilla to a newer one. I installed a newer one on a new server. I run ./checksetup.pl and this is the error:
A valid TYPE was not specified for this column (got $VAR1 = {'PRIMARYKEY' => 1,'ENGINE' => 'MEDIUMSERIAL','NOTNULL' => 1};
) at Bugzilla/DB/Schema.pm line 1975.
Bugzilla::DB::Schema::get_type_ddl('Bugzilla::DB::Schema::Mysql=HASH(0x8 120cd8)', 'HASH(0x8261308)') called at Bugzilla/DB/Schema/Mysql.pm line 380
Bugzilla::DB::Schema::Mysql::get_rename_column_ddl('Bugzilla::DB::Schema ::Mysql=HASH(0x8120cd8)', 'fielddefs', 'fieldid', 'id') called at Bugzilla/DB.pm line 1026
Bugzilla::DB::bz_rename_column('Bugzilla::DB::Mysql=HASH(0x7fed8c0)', 'f ielddefs', 'fieldid', 'id') called at Bugzilla/Install/DB.pm line 69
Bugzilla::Install::DB::update_fielddefs_definition() called at ./checkse tup.pl line 164

Is there any way to build package dependency tree in julia-lang?

Using npm list will show a tree of installed packages, versions and relations:
Although Julia package management is differ (e.g normally no duplicate copy of a package exists), But is there any way to:
Know why one package have been installed?
or build a package dependency tree.
I don't think there's a simple function, but it shouldn't be too hard to do with these two functions:
julia> Pkg.dependents("Cairo")
10-element Array{AbstractString,1}:
"Tk"
"Gtk"
"Mamba"
"Drawing"
"GtkUtilities"
"ProfileView"
"Brim"
"Winston"
"EcologicalNetwork"
"VennEuler"
julia> Pkg.installed()
Dict{ASCIIString,VersionNumber} with 119 entries:
"Libz" => v"0.0.2"
"Gtk" => v"0.9.3"
"Interact" => v"0.3.0"
"ForwardDiff" => v"0.1.4"
"Benchmark" => v"0.1.0"
"AxisAlgorithms" => v"0.1.4"
"Cairo" => v"0.2.31+"
"HttpParser" => v"0.1.1"
"DataFrames" => v"0.6.10"
"Requests" => v"0.3.4"
"QuartzImageIO" => v"0.1.0+"
"Markdown" => v"0.3.0"
"Requires" => v"0.2.2"
"ArgParse" => v"0.3.0"
⋮ => ⋮
simple code bellow will printout the requires-by result for a package:
whorequires(pkgname) = whorequires(pkgname, 0);
function whorequires(pkgname, i)
deps = Pkg.dependents(pkgname);
[print('-') for j=1:i];
println(pkgname);
length(deps) > 0 && [whorequires(dep,i+1) for dep in deps];
end
julia> whorequires("JuliaParser");
JuliaParser
-CodeTools
--Atom
-ASTInterpreter
--Gallium
-Jewel
EDIT (to cover issue commented by #amrods)
whorequires(pkgname) = whorequires(pkgname, 0, Dict{ASCIIString,Vector{ASCIIString}}());
function whorequires(pkgname, i, m)
[print('-') for j=1:i];
if (haskey(m,pkgname))
println("$pkgname *[duplicated]* is required by ", length(m[pkgname]), " packages");
else
println(pkgname);
m[pkgname] = Pkg.dependents(pkgname);
if (length(m[pkgname]) > 0)
for dep in m[pkgname]
whorequires(dep,i+1,m);
end
end
end
end
There is a package, although not registered, which does this: https://github.com/peng1999/PkgDependency.jl
It's quite straightforward to use
pkg> add https://github.com/peng1999/PkgDependency.jl
julia> using PkgDependency
julia> PkgDependency.tree("HTTP")
HTTP v0.9.13
NetworkOptions v1.2.0
IniFile v0.5.0
URIs v1.3.0
MbedTLS v1.0.3
MbedTLS_jll v2.16.8+1
JLLWrappers v1.3.0
Preferences v1.2.2
TOML v1.0.3
Artifacts v1.3.0
It relies on a new (>1.4) experimental API, which can be used on its own to list (direct) dependencies, but it's quite ugly:
julia> using Pkg
julia> Pkg.dependencies()[Pkg.project().dependencies["HTTP"]].dependencies
Dict{String, Base.UUID} with 5 entries:
"Dates" => UUID("ade2ca70-3891-5945-98fb-dc099432e06a")
"Base64" => UUID("2a0f44e3-6c83-55bd-87e4-b1978d98bd5f")
"Sockets" => UUID("6462fe0b-24de-5631-8697-dd941f90decc")
"IniFile" => UUID("83e8ac13-25f8-5344-8a64-a9f2b223428f")
"MbedTLS" => UUID("739be429-bea8-5141-9913-cc70e7f3736d")
If you only want the list for dependencies of the currently active project, then Pkg.project().dependencies is enough.
I've opened a Pkg.jl issue to discuss this here.

Resources