Optional use of commas

I’ve been thinking about the use of commas in code for a long time now, and am curious to see what observations others can make on the matter. The idea is this; commas are mostly (technically) unneeded in various programming languages since spaces, newlines, etc are sufficient to parse the code.

For example,

function my_contrived_example(str::String Alpha Beta Gama)
     a b c = something_interesting(...) # Do something interesting...
     println(str " A:" a " B:" b " C:" c)  # Granted, string interpolation would be prettier!
     return a b c
end

 A B C = my_contrived_example("Look, No commas!" 1 2 3)

… is both parse-able and quite understandable. It also has the advantage that it is terse.

Compare

 function my_contrived_example(str::String, Alpha, Beta, Gama)
     a, b, c = something_interesting(...) # Do something interesting...
     println(str, " A:", a, " B:", b, " C:", c)  # Granted, string interpolation would be prettier!
     return a, b, c
end

 A, B, C = my_contrived_example("Look, using commas!", 1, 2, 3)

Which one is prettier would certainly be debatable (I prefer the one without commas in this case). We are all use to seeing commas all over the place so many may prefer seeing them just because…

I didn’t like omitting semicolons a few years back and thought the code looked ugly without them but am now very use to (and prefer) omitting them unless I feel one is necessary. Could we similarly be addicted to using commas just because everyone always has? …a sort of self-perpetuating habit?

So, could a convincing case be made for making commas optional?
Pros:

  • Takes less space, bringing more code into viewable screen area (I hate H-scrolling).
  • Arguably, cleaner look, easier to read.
  • A few saved keystrokes and slightly smaller files.

Cons:

  • In a few cases, may lead to less readable code.
  • Most people are accustomed to using commas.

One solution to the problem of having a feature, or not, is to make it optional. This could provide the best of both worlds. Omit commas accept where they serve for clarity or serve some function.

Some randomly copied code:

using Dates: Year Month Week Day Hour Minute Second Millisecond
# vs
using Dates: Year, Month, Week, Day, Hour, Minute, Second, Millisecond
sub2ind_gen((3 5) 1 2)
# vs
sub2ind_gen((3, 5), 1, 2)

Well, those are a few of my thoughts on the matter but I’m curious of what others have to say about it. What are some pros and cons that I haven’t mentioned?

3 Likes

I’m mostly indifferent about spaces, but newlines as a separator is a hard no for me. Talking about spaces, maybe the use of commas comes from the fact that we use them in english to separate different items in a list of elements.

2 Likes

I would love something like this. Clojure treats commas as whitespace, so they’re allowed but optional.

The downside of this style is increased potential for ambiguity, particularly with operators. Is f(a + b) f(a, +, b) or f((a + b))?

3 Likes

Indeed, one of the greatest gains that comes with a language not having any notion of operator precedence rules is that you can get rid of commas with no confusion.

We can still make commas optional, it’d just be more confusing than a lispy language. There already is one context where we say commas are optional: macro calls. Recall that @foo x y z is equivalent to @foo(x, y, z).

According to the current parsing rules, if you wanted @f a + b to actually mean @f(a, +, b) then you should instead write @f a (+) b.

julia> :(@f a + b).args
3-element Array{Any,1}:
 Symbol("@f")
 :(#= REPL[14]:1 =#)
 :(a + b)

julia> :(@f a (+) b).args
5-element Array{Any,1}:
 Symbol("@f")
 :(#= REPL[15]:1 =#)
 :a
 :+
 :b

So yeah, there’s nothing technically stopping us from making commas optional across the language. The main barrier is that it makes a ton a of things look rather ambiguous if you haven’t memorized the parsing rules.

3 Likes

Feasibility, costs, and benefits of these changes are very difficult to assess in the abstract.

My impression is that at this point of Julia’s life cycle, a necessary (but not sufficient) condition for major surface syntax change ideas not to be totally ignored is PR that implements them.

2 Likes

To be clear, I wasn’t saying it was something we should do or that I’d support it.

I was just saying that the barrier to doing it is mostly social, not technical, since most of the parsing machinery is there already for macrocalls.

I don’t think we can really know this until the change is actually implemented.

Parsing has a lot of corner cases, which make surface syntax tricky to get right. Even after 1.0, parsing bugs come up from time to time.

I like to use both coma and space, both when writing English and code.

If there’s not enough room for both, then I think leaving out the space and keeping the commas is more readable.

For example: I think f(x,-y) would be better than f(x -y) even if they meant the same thing, but I’d still write f(x, -y) unless I was playing code golf.

Actually I like it just the other way round: Remove all whitespace from code and it is still compilable.
Not that I want to do this in real code, but there are some examples (don’t find them right now) where Julia needs a new line to parse the code correctly. And sometimes in these cases I would like to have the code in a single line.
Another example why I prefer the white space agnostic language is the famous white space indent for blocks in python. This, in my opinion, didn’t helped readability at all but is anoying as hell if something goes wrong with editors (tabs,space).

Readability is much more important than being as terse as possible, at least in a environment where more than one is working on the same code.

Of course this is mainly a matter of taste and others like it different.

Even without removing newlines, this is not something you can do in Julia at the moment, eg

julia> let a = 3
       [2 a;
       3 a]
       end
2×2 Array{Int64,2}:
 2  3
 3  3

julia> let a = 3
       [2a;
       3a]
       end
2-element Array{Int64,1}:
 6
 9

Eg

function f(a)
    let
        a = 1
        a += 1
    end
    a
end

function g(a)
    let a = 1
        a += 1
    end
    a
end

with

julia> f(3)
2

julia> g(3)
3

Using ; frequently makes this possible:

ff(a) = (let; a = 1; a += 1 end; a)
gg(a) = (let a = 1; a += 1 end; a)

(not that I am recommending one-liners in this particular case).

While I kind of admire the simplicity of, say, S-expressions (whitespace delimits, ()s group, and that’s pretty much it), making it a bit more complex apparently allows a much more powerful and terse syntax. I think it is worth it.

3 Likes

Thanks for the examples, I just didn’t have time to dig them out. I think there are examples where even ; and () are not enough to make them oneliners, but I have to search for it later.

In general I do not agree. Simple is fine as long as not so experts still can read it. Terseness is not more power, it is just terseness. Power is not connected to a terse syntax. And so on… But, all in all different tastes, maybe that is an important strength of a language: that it fits to several different styles of coding.

2 Likes

There is a problem with unary operators and optional use of commas, see this example:
case 1:

f(x,y) = 2x+2y
f(x) = 3x+1
f(2,-2) = 0 #the commas indicate that there are two variables

case 2:

f(x y) = 2x+2y
f(x) = 3x+1
f( 2 -2) # ? f(0)? f(2,-2)?

This may be a little OT here but there is at least one place where the use of commas seems inconsistent. We do

using GLM, CSV    # comma when loading packages

but we also do

add GLM CSV    # no comma in Pkg env

Makes for some minor annoyances sometimes (for me at least).

At least on newer Julias you can use commas as well. The Pkg REPL mode is not Julia code and is inspired by passing options to commands like rm foo bar, not rm foo, bar.

5 Likes

Again, that is an ambiguity Julia already dealt with for its macro system. If you want to distinguish between 2 -2 and 2, -2 you would just use parens and write 2 (-2) to mean 2, -2.

1 Like

yeah, i think so, but is one more keystroke!, (I’m mostly indifferent about this, but there are some people that there are not). this is just one corner case. one way to stop this is disallowing the use of unary operators (infix operators too?)