The new Dict syntax in 0.4 is very verbose

1,118 views
Skip to first unread message

Michael Francis

unread,
Sep 2, 2015, 12:45:08 PM9/2/15
to julia-users
With the change to 0.4 happening soon I'm finding the the new Dict syntax in 0.4 (removal of {}, []) is extremely verbose.

I find myself interfacing with JSON APIs frequently, for example a configuration dictionary :

data = {
       
:displayrows => 20,
       
:cols => [
                   
{ :col => "l1" },
                   
{ :col => "l2" },
                   
{ :col => "l3" },
                   
{ :col => "num", :display => true },
                   
{ :col => "sum", :display => true, :conf => { :style => 1, :func => { :method => "sum", :col => "num"  } } }
               
]  
       
... # Lots more  
   
}

becomes -

data = Dict{Symbol,Any}(
       
:displayrows => 20,
       
:cols => [
                   
Dict{Symbol,Any}( :col => "l1" ),
                   
Dict{Symbol,Any}( :col => "l2" ),
                   
Dict{Symbol,Any}( :col => "l3"   ),
                   
Dict{Symbol,Any}( :col => "num", :display => true ),
                   
Dict{Symbol,Any}( :col => "sum", :display => true, :conf => Dict{Symbol,Any}( :style => 1,
                                                                   
:func => Dict{Symbol,Any}( :method => "sum", :col => "num" ) ) )
               
]  
       
... # Lots more
   
)

This feels like asking a person using arrays to write the following

Array{Int64,2}( Vector{Int64}( 1,2,3), Vector{Int64}( 4,5,6) )

vs

[ [ 1, 2, 3] [ 4,5,6 ] ]

Can we please reconsider ?

Mike Innes

unread,
Sep 2, 2015, 12:55:29 PM9/2/15
to julia-users
You might consider creating an alias, e.g.

d(xs...) = Dict{Any, Any}(xs...)

d(:a=>1, :b=>2)

It's not as nice, but it's not awful either. You could also do

macro d(xs...)
  for x in xs
    @assert x.head == :(=>)
    isa(x.args[1], Symbol) && (x.args[1] = Expr(:quote, x.args[1]))
  end
  :(Dict{Any, Any}($(map(esc, xs)...)))
end

@d(a=>1, b=>2)

Saving on the colons might just be enough to make the lack of literal syntax less painful.

David Anthoff

unread,
Sep 2, 2015, 12:58:38 PM9/2/15
to julia...@googlegroups.com

I have to admit that after having used the new syntax for a while now, I’m not a fan at all. It feels like I’m thrown back to my old C# days…

 

I’m sure there was an excellent reason for this change, but I couldn’t find the relevant issue on github. If someone has the relevant link handy, I would appreciate the link.

 

Thanks,

David

Tim Holy

unread,
Sep 2, 2015, 1:04:28 PM9/2/15
to julia...@googlegroups.com
Why not just Dict(:col => "l1")?

--Tim

Isaiah Norton

unread,
Sep 2, 2015, 1:07:59 PM9/2/15
to julia...@googlegroups.com
This issue was raised here:
https://github.com/JuliaLang/julia/issues/6739#issuecomment-120149597

I believe the consensus was that nice JSON input syntax could be handled with a macro.

Also, once the "[ a=>b, ...]" syntax deprecation goes away, I believe this:

    [ :col => "l1", :col => "l2", ... ]

will simply give you an array of Pair objects, which could be translated to unitary Dicts by JSON.

(FWIW, it is not necessary to specify the argument types to Dict)

Michael Francis

unread,
Sep 2, 2015, 1:29:19 PM9/2/15
to julia-users

The arguments given in the thread that Dict 'isn't special' should also also apply to Vector and Array, I presume nobody wants to do away with literal syntax for them as well? 

There are many times when having a simple terse native (code editor aware) literal syntax for structured data is very useful (in the same way that it is useful for vectors and arrays) and I second what David is saying, it feel like I'm back writing C++/C#/Java et al. 

Using macros works, but everybody is going to have their own so there will be no consistency across the code base. Dict(...) works without the types so I guess that is the best of a bad bunch. 

Erik Schnetter

