User Tools

Site Tools


baffling

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

baffling [2018/11/20 13:44] (current)
Line 1: Line 1:
 +
 +~~CLOSETOC~~
 +
 +~~TOC 1-3 wide~~
 +
 +
 +# Common and Baffling Errors
 +
 +Julia is an unusual language in many respects. ​ It is also very novel both for the (rather creative) developers and for its users. ​ This is a collection of common errors and/or weird and unintuitive outcomes.
 +
 +The [Julia FAQ](https://​docs.julialang.org/​en/​v1.0/​) covers many other such issues.
 +
 +For now, the following collection is unordered. ​ They will be ordered as a final step.
 +
 +
 +
 +## Confusing Types and Objects of Types
 +
 +This is a common beginner'​s mistake.
 +
 +|  **statement** ​ |  **result** ​ |  **explanation** ​ |
 +| `v= Float64` | a type | desired? v is now an alias for a type. `x= v(1)` now converts integer to Float64 |
 +| `v= Float64(NaN)` | an initialized variable | v is a now a variable initialized with NaN. |
 +
 +[[inquiring|Inquiring]] explained how you can learn more about both types and variables (use `dump()`).
 +
 +
 +
 +## Local and Global Variables
 +
 +WARNING This is currently changing.
 +
 +```juliarepl
 +julia> beforefor= true;
 +
 +julia> for i in 1:2; beforefor= false; end#for#
 +
 +julia> beforefor
 +true
 +
 +julia> beforeif= true;
 +
 +julia> if (true); beforeif= false; end#if#
 +false
 +
 +julia> beforeif
 +false
 +
 +```
 +
 +* `Module.x= 2` fails, because global assignment only works module-local.
 +
 +
 +
 +## "​Typos"​
 +
 +### Comma is not a Semicolon Statement Operator
 +
 +```juliarepl
 +julia> tmp= ax; ax= bx, bx= tmp
 +ERROR: UndefVarError:​ ax not defined
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +* The middle part means `ax=(bx,​bx)`,​ not `( ax=bx ),`.
 +
 +
 +### Semicolon Error in Iterator
 +
 +```juliarepl
 +julia> for i= -1:0.5;1; (i>0) && info("​Found You!"​);​ end#for#
 +
 +julia> for i= -1.0:​0.5;​1.0;​ @info("​Found $i"); end;
 +[ Info: Found -1.0
 +[ Info: Found 0.0
 +
 +```
 +
 +Look closely at the iterator. ​ You probably meant
 +
 +```juliarepl
 +julia> for i= -1.0:​0.5:​1.0;​ @info("​Found $i"); end;
 +[ Info: Found -1.0
 +[ Info: Found -0.5
 +[ Info: Found 0.0
 +[ Info: Found 0.5
 +[ Info: Found 1.0
 +
 +```
 +
 +
 +### Confusing Periods (in or not in Numbers)
 +
 +```juliarepl
 +julia> 1.+2
 +ERROR: syntax: invalid syntax "​1.+";​ add space(s) to clarify
 +
 +```
 +
 +It could have been `1.0+2` (which is Float64 `3.0`) or `1 .+ 2` (which is Int `3`).
 +
 +
 +### Precedence of Multiplication and Importance of Clarifying Space
 +
 +```juliarepl
 +julia> x=2;
 +
 +julia> ( 3^2x , 3^2*x)
 +(81, 18)
 +```
 +
 +* `3^2 x` is a syntax error.
 +
 +
 +
 +
 +
 +## Control Flow
 +
 +### Looping Over Strings vs. Characters in Strings
 +
 +```juliarepl
 +julia> for i in ("​hi",​); ​ println(i); end
 +hi
 +
 +julia> for i in ("​hi"​); ​ println(i); end
 +h
 +i
 +
 +```
 +
 +### Precedence of `&&​`
 +
 +```juliarepl
 +julia> x= 2;  (true) && x= 3
 +ERROR: syntax: invalid assignment location "true && x"
 +```
 +
 +* This means `((true) && x)= 3`, and not `(true) && (x=3)`.
 +
 +
 +
 +
 +### Iterating Over (Solo-) Tuples
 +
 +```juliarepl
 +julia> for i in (1); println(i); end ## a solo works
 +1
 +
 +julia> for i in (:ab,:cd); println(i); end ## a tuple works
 +ab
 +cd
 +
 +julia> for i in (:ab,); println(i); end ## a clearly designated solo tuple
 +ab
 +
 +julia> for i in (:ab); println(i); end ## but this is a solo ':​ab'​
 +ERROR: MethodError:​ no method matching iterate(::​Symbol)
 +Closest candidates are:
 +  iterate(!Matched::​Core.SimpleVector) at essentials.jl:​589
 +  iterate(!Matched::​Core.SimpleVector,​ !Matched::​Any) at essentials.jl:​589
 +  iterate(!Matched::​ExponentialBackOff) at error.jl:​171
 +  ...
 +Stacktrace:
 + [1] top-level scope at ./none:0
 +
 +```
 +
 +
 +
 +
 +
 +
 +
 +
 +## Functions
 +
 +* Functions can modify their arguments...as long as these arguments are not scalars (e.g., Float) but arrays, structs, dicts, etc.  Be careful. ​ Very careful. ​ Be afraid. ​ Very afraid.
 +
 +### Modifying Const Function Arguments
 +
 +```juliarepl
 +julia> f!(x)= (x[1]=2);
 +
 +julia> y= [5,6]; f!(y); y ## x[1] was propagated back up
 +2-element Array{Int64,​1}:​
 + 2
 + 6
 +
 +julia> f!([5,​6]) ##​ x is not a pointer to [5,6], but its own new object; assignment of '​2'​ was lost
 +2
 +
 +```
 +
 +* If x were a pointer to `[5,6]`, you could not assign into it, because 5 is immutable.
 +
 +
 +### Scalars as Arguments Do Not Modify
 +
 +The function returns the assigned variable, but the assignment does not leave the function
 +
 +```juliarepl
 +julia> s1(x)= (x= 3);
 +
 +julia> a= 10;  s1(a)
 +3
 +
 +julia> a
 +10
 +
 +```
 +
 +
 +### When Are Objects Truly Equal?
 +
 +```juliarepl
 +julia> 1 === 1
 +true
 +
 +julia> ( 1 ) === ( 1 )
 +true
 +
 +julia> ( 1, 2 ) === ( 1, 2 )
 +true
 +
 +julia> [ 1 ] === [ 1 ] ## two different object containers, that happen to have the same content
 +false
 +
 +```
 +
 +
 +### Comparing Structures vs. Comparing Vectors
 +
 +```juliarepl
 +julia> struct I; x::Int; end;#​struct#​
 +
 +julia> I(1) == I(1) ## good boy
 +true
 +
 +julia> mutable struct M; x::Int; end;#​mutable struct#
 +
 +julia> M(1) == M(1) ## bad boy --- unlike vectors, structs with equal contents are not '​=='​
 +false
 +
 +```
 +
 +### Object Modification on Non-Scalars
 +
 +```juliarepl
 +julia> function n1(x); x= [1, 2]; end; # will not survive: object x becomes a new container
 +
 +julia> function n2(x); x[1]= 1; x[2]= 2; end; ## will survive: object is unchanged, but contents are
 +
 +julia> function n3(x); x.= [1, 2]; end; ## will survive: '​.='​ is assign contents to existing object
 +
 +julia> function n4(x); x[:]= [1, 2]; end; ## will survive: object is unchanged
 +
 +julia> a= [-99,​99]; ​ n1( a );  a
 +2-element Array{Int64,​1}:​
 + -99
 +  99
 +
 +julia> a= [-99,​99]; ​ n2( a );  a
 +2-element Array{Int64,​1}:​
 + 1
 + 2
 +
 +julia> a= [-99,​99]; ​ n3( a );  a
 +2-element Array{Int64,​1}:​
 + 1
 + 2
 +
 +julia> a= [-99,​99]; ​ n4( a );  a
 +2-element Array{Int64,​1}:​
 + 1
 + 2
 +
 +```
 +
 +* The biggest problems arise when the caller has not written the library function. ​ In this case, the library function or an even deeper function can wreak havoc on the caller.
 +
 +* Julia recommends a "​collaborative"​ model, where functions that modify their arguments should be named with a trailing '​!'​. ​ Functions without it may or may not modify their passed arguments---well,​ unless the passed arguments are native primitives and not objects.
 +
 +* The collaborative model is an inferior alternative to allowing the caller to force-designate the called function not to have permission to alter the parameter.
 +
 +* Unfortunately,​ this aspect can play a role in many variations. ​ For example, in the Optim package, one can provide gradients. ​ An inadvertent function passed to the optimizer, as in `g!(G,x) G=myfungradients(x)` messes this up and in a most difficult way to debug. ​ Instead, it needs to be `g!(G,x) G.=myfungradients(x)`.
 +
 +
 +### Can your function modify the (object content of its) arguments?
 +
 +This depends on what your code is expected to do---and you have to know.
 +
 +
 +
 +### `<:Type` vs `Type` as Argument
 +
 +```juliarepl
 +julia> f( x::​Vector{AbstractFloat} )= "​ok";​
 +
 +julia> f( [1.0, 2.0] )
 +ERROR: MethodError:​ no method matching f(::​Array{Float64,​1})
 +Closest candidates are:
 +  f(!Matched::​Array{AbstractFloat,​1}) at none:1
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +julia> f( x::​Vector{<:​AbstractFloat} )= "​ok"​ ##​ probably what was meant
 +f (generic function with 2 methods)
 +
 +julia> f( [1.0, 2.0] )
 +"​ok"​
 +
 +```
 +
 +FIXME---give an example of what the first definition would catch.
 +
 +
 +
 +### Varargs Naming (Passthrough of Named Arguments)
 +
 +```juliarepl
 +julia> g(a, b; catchme)= "ok $catchme";​
 +
 +julia> f(a, b, x... ) = g(a, b, x...);
 +
 +julia> f(1,2; catchme="​caught"​)
 +ERROR: function f does not accept keyword arguments
 +Stacktrace:
 + [1] kwfunc(::​Any) at ./​boot.jl:​321
 + [2] top-level scope at none:0
 +
 +```
 +
 +and the call does not work, because the function definition has to be clear in the semicolon vs comma distinction. ​ So, use the following:
 +
 +```juliarepl
 +julia> g(a, b; catchme)= "ok $catchme";​
 +
 +julia> f(a, b; x... ) = g(a, b; x...); ## watch the semicolons
 +
 +julia> f(1,2; catchme="​caught"​)
 +"ok caught"​
 +
 +```
 +
 +
 +### Delayed Eval (inside Function)
 +
 +```julianoeval
 +julia> function tryeval(); @eval (newfun() = 1);  return newfun(); end;#​function tryeval#
 +
 +julia> tryeval()
 +ERROR: MethodError:​ no method matching newfun()
 +The applicable method may be too new: running in world age 25040, while current world is 25041.
 +Closest candidates are:
 +  newfun() at REPL[1]:1 (method too new to be called from this world context.)
 +Stacktrace:
 + [1] tryeval() at ./REPL[1]:1
 + [2] top-level scope at none:0
 +
 +julia> tryeval()
 +1
 +
 +```
 +
 +* The first time, newfun() has not yet been defined at the call time.  The second time it has.
 +
 +
 +
 +### Dispatching to Vector of Vector of *Abstract* Floats
 +
 +This works:
 +
 +```juliarepl
 +julia> twist( manyx::​Vector{ Vector{Float64} } )= @info("​matched"​)
 +twist (generic function with 1 method)
 +
 +julia> twist( [ [1.0, 2.0], [3.0, 4.0] ] )
 +[ Info: matched
 +
 +```
 +
 +but this does not:
 +
 +```juliarepl
 +julia> twist( [ [1.0, 2.0], [3.0, 4.0] ] )
 +ERROR: UndefVarError:​ twist not defined
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +
 +
 +
 +### Passing Functions as Argument
 +
 +```juliarepl
 +julia> f(g::​Function;​ x::​Float64=10)= g(x);
 +
 +julia> f(sqrt, 10.0)
 +ERROR: MethodError:​ no method matching f(::​typeof(sqrt),​ ::Float64)
 +Closest candidates are:
 +  f(::​Function;​ x) at none:1
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +
 +## Objects as Fill Values
 +
 +```juliarepl
 +julia> mutable struct s; v::Int; end
 +
 +julia> nada= s(-1)
 +s(-1)
 +
 +julia> nadavec= fill( nada, 3 )
 +3-element Array{s,1}:
 + s(-1)
 + s(-1)
 + s(-1)
 +
 +julia> nadavec[1].v= 20
 +20
 +
 +julia> nadavec
 +3-element Array{s,1}:
 + s(20)
 + s(20)
 + s(20)
 +
 +```
 +
 +Because the fill does not create new nadas everytime, but just assigns the pointer to nada into the vec, so changing one changes the others.
 +
 +
 +
 +## Hygiene in Macros
 +
 +Macros should not accidentally modify the global variables, but use good local temporary variables. ​ See [Hygiene](https://​docs.julialang.org/​en/​v1.0/​manual/​metaprogramming/#​Hygiene-1)
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +## Arrays (Vectors and Matrices)
 +
 +### Flattened vs. Unflattened Vectors for R users
 +
 +Unlike in R, vectors do not autofold. ​ Therefore
 +
 +```juliarepl
 +julia> [ [ 1, 2 ], 3 ] ## result: a nested structure of different things ​
 +2-element Array{Any,​1}:​
 +  [1, 2]
 + 3
 +
 +julia> vcat( [ 1, 2 ], 3 ) ## use this one if you want one array
 +3-element Array{Int64,​1}:​
 + 1
 + 2
 + 3
 + 
 +```
 +
 +### Vectors of Vectors: Pushing onto Vector of Vectors
 +
 +```juliarepl
 +julia> v= Vector{ Vector{Float64} }(undef,​5) #​ a 5-vector of Undef Float Vectors
 +5-element Array{Array{Float64,​1},​1}:​
 + #​undef
 + #​undef
 + #​undef
 + #​undef
 + #​undef
 +
 +julia> push!( v[1], 1.0 )
 +ERROR: UndefRefError:​ access to undefined reference
 +Stacktrace:
 + [1] getindex(::​Array{Array{Float64,​1},​1},​ ::Int64) at ./​array.jl:​731
 + [2] top-level scope at none:0
 +
 +```
 +
 +
 +### Initializing Vectors of Vectors
 +
 +```juliarepl
 +julia> v= Vector{ Vector{Float64} }(5)
 +ERROR: MethodError:​ no method matching Array{Array{Float64,​1},​1}(::​Int64)
 +Closest candidates are:
 +  Array{Array{Float64,​1},​1}() where T at boot.jl:413
 +  Array{Array{Float64,​1},​1}(!Matched::​UndefInitializer,​ !Matched::​Int64) where T at boot.jl:394
 +  Array{Array{Float64,​1},​1}(!Matched::​UndefInitializer,​ !Matched::​Int64...) where {T, N} at boot.jl:400
 +  ...
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +julia> push!( v[1], 1.0 )
 +ERROR: UndefVarError:​ v not defined
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +FIXME show how to do this.
 +
 +* is this a vector type or an instantiated vector?
 +
 +
 +
 +### Matrix Access
 +
 +```juliarepl
 +julia> m= [ 1 2; 3 4 ]
 +2×2 Array{Int64,​2}:​
 + ​1 ​ 2
 + ​3 ​ 4
 +
 +julia> m[1,:]= m[1,:] .+ 100 ## this is vector access
 +2-element Array{Int64,​1}:​
 + 101
 + 102
 +
 +julia> m
 +2×2 Array{Int64,​2}:​
 + ​101 ​ 102
 +   ​3 ​   4
 +
 +```
 +
 +But the following is not:
 +
 +```juliarepl
 +julia> m= [ 1 2; 3 4 ]
 +2×2 Array{Int64,​2}:​
 + ​1 ​ 2
 + ​3 ​ 4
 +
 +julia> m[1,]= m[1,] .+ 100 ## this is scalar access, probably unintended
 +101
 +
 +julia> m
 +2×2 Array{Int64,​2}:​
 + ​101 ​ 2
 +   ​3 ​ 4
 +
 +```
 +
 +
 +### Assigning Different Matrix Types
 +
 +```juliarepl
 +julia> msz= 4;
 +
 +julia> bvector= reshape( collect(1:​(msz*msz)),​ (msz,msz) )
 +4×4 Array{Int64,​2}:​
 + ​1 ​ 5   ​9 ​ 13
 + ​2 ​ 6  10  14
 + ​3 ​ 7  11  15
 + ​4 ​ 8  12  16
 +
 +julia> using LinearAlgebra
 +
 +julia> bvector[1:​2,​1:​2] = first( qr( bvector[ 1:2, 1:2 ] ) )
 +ERROR: InexactError:​ Int64(Int64,​ -0.44721359549995787)
 +Stacktrace:
 + [1] Type at ./​float.jl:​700 [inlined]
 + [2] convert at ./​number.jl:​7 [inlined]
 + [3] setindex! at ./​array.jl:​771 [inlined]
 + [4] macro expansion at ./​multidimensional.jl:​648 [inlined]
 + [5] macro expansion at ./​cartesian.jl:​64 [inlined]
 + [6] macro expansion at ./​multidimensional.jl:​643 [inlined]
 + [7] _unsafe_setindex!(::​IndexLinear,​ ::​Array{Int64,​2},​ ::​LinearAlgebra.QRCompactWYQ{Float64,​Array{Float64,​2}},​ ::​UnitRange{Int64},​ ::​UnitRange{Int64}) at ./​multidimensional.jl:​636
 + [8] _setindex! at ./​multidimensional.jl:​631 [inlined]
 + [9] setindex!(::​Array{Int64,​2},​ ::​LinearAlgebra.QRCompactWYQ{Float64,​Array{Float64,​2}},​ ::​UnitRange{Int64},​ ::​UnitRange{Int64}) at ./​abstractarray.jl:​998
 + [10] top-level scope at none:0
 +
 +julia> bvector = first( qr( bvector[ 1:2, 1:2 ] ) )
 +2×2 LinearAlgebra.QRCompactWYQ{Float64,​Array{Float64,​2}}:​
 + ​-0.447214 ​ -0.894427
 + ​-0.894427 ​  ​0.447214
 +
 +```
 +
 +* bvector is an Int64 matrix. ​ Thus, you cannot assign the Float64 matrix over its existing contents. ​
 +
 +
 +
 +
 +
 +## Strings
 +
 +### Inadvertent String Interpolation of Module-Named Variables
 +
 +```julianoeval
 +julia> struct FFF; fv::​Float64;​ end#​function
 +
 +julia> Base.show(io::​IO,​ f::FFF) = println(io, "Your FFF type is $f.fv"​)
 +
 +julia> f= FFF(2.0)
 +Error showing value of type FFF:
 +ERROR: StackOverflowError:​
 +Stacktrace:
 +
 +```
 +
 +* You probably meant a version in which `$f.fv` is not `$f\.fv`, but `$(f.fv)`:
 +
 +
 +```juliarepl
 +julia> struct FFF; fv::​Float64;​ end#​function
 +
 +julia> Base.show(io::​IO,​ f::FFF) = println(io, "Your FFF type is $(f.fv)"​)
 +
 +julia> f= FFF(2.0)
 +Your FFF type is 2.0
 +
 +```
 +
 +really nasty. ​ instead, you need to quote this as $(f.fv).
 +
 +
 +
 +### String-Interpolated Names of Exclamation Variables
 +
 +```juliarepl
 +julia> op= 2.0
 +2.0
 +
 +julia> println("​Thank you for $op!")
 +ERROR: UndefVarError:​ op! not defined
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +* Variable names can contain '​!',​ so this asks for `$op!` not for `$op` continues.
 +
 +* Recall also that in `$op.x`, you get `$(op).x`.
 +
 +
 +
 +### String vs. Byte Representations
 +
 +```juliarepl
 +julia> x= 7310302560386184563;​ ##​ (thanks steveng)
 +
 +julia> write(stdout,​ x); println("​\n"​);​ ##​ it's the byte representation!!!
 +surprise
 +
 +```
 +
 +You probably wanted `println(x)`,​ not `write(x)`.
 +
 +
 +### Eval of Function Name Stored in String vs Eval of Function Name in Symbol
 +
 +```juliarepl
 +julia> d1= Dict{String,​Int}()
 +Dict{String,​Int64} with 0 entries
 +
 +julia> d2= Dict{String,​Int}()
 +Dict{String,​Int64} with 0 entries
 +
 +julia> (eval("​d1"​))["​first"​]= 1 ## the eval'​ed string is not d1
 +ERROR: MethodError:​ no method matching setindex!(::​String,​ ::Int64, ::String)
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +julia> (eval(:​d1))["​first"​]= 1 ## the eval'​ed symbol is d1
 +1
 +
 +```
 +
 +
 +
 +
 +
 +
 +## Tuples
 +
 +### Tuples vs Sequential Statements
 +
 +```juliarepl
 +julia> f(x)= ( x=x+1, x*2 )  ## returns (x+1,x*2)
 +ERROR: syntax: invalid named tuple element "(x * 2)"
 +
 +```
 +
 +is not
 +
 +```juliarepl
 +julia> f(x)= ( x=x+1; x*2 )  ## returns 2*(x+1)
 +f (generic function with 1 method)
 +
 +```
 +
 +
 +### Tuples are not Lists
 +
 +```juliarepl
 +julia> (1,2) == (1,2)
 +true
 +
 +julia> (1,2) == (1;2)
 +false
 +
 +julia> (1,) == (1)
 +false
 +
 +```
 +
 +
 +### Wrong Tuple or Array Naming: Parens instead Curlies
 +
 +```juliarepl
 +julia> function f()::​Tuple{Int,​Int};​ x=(1,2); @info(typeof(x));​ x end
 +f (generic function with 1 method)
 +
 +julia> f()
 +[ Info: Tuple{Int64,​Int64}
 +(1, 2)
 +```
 +
 +The following is a bug:
 +
 +```juliarepl
 +julia> function f()::​Tuple(Int,​Int);​ x=(1,2); @info(typeof(x));​ x end
 +f (generic function with 1 method)
 +
 +julia> f()
 +ERROR: MethodError:​ no method matching Tuple(::​Type{Int64},​ ::​Type{Int64})
 +Closest candidates are:
 +  Tuple(::​Any) where T<:Tuple at tuple.jl:​243
 +Stacktrace:
 + [1] f() at ./REPL[8]:1
 + [2] top-level scope at none:0
 +
 +```
 +
 +Maybe this is clearer:
 +
 +```juliarepl
 +julia> Tuple([Int,​Int])
 +(Int64, Int64)
 +
 +julia> Tuple(Int,​Int)
 +ERROR: MethodError:​ no method matching Tuple(::​Type{Int64},​ ::​Type{Int64})
 +Closest candidates are:
 +  Tuple(::​Any) where T<:Tuple at tuple.jl:​243
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +
 +Search for "​potential failure"​ scenarios in Julia Module, e.g., for precompiling to fail.
 +
 +
 +
 +
 +
 +
 +
 +## Structs
 +
 +### All Structs Must Be Global.
 +
 +Functions Cannot Define Structs (Compile Types). ​  Ergo, constructors always need to be outside functions. ​ Fortunately,​ this give a good and clear error:
 +
 +```juliarepl
 +julia> function f();
 + mutable struct Point; x::Float64; f::Float64; end;
 + println("​ok"​);​
 +        end##​function##​
 +ERROR: syntax: "​struct"​ expression not at top level
 +
 +```
 +
 +
 +### Extract All Fields from Vector of Structs
 +
 +```juliarepl
 +
 +julia> struct S; x::Int; f::String; end#struct
 +
 +julia> s1= S(1, "​a"​);​ s2= S(20, "​b"​);​ s3= S(300, "​c"​)
 +S(300, "​c"​)
 +
 +julia> svec= [ s1, s2, s3 ]
 +3-element Array{S,1}:
 + S(1, "​a"​)
 + S(20, "​b"​)
 + ​S(300,​ "​c"​)
 +
 +julia> [ y->​svec[u].x for y in svec ] ## or [ i->​svec[i].x for i=1:​length(svec) ]
 +3-element Array{getfield(Main,​ Symbol("##​4#​6"​)),​1}:​
 + ​getfield(Main,​ Symbol("##​4#​6"​))()
 + ​getfield(Main,​ Symbol("##​4#​6"​))()
 + ​getfield(Main,​ Symbol("##​4#​6"​))()
 +
 +julia> [ y.x for y in svec ] ## or [ svec[i].x for i=1:​length(svec) ]
 +3-element Array{Int64,​1}:​
 +   1
 +  20
 + 300
 +
 +```
 +
 +
 +
 +## Dicts
 +
 +### Initialization of Dict
 +
 +```juliarepl
 +julia> d= Dict{String,​Int}
 +Dict{String,​Int64}
 +
 +julia> d["​first"​]= 1
 +ERROR: MethodError:​ no method matching setindex!(::​Type{Dict{String,​Int64}},​ ::Int64, ::String)
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +julia> d= Dict{String,​Int}(0)
 +ERROR: BoundsError:​ attempt to access 0
 +  at index [2]
 +Stacktrace:
 + [1] indexed_iterate(::​Int64,​ ::Int64, ::Nothing) at ./​tuple.jl:​69
 + [2] Dict{String,​Int64}(::​Int64) at ./​dict.jl:​103
 + [3] top-level scope at none:0
 +
 +julia> d["​first"​]= 1
 +ERROR: MethodError:​ no method matching setindex!(::​Type{Dict{String,​Int64}},​ ::Int64, ::String)
 +Stacktrace:
 + [1] top-level scope at none:0
 +
 +```
 +
 +Instead, you need
 +
 +```juliarepl
 +julia> d= Dict{String,​Int}()
 +Dict{String,​Int64} with 0 entries
 +
 +julia> d["​first"​]= 1
 +1
 +```
 +
 +
 +
 +
 +
 +
 +## Parallel Processing
 +
 +addprocs() must be defined *BEFORE* everywhere.
 +
 +
 +
 +
 +## Plotting
 +
 +### Timing of Redraw
 +
 +```juliarepl
 +julia> using Plots
 +
 +julia> p= plot( [-1,10], [-1,10], color=Gray(0.5),​ w=30, title="​gray scale" )
 +
 +julia> for i=0:10; vline!( [i], color=Gray(i/​10.0),​ w=10 ) end
 +
 +```
 +
 +* The for loop is one statement, and therefore the final statement'​s output is a nothing, which does not lead to a redraw. ​ To redraw, type "​p"​ or "​display(p)"​.
 +
 +
 +
 +## Benchmarking:​ @time and @btime
 +
 +I think that symbols cannot be escaped with '​$'​ in @btime, only numbers
 +
 +or it could be constants pulled out from list?
 +
 +
 +
 +
 +
 +
 +# Backmatter
 +
 +## Commonly Useful Packages on Julia Repository
 +
 +## Notes
  
baffling.txt · Last modified: 2018/11/20 13:44 (external edit)