The following RFC is for more bikeshedding about syntax of the Relay text format not covered by #1782.
The guiding principles for syntax choices are - **readability:** Syntax should be easy to read and parse visually. - **internal consistency:** Syntax choices should be similar to each other (e.g. function definitions and function types should have similar syntax). - **external consistency:** We should strive to reuse existing syntax choices from other languages so users that are familiar with those languages have less to learn. Also existing syntax choices are _usually_ well-thought-out. **Please provide feedback on the syntax choices below or other syntactic features you think should be discussed that weren't already agreed on in #1782.** ## References ### RefCreate Existing languages: OCaml ``` ref 5 ``` ReasonML ``` ref(5) ``` Relay Proposal ``` ref(5) ``` ### RefRead OCaml ``` r := v ``` ReasonML ``` r := v ``` Relay Proposal ``` r := v ``` ### RefWrite OCaml ``` !r ``` ReasonML (adopted because `!` is already used for `not`) ``` r^ ``` It may be temping to use `&x`, but this implies that any expression has a reference, whereas in ML-like languages references must be created explicitly. Relay Proposal ``` *r ``` or ``` read(r) ``` Prefixes seem better than postfixes, but we need to avoid `!` do to ambiguity. I'm open to other suggestions. ## ADTs ReasonML ``` type myVariant = | HasNothing | HasSingleInt(int) | HasSingleTuple((int, int)) | HasMultipleInts(int, int) | HasMultipleTuples((int, int), (int, int)) ``` Rust ``` enum myVariant { HasNothing, HasSingleInt(int), HasSingleTuple((int, int)), HasMultipleInts(int, int), HasMultipleTuples((int, int), (int, int)), } ``` Relay Proposal ``` type myVariant = | HasNothing | HasSingleInt(int) | HasSingleTuple((int, int)) | HasMultipleInts(int, int) | HasMultipleTuples((int, int), (int, int)) ``` ## Pattern Matching ReasonML ``` switch (x) { | HasNothing => 0 | HasSingleInt(x) => 0 | HasSingleTuple((x, y)) => 0 | HasMultipleInts(x, y) => 0 | HasMultipleTuples((x, y), (q, r)) => 0 } ``` Rust ``` match x { HasNothing => 0, HasSingleInt(x) => 0, HasSingleTuple((x, y)) => 0, HasMultipleInts(x, y) => 0, HasMultipleTuples((x, y), (q, r)) => 0, } ``` Relay Proposal ``` match (x) { | HasNothing => 0 | HasSingleInt(x) => 0 | HasSingleTuple((x, y)) => 0 | HasMultipleInts(x, y) => 0 | HasMultipleTuples((x, y), (q, r)) => 0 } ``` `case` is also a viable alternative keyword. ## Generics (i.e. type arguments) Rust ``` enum Option<T> { Some(T), None, } fn takes_anything<T>(x: T) { // do something with x } ``` ``` let x: Option<i32> = Some(5); let x: Option<i64> = Some(5); ``` ReasonML ``` type Option('a) = | Some('a) | None ``` Scala ``` Some[A](a : A) ``` Python ``` Option[A] = Union[A, None] ``` Relay Proposal ``` type Option[A] = | Some(A) | None fn takes_anything[T](%x: T) { // do something with %x } let x = Some[i32](5); let x = Some[i64](5); ``` ## TupleGetItem ReasonML ``` ("foo",2,true).0 // "foo" ``` Rust ``` ("foo",2,true).0 // "foo" ``` Scala ``` ("foo",2,true)._1 // "foo" ``` Python ``` ("foo",2,true)[0] # "foo" ``` Relay Proposal ``` ("foo",2,true).0 // "foo" ``` ## Semicolons We need to consider whether or not to use semicolons as separators in sequence operations. The pros of using semicolons is they're easier to implement and allow us to ignore newline characters when writing and parsing programs. The cons are they are more cumbersome and make the text format less python-like. ## Attributes Python ``` def foo(a, b, c=None, d=None): ``` Relay Proposal ``` @foo(%a, %b, %c=None, %d=None) ``` when the attrs type index matches the operator's attrs type index ``` @foo(%a, %b, BarAttrs={%c: None, %d: None}) ``` when it doesn't. I'm not as certain about this syntax piece, so I'm very open to suggestions here. cc @tqchen @MarisaKirisame @jroesch @wweic @vinx13 @junrushao1994 @nhynes -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/dmlc/tvm/issues/3016