Hello all, i'm trying to figure out a language syntax and I keep going in circles, maybe some opinions from other devs may help.

For a given programming language what is the most efficient & cleanest way of describing a variable, type, etc?

Here is a list of ones I have considered. (psudocode)

C style (structs and return type prefix), pros: simple, really succinct, cons: annoying lexing because return type is ambiguous.

struct Vec3 {
  f32 v[3];
}
struct Player {
  char *username;
  Vec3 pos;
  Color appearance;
}
Player[] login(Player p, char *password) {
...
}
Player me("me", Vec3(0.0,0.0,0.0), Color(255, 0, 0));
login(me, password);

Rust style (function prefix, arrow return type), pros: separation of data and implementation makes composition easier. Cons: not very intuitive for learners.

struct Player {
  username: str,
  pos: Vec3,
  appearance: Color,
}
impl Player {
  fn login(self, pass: str) -> Vec<Player> {
  ...
  }
}
let me: Player = Player {username="me", ...
me.login(password);

Typescript style (similar to rust but without arrows, also OOP). pros: simple, easy to understand. cons: OOP can cause problems

class Player {
  username: string;
  pos: Vec3;
  appearance: Color;
  constructor(username: string, pos: Vec3, appearance: Color) {
    this.username = username;
    ...
  }
  login(password: string):Player[] {
  ...
  }
}
let me: Player = Player(...
me.login(password);

Fortran style (types below definition). Pros: clear whats going on? (maybe too used to fortran weirdness). Cons: extremely verbose.

type player
  string :: username
  real(kind=32), dimension(3) :: pos
  integer(kind=8), dimension(3) :: appearance
contains
  procedure :: login
end type player

player function init_player(username, position, appearance) result(this)
      string :: username
      real(kind=32), dimension(3) :: position
      integer(kind=8), dimension(3) :: appearance

      this%username = username
      this%position = position
      this%appearance = appearance
end function

function login(this, password) result(players)
  class(player) :: this
  string :: password
  player, dimension(:), allocateable :: players
  ...
end function
...
player :: me
me = Player("me" ...
me%login(password)

Go style, types after like rust/typescript but no :, interfaces instead of OOP, prefix types on the left of functions. Slices also backwards. Pros: simple, cons: syntax is backwards and weird, implementing a tupe would be annoying.

type Player {
  username string
  position Vec3
  appearance Color
}
func (p Player) login(password string) []Player {
...
}
me := Player("me" ...
me.login(...

Let me know what you think, thanks all!

  • kleeon [he/him, he/him]
    ·
    6 days ago

    I find how Odin does things pretty interesting. It is somewhat Pascal-like but has some differences. In short:

    Variable declaration looks like this:

    someNumber: int = 123

    You can drop the type though and the compiler will infer it for you:

    someNumber := 123

    In order to declare a constant, you replace = with : to get this:

    aConstant: int : 456

    And with type inference:

    aConstant :: 456

    Odin has functions(or procedures in Odin parlance) as first-class citizens, so procedure declaration is simply a constant declaration:

    doStuff :: proc(stuff: int) -> int {
       return stuff + 1
    }
    

    This kind of syntax has been first used in Jonathan Blow's programming language, so there is another example if you want to learn more. Though it's not public yet unfortunately

    • zongor [comrade/them, he/him]
      hexagon
      ·
      5 days ago

      I have taken a look at Odin, its interesting, its kinda like a bunch of different languages, its got the postfix types like typescript, rust, etc but other structures similar to Go or Pascal.

      • kleeon [he/him, he/him]
        ·
        5 days ago

        Yeah I've been checking in on it for a couple of years now and it seems like the most promising C replacement so far