Syntax styles in programming languages

This is a collection of different syntactical styles in programming languages. It’s woefully incomplete.

Directly relevant:

Other resources:


Single line comments:

Multi-line comments:

Multi-line comments might not really be that useful.

Indentation and bracing

Braces (C, Java, … style):

stuff {

doend (Ruby style):

stuff do

Explicitly naming the thing to end:

end stuff

There’s also bash’s bizarre way of ending statements, with reverse keywords like elihw and esac, but that’s just silly.


Regular math-style or C-style function calls:

plus(2, 3)

Haskell-style calls (without parentheses):

cos pi
plus 2 3

OO-style calls (Smalltalk style):

pi cos
2 plus: 3

OO-style calls (Ruby style, i.e. no parentheses needed):


This approach makes it non-trivial to get hold of the method as an object.

OO-style calls (JavaScript style):


Getting hold of the method itself is simple in this case.

The question of how the method is bound remains. If you get the method, is it still bound to the original object, or not? If not, how do you call it? Do you pass self as the first argument, perhaps?

Concatenative style (like Forth and Factor):

pi cos
2 3 plus

To do: Describe named parameters

Function definitions

No braces, implicit return:

fun greeting()

The parentheses, if no parameters are available, could be left out:

fun greeting

Braces, explicit return:

fun greet() {
  return "Hello!"

Braces, shorthand, implicit return:

fun greet() = "Hello!"

With positional parameters:

fun greet(name)
  return "Hello, ${name}"

With default value, assigned using = (Python style):

fun greet(name = "stranger")
  return "Hello, ${name}"

With default value, assigned using : (Ruby style):

fun greet(name: "stranger")
  return "Hello, ${name}"

Using : can conflict with type declarations.

Different parameter name when calling and inside function definition (like Swift):

func greet(person: String, from hometown: String) -> String {
  // use `hometown` here

greet(person: "Jake", from: "Berlin")

Positional parameters can be opt-in, using _:

func greet(_ person: String, from hometown: String) -> String {
  // use `hometown` here

greet("Jake", from: "Berlin")

To do: Describe variable-argument definitions


Dereferencing in C, C++, …:


Dereferencing in Zig:


In Swift, an argument can be passed in to be mutated by specifying inout on the parameter:

func play(game: inout Game) {
  // …

In C#, on the caller side, ref is used, but the parameter is the same:

Game Update(Game game, int guess) {
  // …
Play(ref game);

Method definitions

To do: associated functions

To do: instance variables

To do: self (this instance), e.g. this.doSomething()

To do: self (this type), e.g. new thisClass




With interpolation, Ruby style:

"Hello, #{name}"

With interpolation, Python style:

f"Hello, {name}"

With interpolation, JavaScript style:

`Hello, ${name}`

With interpolation, Swift style:

"Hello, \(name)"


Ruby: "a" or ?a — there is no difference between characters and strings.

Crystal: 'a'


I’m leaving out old-school C-style for loop iteration because I think it’s too old-school.

Dedicated for construct:

for elem in iterable {
    // …


iterable.each(func (elem) {
    // …

Note that the above can’t use return to break out of the loop. Smalltalk-style non-local returns would allow that, but it’d return from the function entirely:

"a strange way to get the first element of an iterable"
iterable do: [:elem | ^elem]

Ruby has blocks and functions, and thus has nonlocal returns and can break out of blocks. Ruby also has a ton of custom iterators, like #times:

12.times do
  # …



struct Something {
  Type myProp;


struct Point
  property x, y

  def initialize(@x : Int32, @y : Int32)

Crystal has explicit initializer. The initializer syntax is nicer than Ruby’s, in that it removes some duplication by allowing params to be declared as ivars.


const Point = struct {
    x: f32,
    y: f32,

const p = Point {
    .x = 0.12,
    .y = 0.34,

Using the same syntax for types (const Point = struct …) as for values (const p = Point …) is interesting. Maybe confusing, though?


  Animal* = object
    name*, species*: string
    age: int

var carl: Animal
carl = Animal(name : "Carl",
              species : "L. glama",
              age : 12)

I like how types can be used as functions to construct instances.



Ugh! This one is complicated. Common ways to check for equality are:

Different types of equality to take into account:

Ruby’s === is confusing (“case equality” is ambiguous and hard to explain).

See Equality in programming languages.

Discard return value

Some programming languages require a return value to be used, or error instead.

_ = myFunction()

C++ can use [[nodiscard]] to require a value to be used, but it’s opt-in:

int update() {
  // …

Nim uses the discard keyword:

discard myFunction()

Pure functions and constant expressions

GCC allows adding __attribute__((const)) to claim that a function is pure (even if it is not!):

auto update(Game game, int guess) -> Game {
  // …

GCC also allows constexpr to mark something as being able to be executed at compile time:

auto update(Game game, int guess) -> Game {
  // …

Rust supports const functions, which are also able to be executed at compile time:

const fn update(game: Game, guess: int32) -> Game {
  // …


Koka defines a handful of effect types, including:

Additionally, pure is an alias for exn and div.


Note last edited November 2023.