Skip to content

Instantly share code, notes, and snippets.

@PhilipWitte
Created September 21, 2013 08:58
Show Gist options
  • Save PhilipWitte/6648742 to your computer and use it in GitHub Desktop.
Save PhilipWitte/6648742 to your computer and use it in GitHub Desktop.
Nimrod - feature suggestions

Changes I would love to see in Nimrod.

"Good Syntax" is often heavily subjective. So it makes sense to allow people to program in the styles they like best. I would argue that there is also value in the ability to lock-up and restrict syntax features (for things like compile-to-OpenCL, or game scripts), but that's beyond the scope of this document.

Many programmers prefer empirical style to functional. In the order to attract these people to Nimrod, and to give all developers freedom of expression, I have a few ideas on how to change and extend Nimrod to support a more empirical coding style, in addition to it's already great functional style.

type

First, a gripe. I don't like the inconsistency of type syntax. No other object is defined this way in the syntax. The following:

type Foo = object
  ...

type Bar = object of Foo
  ...

would be best if expressed similar to 'proc's style:

type Foo =
  ...

type Bar: Foo =
  ...

Alternatively, as Araq said in a recent conversation, the following short-hand syntax would accomplish the same thing:

object Foo =
  ...

object Bar of Foo =
  ...

Reverse UFCS

Just as function proc foo(a:bar) can be called as both foo(b) and b.foo() due to UFCS, I think it makes sense to also allow the definition to appear as both functional, and empirical, to fit the programmers preference. For example, the following two functions would be identical:

proc bar(this:Foo) =
  echo this.baz

proc Foo.bar() =
  echo this.baz

Just as result is automatically defined within procs which return a type, this could be automatically defined as an parameters for procs which are defined with a type prefix.

init

Inits would be a special type of proc, which are callable from both the Type reference (in which case they act as factories), or by an instance (in which case they act as initializers).

Similar to above UFCS example, init's would auto-define a this parameter as the type either prefix if declared using empirical style, only as the return type rather than a parameter (alternative would be to use result). For example, the following two inits would be identical:

init new(name:string): Person =
  this.name = name

init Person.new(name:string) =
  this.name = name

Empirical Nimrod Example

The following is a quick example of the features combined.

# Person

type Person =
  name: string
  age: int

init Person.new(name:string, age:int) =
  this.name = name
  this.age = age

proc Person.greet(name:string, age:int) =
  echo "Hi, my name is ", this.name, "."
  echo "I am ", this.age, " years old."


# Employee

type Employee: Person =
  salary: float
  
init Employee.new(name:string,, age:int, salary:float) =
  this.new(name, age)
  this.salary = salary

proc Employee.greet() =
  (this as Person).greet()
  echo "I make ", this.salary, " per year."


# main

block main =
  var bob = Person.new("Bob", 28)
  var joe = Employee.new("Joe", 26, 25_000)
  bob.greet()
  joe.greet()

Another example of init

type Image =
  width: int
  height: int

init Image.new(width, height:int) =
  this.width = width
  this.height = height

init Image.load(path:string) =
  var bitmap = Bitmap.load(path)
  this.width = bitmap.width
  this.height = bitmap.height

block main =
  var image = Image.new(512, 512)
  canvas.drawImage(image)
  
  image.load("some/image.png")
  canvas.drawImage(image)
  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment