jamiebuilds / ghost-lang

:ghost: A friendly little language for you and me.
302 stars 10 forks source link

Map / Set syntax 🚲 #27

Open aleclarson opened 6 years ago

aleclarson commented 6 years ago

FWIW: I don't love the aesthetic of {= =} and {- -}.

Below is my proposal (other proposals are invited to this thread):

let map = Map {
  1 => 2,
  2 => 3,
  3 => 4,
}

let set = Set [ 1, 2, 3 ]

The idea is to remove cryptic syntax ({= and {-) and make map keys look less like variable assignments.

Along the way, I'm playing with the idea of function calls being able to omit the parentheses when only one argument is passed and it's an object/array literal.

jamiebuilds commented 6 years ago

I did think of map and set being keywords, but I don't want [|arrays|], maps, and sets to feel like second class citizens, or like they are somehow significantly different from records or lists.

A lot of the things that are possible in records are also possible in maps and sets, and they share a lot of syntax. So I want them to feel conceptually similar

aleclarson commented 6 years ago

I agree, they should feel first-class.

You wouldn't really need the Map keyword since 1 => 2, indicates a map to the compiler, and you wouldn't be able to mix that with a: 1 syntax.

let record = { a: 1, b: 2 }
let map = { 'a' => 1, 'b' => 2 }

For lists, arrays, and sets:

let list = [ 1, 2, 3 ]
let array = +[ 1, 2, 3 ]
let set = -[ 1, 2, 3 ]
aleclarson commented 6 years ago

It might be interesting for lists to use parentheses.

let list = ( 1, 2, 3 )
let array = [ 1, 2, 3 ]
let set = [[ 1, 2, 3 ]]
jamiebuilds commented 6 years ago

This won't work because a list of a single list is a valid thing people may want to do and relying on their being a whitespace is hard to notice.

let set = [[ 1, 2, 3 ]]

let list = ( 1, 2, 3 )

There's already a lot of use of parenthesis in expressions. I don't want there to be many places where you have parenthesis next to each other:

let a = fn((a && (fn())))

Also, you have to deal with a lot of syntax ambiguities when using the (grouping && syntax). It just generally gets confusing.


let record = { a: 1, b: 2 }
let map = { 'a' => 1, 'b' => 2 }

How do you create an empty map? I don't want the answer to be new Map()

I also don't want to have huge lookaheads in the parser to figure out what { means.


I can see an argument for => over = but I think it's already going to have to be something people get used to, and I liked how {= and = matched up. So much so that I've thought about doing this:

let map = {=
  'keyA' = 1,
  'keyB' = 2,
=}

let record = {:
  keyA: 1,
  keyB: 2,
:}

let set = {
  1,
  2,
}
j-f1 commented 6 years ago

How about getting rid of the regular record syntax and requiring that it be annotated with a type?

let record = Person {
  name: "John Doe",
  age: 42
}

This would free up {} for maps, and perhaps {{}} for sets.

Also, Python uses (a, b, c) (parens are optional in most cases, that’s how you can do a, b = b, a) as a tuple, or readonly array.

j-f1 commented 6 years ago

There could also be a sigil (_, perhaps) that would infer the type:

let record = Person {
  name: _ {
    first: "Jane",
    last: "Doe"
  },
  age: 42
}
aleclarson commented 5 years ago

Would empty map be {==} or {=}?

I think {: a: 1 :} would be unbearable when using records a lot.

How about the following?

let map = { 'a' = 1, 'b' = 2 }
let empty = <Map>{}

let set = { 1, 2 }
let empty = <Set>{}

let record = { a: 1, b: 2 }
let empty = {}

PS: Not a fan of the required type annotation for records that @j-f1 suggests.

jamiebuilds commented 5 years ago

This is the other syntax that I'm considering with keywords:

let map = map { 'a' = 1, 'b' = 2 }
let empty = map {}

let set = set { 1, 2 }
let empty = set {}

let record = { a: 1, b: 2 }
let empty = {}
tekknolagi commented 5 years ago

You could also have everything use constructors:

let m = map(a=1, b=2)
let s = set(1, 2, 3)
let r = record(a=1, a=2)
let a = array(1, 2, 3)
# etc