diff --git a/base/dict.jl b/base/dict.jl index cb249f65dbe88..8a37cda0590c2 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -7,6 +7,24 @@ const _jl_secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ has(t::Associative, key) = !is(get(t, key, _jl_secret_table_token), _jl_secret_table_token) +# @get! works like get, but evaluates the default value only if the key is not +# present; it then assigns the default value to the key and returns the +# (converted) value +macro get!(d, k, default) + quote + d::Associative, k = $(esc(d)), $(esc(k)) + p, index = _assoc_keyindex(d, k) + V = valtype(d) + ( p ? _get_at(d, index) : (d[k] = convert(V,$(esc(default)))) )::V + end +end + +# Used by @get!. +# If you provide _assoc_keyindex for a type, +# you must provide a matching _get_at. +_assoc_keyindex(d::Associative, k) = (has(d, k), k) +_get_at(d::Associative, index) = d[index] + function show{K,V}(io, t::Associative{K,V}) if isempty(t) print(io, typeof(t),"()") @@ -423,6 +441,9 @@ function get{K,V}(h::Dict{K,V}, key, deflt) return (index<0) ? deflt : h.vals[index]::V end +_assoc_keyindex(d::Dict, k) = (i=ht_keyindex(d,k);(i<0) ? (false,0) : (true,i)) +_get_at(d::Dict, index) = d.vals[index] + has(h::Dict, key) = (ht_keyindex(h, key) >= 0) function key{K,V}(h::Dict{K,V}, key, deflt) diff --git a/base/export.jl b/base/export.jl index fc181d8204f5d..0e69a6697ea1c 100644 --- a/base/export.jl +++ b/base/export.jl @@ -1294,6 +1294,7 @@ export unsetenv, # Macros + @get!, @v_str, @unexpected, @assert, diff --git a/test/corelib.jl b/test/corelib.jl index 4635cd4c78202..ee6a358f383de 100644 --- a/test/corelib.jl +++ b/test/corelib.jl @@ -181,6 +181,17 @@ d4[1001] = randstring(3) @test !isequal({1 => 2}, {"dog" => "bone"}) @test isequal(Dict{Int, Int}(), Dict{String, String}()) +#@get! +let + d = {8=>19} + def = {} + f = x->(push(def,x); x) + @test @get!(d, 8, f(5)) == 19 + @test @get!(d, 19, f(2)) == 2 + @test d == {8=>19, 19=>2} + @test def == [2] +end + # ############# end of dict tests ############# # #################### set ####################