{"action":"created","issue":{"url":"https://api.github.com/repos/nim-lang/Nim/issues/3502","labels_url":"https://api.github.com/repos/nim-lang/Nim/issues/3502/labels{/name}","comments_url":"https://api.github.com/repos/nim-lang/Nim/issues/3502/comments","events_url":"https://api.github.com/repos/nim-lang/Nim/issues/3502/events","html_url":"https://github.com/nim-lang/Nim/issues/3502","id":114279797,"number":3502,"title":"New unambiguous generics syntax (generic arguments syntax)","user":{"login":"nanoant","id":103067,"avatar_url":"https://avatars.githubusercontent.com/u/103067?v=3","gravatar_id":"","url":"https://api.github.com/users/nanoant","html_url":"https://github.com/nanoant","followers_url":"https://api.github.com/users/nanoant/followers","following_url":"https://api.github.com/users/nanoant/following{/other_user}","gists_url":"https://api.github.com/users/nanoant/gists{/gist_id}","starred_url":"https://api.github.com/users/nanoant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nanoant/subscriptions","organizations_url":"https://api.github.com/users/nanoant/orgs","repos_url":"https://api.github.com/users/nanoant/repos","events_url":"https://api.github.com/users/nanoant/events{/privacy}","received_events_url":"https://api.github.com/users/nanoant/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/nim-lang/Nim/labels/RFC","name":"RFC","color":"1d1d1d"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-10-30T14:24:48Z","updated_at":"2015-11-02T11:35:48Z","closed_at":null,"body":"Current `some[A, B](x, y)` syntax has serious flaw, it uses same notation as array subscript operator, so the `some[A, B](x, y)` meaning depends on what `some` represents, and can be given when we know semantics of `some`. This makes it impossible to distinguish subscript call from generic call just using grammar (lexer), eg. doing syntax highlight in editor.\r\n\r\nThis implies some subtle problems, eg.:\r\n\r\n```nim\r\ntemplate arr: expr = [1, 2, 3, 4]\r\ntemplate arr2[N]: expr = N\r\n\r\n# ...  in some other galaxy far, far away:\r\n\r\necho arr[1] #<- template eval with no args then array access, or maybe something else\r\necho arr2[1] #<- template eval with 1 generic arg, or maybe something else\r\n```\r\nAs it can be observed above, we don't know what's going on until we see definition of `arr` and `arr2`, which often may be in separate file.\r\n\r\nTherefore we should take into consideration moving away from this array subscript like syntax to something exclusive to generic arguments. Here are some propositions:\r\n\r\n##### Current ambiguous syntax\r\nGeneric args supplied in `[Arg]`, same as subscript operator.\r\n```nim\r\nproc newSeq[A](size: int): seq[A] = …\r\n\r\nvar v: seq[int]\r\nlet x = newTable[string, int]\r\nlet y = newSeq[int](10)\r\nlet z = newList[10](1) # static\r\n```\r\n\r\n##### 1.1. Generic args supplied in `[.Arg….]`\r\n```nim\r\nproc newSeq[.A.](size: int): seq[.A.] = …\r\n\r\nvar v: seq[.int.]\r\nlet x = newTable[.string, int.]\r\nlet y = newSeq[.int.](10)\r\nlet z = newList[.10.](1) # static\r\n```\r\n##### 1.2. Generic args supplied in `[.Arg…]`\r\n```nim\r\nproc newSeq[.A](size: int): seq[.A] = …\r\n\r\nlet x = newTable[.string, int]\r\nlet y = newSeq[.int](10)\r\nlet z = newList[.10](1) # static\r\n```\r\n##### 2. Generic args supplied in `(.Arg….)`\r\n```nim\r\nproc newSeq(.A.)(size: int): seq(.A.) = …\r\n\r\nvar v: seq(.int.)\r\nlet x = newTable(.string, int.)\r\nlet y = newSeq(.int.)(10)\r\nlet z = newList(.10.)(1) # static\r\n```\r\n##### 3.1. Generic args supplied in `[:Arg…]`\r\n```nim\r\nproc newSeq[:A](size: int): seq[:A] = …\r\n\r\nvar v: seq[:int]\r\nlet x = newTable[:string, int]\r\nlet y = newSeq[:int](10)\r\nlet z = newList[:10](1) # static\r\n```\r\n##### 3.2. Generic args supplied in `{:Arg…}`\r\n```nim\r\nproc newSeq{:A}(size: int): seq{:A} = …\r\n\r\nvar v: seq{:int}\r\nlet x = newTable{:string, int}\r\nlet y = newSeq{:int}(10)\r\nlet z = newList{:10}(1) # static\r\n```\r\n##### 4. Generic args introduced to called ident with `::Arg`\r\n```nim\r\nproc newSeq::A(size: int): seq::A = …\r\n\r\nvar v: seq::int\r\nlet x = newTable::string::int\r\nlet y = newSeq::int(10)\r\nlet z = newList::10(1) # static\r\n```\r\n##### 5. Generic args together with normal in `()` separated from them by `;`\r\n```nim\r\nproc newSeq(A; size: int): seq(int;) = …\r\n\r\nvar v: seq(int;)\r\nlet x = newTable(string, int;)\r\nlet y = newSeq(int; 10)\r\nlet z = newList(10; 1) # static\r\n```\r\n##### 6.1. Generic args together with normal, each prefixed with `:`\r\n```nim\r\nproc newSeq(:A, size: int) seq :A = …\r\n\r\nvar v: seq :int\r\nlet x = newTable :string, :int\r\nlet y = newSeq :int, 10\r\nlet z = newList :10, 1 # static\r\n```\r\n##### 6.2 Generic args together with normal, each suffixed with `.`\r\n```nim\r\nproc newSeq(A., size: int) seq A. = …\r\n\r\nvar v: seq int.\r\nlet x = newTable string., int.\r\nlet y = newSeq int., 10\r\nlet z = newList 10., 1 # static\r\n```\r\n##### 7. Generic args inserted to call expression via `of Arg` bin-op expression\r\n```nim\r\nproc newSeq(size: int) of A: seq of A = …\r\n\r\nvar v: seq of int\r\nlet x = newTable of (string, int)\r\nlet y = newSeq(10) of int\r\nlet z = newList(1) of 10 # static\r\n```\r\n##### 8. Generic args supplied in `\\Arg…\\`\r\n```nim\r\nproc newSeq \\A\\(size: int): seq \\A\\ = …\r\n\r\nvar v: seq \\int\\\r\nlet x = newTable \\string, int\\\r\nlet y = newSeq \\int\\(10)\r\nlet z = newList \\10\\(1) # static\r\n```"},"comment":{"url":"https://api.github.com/repos/nim-lang/Nim/issues/comments/152994715","html_url":"https://github.com/nim-lang/Nim/issues/3502#issuecomment-152994715","issue_url":"https://api.github.com/repos/nim-lang/Nim/issues/3502","id":152994715,"user":{"login":"baabelfish","id":1986366,"avatar_url":"https://avatars.githubusercontent.com/u/1986366?v=3","gravatar_id":"","url":"https://api.github.com/users/baabelfish","html_url":"https://github.com/baabelfish","followers_url":"https://api.github.com/users/baabelfish/followers","following_url":"https://api.github.com/users/baabelfish/following{/other_user}","gists_url":"https://api.github.com/users/baabelfish/gists{/gist_id}","starred_url":"https://api.github.com/users/baabelfish/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/baabelfish/subscriptions","organizations_url":"https://api.github.com/users/baabelfish/orgs","repos_url":"https://api.github.com/users/baabelfish/repos","events_url":"https://api.github.com/users/baabelfish/events{/privacy}","received_events_url":"https://api.github.com/users/baabelfish/received_events","type":"User","site_admin":false},"created_at":"2015-11-02T11:35:48Z","updated_at":"2015-11-02T11:35:48Z","body":"Why not use angle brackets?"}}