Live data from Hacker News

Language Design: Use 'ident: Type' not 'Type ident'

soc.me

121–130 of 192 posts

Re: Language Design: Use 'ident: Type' not 'Type ident'

#121
post #7

This feels a little nitpicky/idealistic, I don't think the post does a good job of conveying why it's more beneficial. > This means that the vertical offset of names stays consistent, regardless of whether a type annotation is present (and how long it is) or not. Why is this necessarily desirable? Strong typing systems have very expressive types, to the point where if something is typed correctly, most of the time my…

> Maybe this is nice in theory? But `Int` really isn't an output here, and the value being assigned isn't either. Rather this seems more like `f(i, Int, value) -> assignment`. It seems just as arguable that `f(Int, i, value) -> assignment` is appropriate.

The point is that you want variable declarations and function signatures to be consistent, so you either write

    val i : Int
    def f(x: Int) : String
Or

    Int i
    String f(Int x)
And if you do the latter then you have a confusing syntax because the output type comes before the input type, and it's very hard to do lambdas in a way that looks consistent.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#122
post #106

Earlier quoted context omitted.

I find the opposite, I can't stand it. Give me curly braces over arbitrary indentation any day.

I think a better (subjective of course) lesson might be to enforce a style. I have been thinking about making a toy compiler (I wanted to write a borrow checker) that treats bad code as an error, solely aimed at numerical code - I have recently had "Scientific Programming in Python for physics etc." inflicted on me. Slight tangent, but I think if Haskell enforced some kind of whitespace a la Python it would be much m…

What do you mean? Whitespace does mean something in Haskell, see http://echo.rsmw.net/n00bfaq.html .

Re: Language Design: Use 'ident: Type' not 'Type ident'

#123
post #12

A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…

It's a historical problem in C. Originally, C had only built-in types. Structs were declared with struct foo { int x; int y; }; which is easy to parse. Then came typedef. With user-defined types, foo*bar; isn't parseable with a LALR(1) parser until you've seen the definition of "foo". Even the ordinary case foo bar; needs more than one lookahead to parse. This is a headache for compilers, and a huge headache for anyt…

Years ago, I stumbled upon a Visual C++ 6.0 bug (if memory serves me right), just by playing around trying to understand C/C++ decls. It would crash on a stray:

   *c;
at the beginning of a translation unit.

Didn't K&R have a tiny, tiny C declarations parser (printing out 'human readable' equivalents) example in their book? I think the caveat was that it needs to assume it's dealing with a declaration...

Re: Language Design: Use 'ident: Type' not 'Type ident'

#124
One downside of the 'ident: Type' approach is the extra colon character.

The major downside of the 'Type ident' approach, is that if 'Type' is optional, then the parser can't be sure if its parsing the 'Type' or the 'ident' when encountering the first token. In practice this isn't too hard to solve however, it can be handled with some backtracking.

In my language, Winter, I have chosen the 'Type ident', approach, mostly due to similarity with C, C++ and Java. I do sometimes wonder if I made the right choice however. Maybe it could be an option? :)

Re: Language Design: Use 'ident: Type' not 'Type ident'

#125
post #76

Earlier quoted context omitted.

To declare two pointers to int in C: int *a, *b; In D: int* a, b; The use of whitespace makes the distinction clear, although the parser doesn't care.

C is just riddled with mistakes and this one finally gelled with me. Python taught me that whitespace is great for syntax and, in this case, I'm quite convinced that it should be used more firmly in most languages.

Python's syntax precludes works against a lot of things, like first-class lambdas, case (yes it can be emulated with if/elif, but it's not the same, even without fallthrough), pattern-matching in general, or assigning the result of a method-chaining pipeline to a variable.

I use python at $dayjob, and I run into the limitations of whitespace as syntax all the time.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#126
post #40