unread,
Sep 2, 2015, 2:21:35 PM9/2/15
to julia...@googlegroups.com
If I recall correctly, the two sets of ASCII bracketing operators ([] and {}) were deemed to be more usefully employed for arrays; apparently, arrays are used more often than dictionaries in Julia. However, I also recall the suggestion that some other kind of bracketing operators -- maybe non-ASCII unicode ones, or double up operators such as [[ ]] or <| |> or somesuch -- could be used for dictionaries.

On the other hand: In many cases where one would naturally use arrays, using iterators is more efficient. Similarly, instead of using dictionaries, using arrays of pairs is often possible.

-erik

Jeffrey Sarnoff

unread,
Sep 2, 2015, 3:36:08 PM9/2/15
to julia-users
This is an outcome of an underlying as-yet-unresolvedness, one all agree is important as it must shape some of the experience one has with Julia.  Stefan makes good sense: "In Julia, [Dict is] just another data structure ... So having special syntax ends up being  ... problematic and [un]helpful."  And so do you, Michael because syntax that erupts in natural application is not yet well-situated; that David is having flashbacks is proof enough. If there were one not-overly-recondite macro that gave back some expressive parsimony .. there is not, and if there were it would be like finding your friend came back from spring break with a bad tattoo.

Dicts are at least not-unimportant for Julia. And without specializing syntax beyond system consonant indication, population, access and movement there must be some lexicographic uniqueness.  It could be limited to :Dict, should it? Julia knows (I do not), the more robust and healthy approach is to match other not-unimportant stuff that already is happily adopted and comfortable in use.  The most important underpinnings of the language live in a very intra-relating and inter-related relm.  Even there, these not-unimportants are mutually strengthening rather than sub-segmenting.  So using Dicts mellows when we know how Julia lifts semantic efficacy to project syntactic clarity.

There are math-y views of this, here is one:
"In general you can think of the homotopy pushout of A → B, A → C as the 'free' thing generated by B and C with 'relations' coming from A. But it's important that the "relations" are imposed exactly once, since in the homotopical/derived setting we keep track of such things (and have 'relations between relations' etc.)” - from Ried Barton

Phil Tomson

unread,
Sep 2, 2015, 7:49:02 PM9/2/15
to julia-users


On Wednesday, September 2, 2015 at 11:21:35 AM UTC-7, Erik Schnetter wrote:
If I recall correctly, the two sets of ASCII bracketing operators ([] and {}) were deemed to be more usefully employed for arrays;

How has have the curly braces "{" and "}" been reused for arrays in 0.4? Curly braces have been used to indicate Dicts up until 0.4 (and the syntax was essentially borrowed from Python/Ruby/others) I have to agree with the OP and others here that the verbose Dict syntax in 0.4 is pretty ugly. I didn't realize that was the way it was headed as I haven't done much in 0.4 yet.

 

Tim Holy

unread,
Sep 2, 2015, 7:59:39 PM9/2/15
to julia...@googlegroups.com
The amount we can re-use old syntax for new purposes is limited: we need one
release in which the old syntax generates a warning, and then the new meaning
can arrive in the next release. Otherwise, code that worked on 0.3 might
exhibit surprising failures in the cases where the new meaning doesn't
generate an error but it is not what the programmer initially intended.

--Tim
> >>>> :fu
> >>>> :nc

Marcio Sales

unread,
Sep 2, 2015, 9:39:47 PM9/2/15
to julia-users
Made me remember the Mayor's decisions for new infrastructure in my city. "Just why?" :)

Adrian Cuthbertson

unread,
Sep 3, 2015, 2:14:38 AM9/3/15
to julia...@googlegroups.com
Yeah, like a toll-gate has been introduced and we're not sure what the tax is being spent on :)

Mauro

unread,
Sep 3, 2015, 3:46:12 AM9/3/15
to julia...@googlegroups.com
Easy now!

If you want to know what is going on with the design of Julia and why
certain decisions are made then you need to follow the development on
github. As a first stop, the NEWS.md file is your friend:
https://github.com/JuliaLang/julia/blob/master/NEWS.md which has some
details on this.

Then, searching for curly brings up a few issues, try this for starters:
https://github.com/JuliaLang/julia/issues/8470

Andreas Lobinger

