Why is a space necessary before : in method args?

Back when I started learning Crystal, it took me a while to figure out my first compiler error. I had

def blah(a: Float64)

and eventually figured out I should have

def blah(a : Float64)

Why is that space necessary? Would there be some syntax conflict if the compiler accepted “a:” instead of “a :”?

There’s no conflict when declaring an argument, but when calling a. method there’s a difference. That’s why I wanted the syntax to be the same in the definition side to avoid confusion.

Maybe the error message could be improved? It points you to the location in your code and tells you

space required before colon in type restriction

IMO that pretty precisely tells you what to do. But I have a different view that a beginner.

What would’ve helped you to figure it out faster?

I’m not sure I follow. An example, please?

When calling a function there would be no def ? Cant that work as distinction instead of whitespace ?

What I mean is these are two different things:

call foo: Int32
call foo : Int32

The first one is calling call with foo as a named argument with the value Int32 (a class type).

The second one is calling call with a single argument being a type declaration foo : Int32, which is usually (only) used in macros. One such example is property:

property foo : Int32

That’s the difference. And because foo : Int32 means “foo with a type Int32” but foo: Int32 means "an argument foo with a value of Int32` and in method declarations you want to specify a type, not a value, the former syntax is used in method declarations.

If you have proposals to improve this situation I’m all open to them!


named tuples died for this

Good that someone ask it, I have been thought about it for long time on syntax design.

Simply it’s clearer if we could get rid “:” between variable and type, you save typing and space.

properties items Int32

Go language makes types look easier for programmers to interpret like slice array of Int32:


Compare to Crystal which:

Array of Int32

: shows a relationship (connection) between two objects, I like it.

That’s not going to work because there’d be no way to tell a variable declaration from am method call.

Crystal generics are much more generalized and can be used for many other purposes besides arrays. It’s good to not have a different syntax for a single use case.