Strong disagreement here. "type ident" flows with the data during assignment, doesn't confuse the infix operators, and doesn't misuse ":" from a human-language standpoint. For example: val x: String = "hello" The type interrupts the flow of data from "hello" to x, so one thing that pops into mind is that this is typecasting the value to a string before storing it. Nope. Another possibility I instinctively see this as…

I was going to say the same thing about meaning flow.

But here's an idea. The OP wants meaning to flow left to right for lambda declarations. Why not have assignment go that way too.

    "Hello" => x: string
Might work. Computer science pseudocode uses notation kind of like that.

Also, I understand now why Scala and Rust always seemed clunky to me.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#127
post #90

Earlier quoted context omitted.

I agree, though I could see the merit for a standalone declaration: val x: String x = "hello" The type at this point is almost like a comment. For declaration and assignment though, I agree that reading "ident: Type" is harder for me. Perhaps an interesting idea would be to have the type at the end of the expression . Like so: val x = "hello": String Essentially, you're making a type assertion on an expression. Since…

Most statically typed languages don't even need the type assertion in a case like this, though. A literal has a definite type (hopefully), so the type of x can be inferred. val x = "hello" Standalone declarations are the most important problem to solve here.

Yeah, type inference is preferred (and pretty common). I'm just saying that, if I had (or wanted to) set the type, at the end of the expression would be my preferred place.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#128
post #46

Earlier quoted context omitted.

> Not sure about Rust Rust has made a point of being parser-friendly, to support tooling. The entire reason the turbofish :: exists is to avoid ambiguous grammar. (This operator seems to vex people, I don't get the hate.)

Being parser-friendly is not at all the same thing as being user-friendly. The difficulty of writing parsers is way overblown. One thing to avoid is depending on the existence of the symbol table to parse correctly. (C++ has this problem.) Needing a symbol table makes it hard for parsers like source code formatting and syntax highlighting. Another is to avoid raw string literals that reach back and try to unwind the…

Both humans and computers parse code. Humans can handle ambiguity mode easily than computers, but that doesn’t make the ambiguity more user friendly somehow.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#129

A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…

I was just thinking about pointer syntax today, and if you ask me, there are a lot of problems that could be avoided if language designers took a page out of Guido van Rossum's book and extend his idea of forced spacing. Take the first example you've given, and let's just talk about variable declaration: int* a; int * a; int *a; That's all the same. That's wrong. Obviously, you can write a lexer and parser that doesn…

There are four possible spacings to consider:

  foo*bar; // multiplies foo and bar
  foo* bar; // declares bar as pointer-to-foo
  foo *bar; // declares *bar as foo (so bar is still a foo*)
  foo * bar; // multiplies foo and bar
These are all unambigous and there are only two semantics between them. You also have:

  foo* bar,baz; // baz is a pointer
  foo *bar,baz; // baz is a foo
  foo *bar,*baz; // baz is pointer again
  foo* bar,*baz; // baz is now a pointer *to* a pointer
This is all obvious - or at worst unambigous - to a person reading the actual code (without trying to correct for the idiosyncracies of a parser), so the language should either match that or spit out a warning about unsupported spacing.

> [`int c = x*y;` is] wrong.

No, that's unambigously multiplication.

Re: Language Design: Use 'ident: Type' not 'Type ident'

#130

Earlier quoted context omitted.

I agree, though I could see the merit for a standalone declaration: val x: String x = "hello" The type at this point is almost like a comment. For declaration and assignment though, I agree that reading "ident: Type" is harder for me. Perhaps an interesting idea would be to have the type at the end of the expression . Like so: val x = "hello": String Essentially, you're making a type assertion on an expression. Since…

But now it's difficult to declare that x is single assignment.

Not sure that's true. I'd I say:

  let x = "hello": String
  let x = "world": String
If 'let' is a keyword that implies single assignment, then problem is solved.

Alternatively, using pattern matching alarm Erlang would be even better:

  x = "hello": String //x is bound to "hello"
  x = "hello": String //equality check is successful
  x = "world": String //Error: values not equal
Post reply on HN