unread,
Sep 3, 2015, 7:35:27 AM9/3/15
to julia-users
I have to admit i didn't follow this discussion although i'm a big fan of structuring data into Dicts.

I still understood http://julialang.org/blog/2012/02/why-we-created-julia/ as somehow setting the tone for Julia as a language. And i find
 
We want something as usable for general programming as Python,

and dictionary are especially a means for general programming (Arrays are not, Lists are). And

We never want to mention types when we don’t feel like it.

contradicts a little bit the Dict{Symbol,Any}( :col => "l1" ) syntax.

I would not claim that something goes wrong here, but my expectation would have been rather: non-verbose syntax where it can be avoided. And i disagree, Dict are not just another data structure.
 

Scott Jones

unread,
Sep 3, 2015, 9:25:42 AM9/3/15
to julia-users
Yes, I’d say Dicts (AKA associative arrays) need to absolutely be a first class data structure in Julia, with appropriate easy to understand and use syntax.

This seems like a huge step backwards, already the ‘=>’ syntax makes it a lot clumsier than in most other popular modern languages.

Scott

Jonathan Malmaud

unread,
Sep 3, 2015, 9:36:33 AM9/3/15
to julia-users
I agree that syntactic sugar for Dict literal construction would be appreciated. There were good reasons for removing the previous syntax, but I think it should be possible to find something more terse than the status quo. 


On Wednesday, September 2, 2015 at 12:45:08 PM UTC-4, Michael Francis wrote:

Mike Nolta

unread,
Sep 3, 2015, 10:12:58 AM9/3/15
to julia...@googlegroups.com
I also think ditching {} for dicts wasn't a great idea.

-Mike

Jeff Bezanson

unread,
Sep 3, 2015, 10:38:15 AM9/3/15
to julia...@googlegroups.com
There is no need to write the type over and over again. You can say

const D = Dict{Symbol, Any}

D(:a => "", :b => 0, ...)

The old syntax for this was

(Symbol=>Any)[:a => "", :b => 0, ...]

but there was no way to abstract over the type part, `(Symbol=>Any)`,
so you really did have to write the types over and over again. The `{
}` syntax only constructed dicts of exactly one type, Dict{Any,Any}.
Do we really want to use an entire set of brackets for exactly one
very-loosely-typed kind of dict?

So in other words there was a "syntax cliff", where you could start
with a bunch of nested `{ }`, but then if you realized every key was
the same type you would have to rewrite everything, switching `{ }` to
`[ ]` and inserting `(T=>S)` in front. Now you can just change the
definition of `const D = ...` in one place.

Steven G. Johnson

unread,
Sep 3, 2015, 10:51:12 AM9/3/15
to julia-users


On Thursday, September 3, 2015 at 10:38:15 AM UTC-4, Jeff Bezanson wrote:
There is no need to write the type over and over again. You can say

const D = Dict{Symbol, Any}

D(:a => "", :b => 0, ...)

There is also often no need to write the type at all: 

julia> Dict(:a => "", :b => 0)

Dict{Symbol,Any} with 2 entries:

  :a => ""

  :b => 0


The Dict constructor automatically computes the common parent of the key and value types.

Kevin Squire

unread,
Sep 3, 2015, 10:51:34 AM9/3/15
to julia...@googlegroups.com

Scott Jones

unread,
Sep 3, 2015, 11:01:22 AM9/3/15
to julia-users
There are a number of inconsistency problems currently though.

[1,2.3,4] gives Array{Float64,1},
but Dict(1=>1,2=>2.3,3=>3) gives Dict{Int64,Any}.

