I would like to create a quote which gets the symbol :abc saved in variable x and push it into the array a. However I could only get the variable abc. The syntax :$x seems incorrect (not what I desired). What is the syntax to do this?:
julia> x = :abc
julia> expr = quote
a = []
push!(a, $x)
push!(a, :($x))
push!(a, :$x)
a
end
quote
a = []
push!(a, abc)
push!(a, $(Expr(:quote, :($(Expr(:$, :x))))))
push!(a, :$ * x)
a
end
The desired output is:
quote
a = []
push!(a, :abc)
a
end
You need to add another layer of quotation, using $(Meta.quot(:abc)) which is equivalent to $(Expr(:quote, :abc)).
Using:
_
_ _ _(_)_ | A fresh approach to technical computing
(_) | (_) (_) | Documentation: https://docs.julialang.org
_ _ _| |_ __ _ | Type "?help" for help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 0.6.2 (2017-12-13 18:08 UTC)
_/ |\__'_|_|_|\__'_| | Official http://julialang.org/ release
|__/ | x86_64-pc-linux-gnu
Setup:
julia> x = :abc
:abc
julia> es = [x, :x, :(:x), Expr(:quote, x), Meta.quot(x)] # :(x) is parsed as :x
5-element Array{Any,1}:
:abc
:x
:(:x)
:(:abc)
:(:abc)
julia> blk = Expr(:block)
quote
end
Push!:
julia> push!(blk.args, :(a = []))
1-element Array{Any,1}:
:(a = [])
julia> blk
quote
a = []
end
julia> for e in es
push!(blk.args, :(push!(a, $e)))
end
julia> blk
quote
a = []
push!(a, abc)
push!(a, x)
push!(a, :x)
push!(a, :abc)
push!(a, :abc)
end
julia> push!(blk.args, :a)
7-element Array{Any,1}:
:(a = [])
:(push!(a, abc))
:(push!(a, x))
:(push!(a, :x))
:(push!(a, :abc))
:(push!(a, :abc))
:a
Eval:
julia> blk
quote
a = []
push!(a, abc)
push!(a, x)
push!(a, :x)
push!(a, :abc)
push!(a, :abc)
a
end
julia> eval(ans)
ERROR: UndefVarError: abc not defined
Stacktrace:
[1] eval(::Module, ::Any) at ./boot.jl:235
[2] eval(::Any) at ./boot.jl:234
Fix:
julia> deleteat!(blk.args, 2)
6-element Array{Any,1}:
:(a = [])
:(push!(a, x))
:(push!(a, :x))
:(push!(a, :abc))
:(push!(a, :abc))
:a
julia> blk
quote
a = []
push!(a, x)
push!(a, :x)
push!(a, :abc)
push!(a, :abc)
a
end
julia> eval(ans)
4-element Array{Any,1}:
:abc
:x
:abc
:abc
Finally:
julia> using Base.Meta: quot
julia> x = :abc
:abc
julia> expr = quote
a = []
push!(a, $(quot(x)))
a
end
quote
#= REPL[16]:2 =#
a = []
#= REPL[16]:3 =#
push!(a, :abc)
#= REPL[16]:4 =#
a
end
julia> eval(ans)
1-element Array{Any,1}:
:abc
Related
I am studying Julia static analysis, and I have the following function:
function f(x,y,z)
d=x+y
d=d*2*z
end
i use code_typed to analyze it.
julia> y=code_typed(f)
1-element Vector{Any}:
CodeInfo(
1 ─ %1 = (x + y)::Any
│ %2 = (%1 * 2)::Any
│ %3 = (%2 * z)::Any
└── return %3
) => Any
i can get slots and slot types of it.
julia> y[1].first.slotnames
5-element Vector{Symbol}:
Symbol("#self#")
:x
:y
:z
:d
julia> y[1].first.slottypes
5-element Vector{Any}:
Core.Const(f)
Any
Any
Any
Any
but do i have any way to know which is argument and which is local variables among the slots?
You can use Base.argnames to find out arguments of your function:
julia> Base.method_argnames.(methods(f))
1-element Vector{Vector{Symbol}}:
[Symbol("#self#"), :x, :y, :z]
You can extract this from the CodeInfo object as well:
julia> Base.method_argnames(y[1].first.parent.def)
4-element Vector{Symbol}:
Symbol("#self#")
:x
:y
:z
I wrote the following code in SML with the NJ Compiler:
fun all_answers (f, xs) =
let
fun aux(accu, xs_left) =
case xs of
[] => SOME accu
| x::xs' => case f(x) of
NONE => NONE
| SOME y => aux(accu#y, xs')
in
aux([], xs)
end
It works well for this tests:
val testAll1 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), []) = SOME []
val testAll2 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), [2,3,4,5,6,7]) = NONE
However, something weird happens with this test:
val testAll3 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), [1]) = SOME [1]
After running the program, the terminal goes on forever.
I defined the tail recursion and used the pattern-match with xs' to reach the tail.
Moreover, I defined the base case to end the recursion so that if xs is [] then the auxiliary function returns SOME accumulator
Can anybody help me?
Thanks in advance.
As #kopecs pointed out, this is caused by case xs of when you want case xs_left of.
Here is a cleaned up (whitespace, naming) version of your function:
fun all_answers (f, ys) =
let
fun aux (accu, xs) =
case xs of
[] => SOME accu
| x::xs' => case f x of
NONE => NONE
| SOME y => aux (accu#y, xs)
in
aux ([], ys)
end
There are at least two things you could do to simplify the way this function is made. (1) Perform the case xs of inside the function pattern rather than in a nested case-of. (2) Remove the inner aux function and simply do the recursion in the outer function, at the expense of some tail-recursion
The first simplification might look like:
fun all_answers2 (f, ys) =
let
fun aux (accu, []) = SOME accu
| aux (accu, x::xs) =
case f x of
NONE => NONE
| SOME y => aux (accu#y, xs)
in
aux ([], ys)
end
And the second might look like:
fun all_answers' (f, []) = SOME []
| all_answers' (f, x::xs) =
case f x of
NONE => NONE
| SOME ys => case all_answers' (f, xs) of
NONE => NONE
| SOME result => SOME (ys # result)
This shows a pattern: Whenever you have
case f x of
NONE => NONE
| SOME y => case g y of
NONE => NONE
| SOME z => ...
then you have a programming pattern that could be abstracted out with a function.
There is already a standard library function that is made for this called Option.map, so you could write:
fun all_answers3 (f, ys) =
let
fun aux (accu, []) = SOME accu
| aux (accu, x::xs) =
Option.map (fn y => aux (accu#y, xs))
(f x)
in
aux ([], ys)
end
Try and play around with this function in the REPL:
- Option.map (fn y => y + 2) NONE;
> val it = NONE : int option
- Option.map (fn y => y + 2) (SOME 2);
> val it = SOME 4 : int option
Taking this in another direction, rather than an inner function:
(* Alternative to Option.map: *)
fun for NONE _ = NONE
| for (SOME x) f = f x
(* Equivalent to Option.mapPartial with "flipped" arguments: *)
fun for opt f = Option.mapPartial f opt
fun all_answers'' (f, []) = SOME []
| all_answers'' (f, x::xs) =
for (f x) (fn ys =>
for (all_answers'' (f, xs)) (fn result =>
SOME (ys # result)))
This style is more Haskell-like because it follows a monadic design pattern.
defmodule Maps do
def map([],[]) do [] end
def map([x|xs], [x1 | xs1])
do map([xs],[xs1]) ++ [(x + x1) | []] end
end
I don't get what's wrong with it. Suppose you run Maps.map([1],[2]). It should then do map(xs,xs1) and since xs = [] and xs1 = [] is empty, map ([],[]) should return [], which ends the recursion. Then
[] ++ [1+2] = [3] so the result should return [3]. However, this just freezes my terminal.
xs and xs1 are already lists in the second clause, but you're wrapping it in another list, which is creating infinite recursion. Changing:
map([xs],[xs1]) ++ [(x + x1) | []]
to:
map(xs, xs1) ++ [(x + x1) | []]
Gives the expected output:
iex(1)> Maps.map([1, 2, 3], [4, 5, 6])
[9, 7, 5]
Sidenote: [x | []] is the same as [x], so you could rewrite that to just:
map(xs, xs1) ++ [x + x1]
I am writing a macro, that takes a function name,
and declares a couple of other version of the function.
I want to give these variations the same doc string as the original method,
with perhaps a few changes.
To do this, I need to retrieve the docstring for the orginal method.
So what I am looking for is a function:
get_docstring(functionname::Symbol, argtypes)::String
So that I could do:
julia> s=get_docstring(:values,(Associative,)) and then s would be set to:
s="""
values(a::Associative)
Return an iterator over all values in a collection.
`collect(values(d))` returns an array of values.
```jldoctest
julia> a = Dict('a'=>2, 'b'=>3)
Dict{Char,Int64} with 2 entries:
'b' => 3
'a' => 2
julia> collect(values(a))
2-element Array{Int64,1}:
3
2
```
"""
You can use the #doc macro, but instead of a string, it returns a markdown object:
julia> #doc "foo int" ->
foo(x::Int) = x
foo
julia> #doc "foo float" ->
foo(x::Float64) = x
foo
julia> #doc "foo sym" ->
foo(x::Symbol) = x
foo
julia> #doc "foo x, y" ->
function foo(x, y) x, y end
foo
julia> #doc foo
foo int
foo float
foo sym
foo x, y
julia> typeof(ans)
Base.Markdown.MD
julia> #doc foo(::Int)
foo int
julia> #doc foo(::Float64)
foo float
julia> #doc foo(::Symbol)
foo sym
julia> md = #doc foo(::Any, ::Any)
foo x, y
julia> md.content
1-element Array{Any,1}:
foo x, y
julia> md.content[1]
foo x, y
julia> md.content[1].content
1-element Array{Any,1}:
Base.Markdown.Paragraph(Any["foo x, y"])
julia> md.meta
Dict{Any,Any} with 3 entries:
:typesig => Tuple{Any,Any}
:results => Base.Docs.DocStr[Base.Docs.DocStr(svec("foo x, y"),foo x, y…
:binding => foo
julia>
I often need to match a tuple of values that should have the same constructor. The catchall _,_ always winds-up at the end. This of course is fragile, any additional constructor added to the type will compile perfectly fine. My current thoughts are to have matches that connect the first but not second argument. But, is there any other options?
For example,
type data = | States of int array
| Chars of (char list) array
let median a b = match a,b with
| States xs, States ys ->
assert( (Array.length xs) = (Array.length ys) );
States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| Chars xs, Chars ys ->
assert( (Array.length xs) = (Array.length ys) );
let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) # c2 in
Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
(* inconsistent pairs of matching *)
| Chars _, _
| States _, _ -> assert false
You can use the slightly shorter pattern below:
| (Chars _| States _), _ -> assert false
In fact, you can let the compiler generate it for you, because it's still a little tedious.
Type the following and compile:
let median a b = match a,b with
| States xs, States ys ->
assert( (Array.length xs) = (Array.length ys) );
States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| Chars xs, Chars ys ->
assert( (Array.length xs) = (Array.length ys) );
let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) # c2 in
Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
Warning 8: this pattern-matching is
not exhaustive. Here is an example of
a value that is not matched: (Chars _,
States _)
You can now copy-paste the suggested pattern back into your code. This is usually how I generate non-fragile catch-all patterns for types with tens of constructors. You may need to launch the compiler several times, but it's still faster than typing them yourself.
It's only a matter of taste/style, but I tend to prefer grouping clauses on the same constructor together, rather than having the useful clauses for everything first, then all the "absurd cases" together. This can be quite helpful when you get to write several "useful" clauses for one given constructor, and want to check you didn't forget anything.
let median a b = match a,b with
| States xs, States ys ->
assert( (Array.length xs) = (Array.length ys) );
States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| States _, _ -> assert false
| Chars xs, Chars ys ->
assert( (Array.length xs) = (Array.length ys) );
let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) # c2 in
Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
| Chars _, _ -> assert false
This is pretty hackish (and results in warnings) but you can use Obj to check if the tags are equal or not. It should catch all cases where a and b have different values:
type data = | States of int array
| Chars of (char list) array
let median a b = match a,b with
| States xs, States ys ->
assert( (Array.length xs) = (Array.length ys) );
States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| Chars xs, Chars ys ->
assert( (Array.length xs) = (Array.length ys) );
let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) # c2 in
Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
(* inconsistent pairs of matching *)
| x, y when (Obj.tag (Obj.repr x)) <> (Obj.tag (Obj.repr y)) -> assert false
The warning is for non-exhaustive pattern-matching (since it can't tell whether or not the guarded clause matches the rest or not).
EDIT: you don't need to use Obj at all, you can just compare x and y directly:
| x, y when x <> y -> assert false
Though this still results in a warning, unfortunately.