I've been enamored with the fantasy of making a programming language for a while. Not that I think I ever will, but I like to think about how it would work. I think I've learned a lot from studying very different languages and that I know how to combine the best ideas from all of them. I also think some of my ideas are genuinely original (as far as I've seen) and pretty good. And there's some chance someone who is in a position to design or influence a language will read this and get my good ideas. So here's the working spec for what I'd consider an ideal language. It's working name is Gold and stands for "Go Over Limits, Doofus".

Basic usage

The error handling strategy

Ignore an error:

    err ignore

Throw with context:

    err "dangerous failed"

Get the error reference:

    err(e) "dangerous failed because:" + e

Different behavior for different error types:

    err_index ignore
    err_os close(file)

An index error will be ignored, an OS error will close file and then throw, and any other type of error will just throw.

Multi-statement err blocks:

    	print("An error occurred: " + e)

try block:

err ignore

The error will be caught and ignored if it happens anywhere in the try block.



Infix operators

Flow control


branch if cond1
if cond2

Single statement clauses can be written on the same line with a colon:

branch if cond1: do_1()
if cond2: do_2()
else: do_default()

This is also an expression:

var = branch
    if cond1: val1
    if cond2: val2
    else: val3

Clauses can be put onto one line:

function(branch if cond1: val1; if cond2: val2; else: val3)

branch is always necessary so that there's never any ambiguity about whether a lone if or if-else is part of the preceding branch or not. For example:

branch if cond1: do_1()
if cond2: do_2()
if unrelated_cond: do_thing_that_should_happen_regardless_of_cond1_and_cond2()

I don't want to need to indent branches under branch, or have an endbranch keyword or something. So that last part should just be written as:

branch if cond1: do_1()
if cond2: do_2()
branch if unrelated_cond: do_thing_that_should_happen_regardless_of_cond1_and_cond2()

A branch ends at the first statement on its level that doesn't start with if or else.


while condition

for counter, item from items where criterion - iterates on elements of items where criterion is true, binding the element and the iteration counter to item and counter. Counter is not incremented when an item is skipped due to failing the criterion. If you want it to still increment, filter using a continue statement instead of the where clause in the loop header.

break and continue can take an arg that says how many levels of loop out to go.


Generator expression:

results = function(v) for v from inputs where condition(v)

The results are not evaluated immediately, but they can be iterated on.


results = Array (function(v) for v from inputs where condition(v))

Converts the results to an Array (not lazy), so they're all evaluated.

Function declarations

Functions are values, so there isn't a keyword to declare them; you just use the => to define a function literal and name it.

double_num = num =>
    num * 2

# Default value
greet = (name = "Anon") =>
    print "Hi, " + name + "!"




struct Person
    # The colon specifies the type of the field.
    name : String
    age : Int
    # The = specifies a default value, inferring the type.
    admin = false

alice = Person(name = "Alice", age = 22)


struct Programmer
    include Person
    lang : String

bob = Programmer(name = "Bob", age = 46, lang = "Gold")

Any function that wants a Person will accept a Programmer.


enum Color

Color is inferred to be an enum of String, so it can be casted to string without a converter function.

The enum values can also be given names:

enum Color
    "blue" blue
    "red" red
    "green" green
    "yellow" yellow

Other thoughts

This page was last modified (UTC)