Another weird one with arrays that is inconsistent (hopefully will be fixed in 0.5):
[1,2,[3,4]] gives a deprecation warning about concatenation, while
Any[1,2,[3,4]] give what I expected, i.e. Array{Any,1}
(Dict on the other hand gives me what I'd expect, i.e. Dict{Int64, Any}).

Jeff Bezanson

unread,
Sep 3, 2015, 11:14:08 AM9/3/15
to julia...@googlegroups.com
> Another weird one with arrays that is inconsistent (hopefully will be fixed in 0.5)

Yes that's the whole point of the deprecation warning.

cormu...@mac.com

unread,
Sep 3, 2015, 11:22:09 AM9/3/15
to julia-users
Early adopters shouldn't throw stones... :) But in fact I quite like the new Dict syntax, which seems to be more explicit and readable. Curly braces seem to be gainfully employed elsewhere doing type stuff. And experts can make short cuts, either in Julia or in their editors...

I confess I'm a bit puzzled by having to change `[1:10]` to `[1:10...]`, but then again, `collect(1:10)` is more explicit and readable. So I think it's progress.

I suppose, as a former user of The Programming Language Formerly Known as Mathematica", I might be more grateful than others for a  less punctuation-heavy language syntax. Mathematica Wizards can fluently read and write code like this:

     lcm = Fold[#/#2/._~_~x_|_:>#x&,1,{##}]&

but I'm happy with a more readable approach.

Jeff Bezanson

unread,
Sep 3, 2015, 11:25:32 AM9/3/15
to julia...@googlegroups.com
For `[1:10]`, I recommend `collect(1:10)` or `[1:10;]`. Splatting
should be avoided where possible.

Tim Holy

unread,
Sep 3, 2015, 11:49:45 AM9/3/15
to julia...@googlegroups.com
The motivation for this change is so people can more easily construct arrays-
of-arrays. In the future, [1:10] will construct a Vector{UnitRange{Int}}, not
a Vector{Int}. [1:10;] is concatenating and makes a Vector{Int}. (The first
does too, but we need a release cycle with deprecation warnings before we can
change it.)

--Tim

Scott Jones

unread,
Sep 3, 2015, 11:54:05 AM9/3/15
to julia-users


On Thursday, September 3, 2015 at 11:22:09 AM UTC-4, cormu...@mac.com wrote:
Early adopters shouldn't throw stones... :) But in fact I quite like the new Dict syntax, which seems to be more explicit and readable. Curly braces seem to be gainfully employed elsewhere doing type stuff. And experts can make short cuts, either in Julia or in their editors...

It's not a matter of throwing stones, IMO.  It's trying to help guide the language so that it is better for everyone.  Discussion and bikeshedding may ensue, but I think it is an important part of making the language better than it already is.

I'm a huge fan of Julia (and the creators/contributors), but that doesn't mean that I think it is perfect (although it's great and getting better daily).
(Maybe in some sense Scheme was perfect, but I'd still rather program in Julia)

Scott Jones

unread,
Sep 3, 2015, 12:00:48 PM9/3/15
to julia-users


On Thursday, September 3, 2015 at 11:22:09 AM UTC-4, cormu...@mac.com wrote:
Early adopters shouldn't throw stones... :) But in fact I quite like the new Dict syntax, which seems to be more explicit and readable. Curly braces seem to be gainfully employed elsewhere doing type stuff. And experts can make short cuts, either in Julia or in their editors...

I confess I'm a bit puzzled by having to change `[1:10]` to `[1:10...]`, but then again, `collect(1:10)` is more explicit and readable. So I think it's progress.

Why is that a puzzle? [1:10] seems like it should be a vector with one element, a range 1:10.
The fact that it automatically splats is a bit of a surprise, which doesn't feel consistent.
Dict(:range=>1:10) does what I'd expect.

I'm hoping that that is being deprecated so that in 0.5 in can do the more consistent thing.

cormu...@mac.com

unread,
Sep 3, 2015, 12:20:51 PM9/3/15
to julia-users
"Why is [1:10...] a puzzle?"

Just that a new user might expect to see or use the ellipsis in its conventional position:

    [1...10]

rather than at the end:

    [1:10...]


Scott Jones

unread,
Sep 3, 2015, 12:25:04 PM9/3/15
to julia-users


On Thursday, September 3, 2015 at 12:20:51 PM UTC-4, cormu...@mac.com wrote:
"Why is [1:10...] a puzzle?"

Just that a new user might expect to see or use the ellipsis in its conventional position:

    [1...10]

[1...10] may be conventional outside of julia (is that done in other programming languages, or just in math?), but 1:10... does seem very consistent with the rest of julia's uses of the splat operator and unit ranges, so it doesn't seem at all surprising to me.
When I saw it, I knew immediately what it meant.

Scott Jones

unread,
Sep 3, 2015, 12:28:27 PM9/3/15
to julia-users
To me, the use of ; within [ ] seems pretty confusing.
Elsewhere in Julia, it seems to mean, throw away the result, so I would have expected [1:10; ] to be equivalent to [].
Why is [1:10;] (confusing, ; is not consistent with any other uses in Julia),
preferred over [1:10...] (easy to understand, consistent with other uses in Julia)?

Sean Marshallsay

unread,
Sep 3, 2015, 1:47:07 PM9/3/15
to julia-users
[1:10;] is simply a consequence of matrix literal syntax (like [1:10; 11:20]) and gets translated into vcat(1:10). It might be a bit confusing but there's no point in making it a special case.

Scott Jones

unread,
Sep 3, 2015, 3:06:22 PM9/3/15
to julia-users


On Thursday, September 3, 2015 at 1:47:07 PM UTC-4, Sean Marshallsay wrote:
[1:10;] is simply a consequence of matrix literal syntax (like [1:10; 11:20]) and gets translated into vcat(1:10). It might be a bit confusing but there's no point in making it a special case

Yes, I understand that, and that too is not consistent with the use of ; outside of [ ].
spaces, colon, semicolon, and commas are all treated specially instead of [ ], which can be rather confusing.
Some of that special behavior is being deprecated, but some remains.
 

Jonathan Malmaud

unread,
Sep 3, 2015, 3:11:34 PM9/3/15
to julia-users
What are the other uses of ; in Julia? I can only think of suppressing output on the REPL and separating expressions on a single line - neither seems inconsistent or really related at all to the use within []. 

Scott Jones

unread,
Sep 3, 2015, 4:21:55 PM9/3/15
to julia-users
Another use is marking off the keyword arguments or parameters.

Mike Innes

unread,
Sep 3, 2015, 4:40:54 PM9/3/15
to julia-users
FWIW I mocked up a json syntax macro:

using MacroTools, Lazy

import MacroTools: prewalk

function prockey(key)
  @capture(key, (a_:b_) | (a_=>b_)) || error("Invalid json key $key")
  isa(a, Symbol) && (a = Expr(:quote, a))
  :($a=>$b)
end

function procmap(d)
  @capture(d, {xs__}) || return d
  :(Dict{Any, Any}($(map(prockey, xs)...)))
end

macro json(ex)
  @>> ex prewalk(procmap) esc
end

Michael's original example becomes:

data = @json {
        displayrows: 20,
        cols: [
                    { col: "l1" },
                    { col: "l2" },
                    { col: "l3" },
                    { col: "num", display: true },
                    { col: "sum", display: true, conf: { style: 1, func: { method: "sum", col: "num"  } } }
                ]
      # ...
    }

You might argue that it's actually nicer than the original.

Michael Francis

unread,
Sep 3, 2015, 5:13:28 PM9/3/15
to julia-users
That's really quite nice and for the purpose of interfacing with JSON is certainly clearer. 

Scott Jones

unread,
Sep 3, 2015, 7:20:53 PM9/3/15
to julia-users
I must say, that's beautiful!  I hope I can figure out just how it is doing it's magic, as I didn't think macros could change the way things like { } and : were handled.   👏


On Thursday, September 3, 2015 at 4:40:54 PM UTC-4, Mike Innes wrote:

Jeffrey Sarnoff

unread,
Sep 3, 2015, 8:12:50 PM9/3/15
to julia-users
tip o' hat to that

this minor edit, omitting {Any,Any} (following Jeff B's note) gives back some autotyping 


 function procmap(d)
         @capture(d, {xs__}) || return d
         :(Dict($(map(prockey, xs)...)))
       end

On Thursday, September 3, 2015 at 4:40:54 PM UTC-4, Mike Innes wrote:

Jeffrey Sarnoff

unread,
Sep 8, 2015, 2:49:29 AM9/8/15
to julia-users
Do others get this warning? If so, what modification of Mike's macro avoids it?

WARNING: deprecated syntax "{a,b, ...}".
Use "Any[a,b, ...]" instead.

Michael Turok

unread,
Sep 8, 2015, 11:59:52 AM9/8/15
to julia-users
That is elegant....if I only could follow how it works....


On Thursday, September 3, 2015 at 4:40:54 PM UTC-4, Mike Innes wrote:
Reply all
Reply to author
Forward
0 new messages