{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/191","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/191/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/191/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/191/events","html_url":"https://github.com/dotnet/roslyn/issues/191","id":56129045,"number":191,"title":"(Proposal) Match Expression","user":{"login":"AdamSpeight2008","id":900107,"avatar_url":"https://avatars.githubusercontent.com/u/900107?v=3","gravatar_id":"","url":"https://api.github.com/users/AdamSpeight2008","html_url":"https://github.com/AdamSpeight2008","followers_url":"https://api.github.com/users/AdamSpeight2008/followers","following_url":"https://api.github.com/users/AdamSpeight2008/following{/other_user}","gists_url":"https://api.github.com/users/AdamSpeight2008/gists{/gist_id}","starred_url":"https://api.github.com/users/AdamSpeight2008/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AdamSpeight2008/subscriptions","organizations_url":"https://api.github.com/users/AdamSpeight2008/orgs","repos_url":"https://api.github.com/users/AdamSpeight2008/repos","events_url":"https://api.github.com/users/AdamSpeight2008/events{/privacy}","received_events_url":"https://api.github.com/users/AdamSpeight2008/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Discussion","name":"Discussion","color":"fbca04"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-01-31T15:52:24Z","updated_at":"2015-04-23T20:59:37Z","closed_at":"2015-04-23T20:59:37Z","body":"### Match Expression\r\n\r\nThis proposal is separated out from #180. The approach to the syntax is an alternative to the one proposed by @MadsTorgersen\r\n\r\nA match expression block is an expression as it permits uses in situations that switch can not be used. For example in-conjunction with a return\r\n```\r\nreturn match( ... ) { | _ => ... }\r\n```\r\n or an 'await' *this needs further investigation*\r\n```\r\nvar result = await match( ) { };\r\n```\r\n\r\n* `|`\r\n donates the start of a **match clause**\r\n* `into`\r\n allow you to introduce new variables into the scope (of this match clause), or reuse existing in scope variables.\r\n** ` := ` is for introducing a new variable into scope.\r\n* `when`\r\n is for specifying that this match clause is considered if the predicate is satisfied.\r\n* `=>` this doesn't indicate the the expression after is a lambda function, it just reusing an existing symbol as it's is close to what you use for lambda. Eg multiple statements / expression are required to be enclosed inside braces `{ ... }`. Not needing a `return` for simple single expressions.\r\nThe code called when the match clause is satisfied could be an expression, a statement or an exception.You can't intermingle expression and statements.\r\nEg\r\n```\r\nmatch ( x ) with\r\n{\r\n  | 0 => Console.WriteLine(\"Zero\");\r\n  | 1 => return \"One\"; // Error not a statement;\r\n  | _ => Throw New Exception(\"FUBAR\");\r\n}\r\n\r\n\r\nmatch ( x ) with\r\n{\r\n  | 1 => return \"One\";\r\n  | 0 => Console.WriteLine(\"Zero\"); // Error not an expression\r\n  | _ => Throw New Exception(\"FUBAR\");\r\n}\r\n```\r\n\r\nThe rationale for `into` before `when` is that is allows the variable just introduced to be used with the predicate of the of the guard expression (when).\r\n\r\n`...` is being use in the following examples as a place-holder for some code.\r\n\r\n\r\n\r\n**Default Clause**\r\n\r\nEvery **match** is required to have default clause, which is used if non of the other clause are satisfied. Examples will use `| _ =>` to represent this. If all of args in the \"target\" are wildcards this is also consider a default clause. A default clause most also have no guards, so it can catch all possibilities..\r\n\r\n**Examples**\r\n```nemerle\r\nmatch ( e , a ) with\r\n{  \r\n  | ( null, null ) => ... ;\r\n  | ( _ , _ ) into \r\n       {l:= a.Left as IdentifierName;\r\n        r:= a.Right as IdentifierName;\r\n       } => match (l,r) with\r\n            {\r\n              | (null,null) =>  ... ;\r\n              | ( _ , _ ) when (a.Name.name == r.Name.name) => ... ;\r\n              | _ => ... ;\r\n            };\r\n  | _ => ... ;\r\n}\r\n```\r\n\r\n```nemerle\r\ntry\r\n{\r\n  var res = match( l, op , r ) with\r\n            { \r\n              | ( _ ,'+', _ ) => ... ;\r\n              | ( _ ,'-', _ ) => ... ; \r\n              | ( _ ,'*', _ ) => ... ;\r\n              | ( _ ,'/'. _ ) => ... ;\r\n              | ( _ , _ , _ ) => throw new NotSupported(); // Also the default clause.\r\n            }\r\ncatch (ex) when NotSuppored\r\n{\r\n  ...\r\n}\r\n```\r\n\r\n```nemerle\r\nmatch type ( o ) with\r\n{\r\n  | ( String ) into s when (s != null) => ;\r\n  | ( Short  ) into s when (s >= 0 ) => ; // not an error \r\n  // ...\r\n}\r\n```\r\n\r\n**Grammar**\r\n\r\n```\r\nmatch_expr     ::= \"match\" match_category? '(' match_source ')' \"with\"\r\nmatch_source   ::= source (',' source)*\r\nmatch_body     ::= '{' clause* default_clause '}'\r\nmatch_category ::= match_type\r\nmatch_type     ::= \"type\"\r\nclause         ::= '|' target into? when? result\r\ndefault_clause ::= '|' '_' \"=>\" expr ';'\r\ntarget         ::= target_part | '(' target_part ')' | '(' target_part (',' target_part)+ ')'\r\ntarget_part    ::= \r\ntarget_wild    ::= '_'\r\ninto           ::= \"into\" '{' into_vars '}' \r\ninto_vars      ::= into_var ( into_var )*\r\ninto_var       ::= in_scope | in_var \r\nin_scope       ::= identifier ';' \r\nin_var         ::= identitfier \":=\" expr ';'\r\nwhen           ::= \"when\" predicate\r\npredicate      ::= \r\nresult         ::= \"=>\" expr ';'\r\nexpr           ::=\r\n```\r\n\r\nHow the your code looks when using the form being proposed is clean looking and fit in well is existing C# style. It's not too far from existing style to be jarring, when creating the examples it felt *(to me)* very natural.\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/95717215","html_url":"https://github.com/dotnet/roslyn/issues/191#issuecomment-95717215","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/191","id":95717215,"user":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"created_at":"2015-04-23T20:59:36Z","updated_at":"2015-04-23T20:59:36Z","body":"This proposal doesn't stand on its own; it is discussion of an alternative syntax for a proposal already under consideration. Please move discussion to https://github.com/dotnet/roslyn/issues/1572 or https://github.com/dotnet/roslyn/issues/206 ."}}