{"action":"created","issue":{"url":"https://api.github.com/repos/masak/007/issues/164","repository_url":"https://api.github.com/repos/masak/007","labels_url":"https://api.github.com/repos/masak/007/issues/164/labels{/name}","comments_url":"https://api.github.com/repos/masak/007/issues/164/comments","events_url":"https://api.github.com/repos/masak/007/issues/164/events","html_url":"https://github.com/masak/007/issues/164","id":169126910,"number":164,"title":"Implement 'multi' things as a macro","user":{"login":"masak","id":20627,"avatar_url":"https://avatars.githubusercontent.com/u/20627?v=3","gravatar_id":"","url":"https://api.github.com/users/masak","html_url":"https://github.com/masak","followers_url":"https://api.github.com/users/masak/followers","following_url":"https://api.github.com/users/masak/following{/other_user}","gists_url":"https://api.github.com/users/masak/gists{/gist_id}","starred_url":"https://api.github.com/users/masak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masak/subscriptions","organizations_url":"https://api.github.com/users/masak/orgs","repos_url":"https://api.github.com/users/masak/repos","events_url":"https://api.github.com/users/masak/events{/privacy}","received_events_url":"https://api.github.com/users/masak/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/masak/007/labels/macro-idea","name":"macro-idea","color":"bb0000"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2016-08-03T13:07:03Z","updated_at":"2016-08-23T08:32:29Z","closed_at":null,"body":"With the `case` statements of #34, we could implement `multi` subs/methods/macros in a cool way: by processing all `multi` declarations after parsing (using watcher/walker macros, presumably), and building a synthetic routine to stand in for all the multi variants.\r\n\r\nTo make this concrete, here's a Perl 6 implementation of rock-paper-scissors:\r\n\r\n    enum Hand <Rock Paper Scissors>;\r\n\r\n    multi infix:<beats>(Paper, Rock) { True }\r\n    multi infix:<beats>(Rock, Scissors) { True }\r\n    multi infix:<beats>(Scissors, Paper) { True }\r\n    multi infix:<beats>($, $) { False }\r\n\r\n    my $p1 = Hand.roll;\r\n    say \"Player 1 chooses {$p1}\";\r\n\r\n    my $p2 = Hand.roll;\r\n    say \"Player 2 chooses {$p2}\";\r\n\r\n    say do {\r\n        when $p1 beats $p2 { \"Player 1 wins!\" }\r\n        when $p2 beats $p1 { \"Player 2 wins!\" }\r\n        default { \"It's a tie!\" }\r\n    };\r\n\r\nHere would be the corresponding 007 implementation:\r\n\r\n    enum Hand { Rock | Paper | Scissors }\r\n\r\n    multi sub infix:<beats>(L: Paper, R: Rock) { return True }\r\n    multi sub infix:<beats>(L: Rock, R: Scissors) { return True }\r\n    multi sub infix:<beats>(L: Scissors, R: Paper) { return True }\r\n    multi sub infix:<beats>(L, R) { return False }\r\n\r\n    my p1 = Hand.roll();  # assumes EnumType.roll()\r\n    say(\"Player 1 chooses \" ~ p1);\r\n\r\n    my p2 = Hand.roll();\r\n    say(\"Player 2 chooses \" ~ p2);\r\n\r\n    if p1 beats p2 {\r\n        say(\"Player 1 wins!\");\r\n    }\r\n    else if p2 beats p1 {\r\n        say(\"Player 2 wins!\");\r\n    }\r\n    else {\r\n        say(\"It's a tie!\");\r\n    }\r\n\r\nAnd here would be what the macro transformation makes of it afterward:\r\n\r\n    enum Hand { Rock | Paper | Scissors }\r\n\r\n    sub ⟦sym0⟧(L: Paper, R: Rock) { return True }\r\n    sub ⟦sym1⟧(L: Rock, R: Scissors) { return True }\r\n    sub ⟦sym2⟧(L: Scissors, R: Paper) { return True }\r\n    sub ⟦sym3⟧(L, R) { return False }\r\n\r\n    sub infix:<beats>(L: Hand, R: Hand) {\r\n        return case (L, R) {\r\n            | (Paper, Rock): ⟦sym0⟧(L, R)\r\n            | (Rock, Scissors): ⟦sym1⟧(L, R)\r\n            | (Scissors, Paper): ⟦sym2⟧(L, R)\r\n            | otherwise: ⟦sym3⟧(L, R)\r\n        }\r\n    }\r\n\r\n    my p1 = Hand.roll();  # assumes EnumType.roll()\r\n    say(\"Player 1 chooses \" ~ p1);\r\n\r\n    my p2 = Hand.roll();\r\n    say(\"Player 2 chooses \" ~ p2);\r\n\r\n    if p1 beats p2 {\r\n        say(\"Player 1 wins!\");\r\n    }\r\n    else if p2 beats p1 {\r\n        say(\"Player 2 wins!\");\r\n    }\r\n    else {\r\n        say(\"It's a tie!\");\r\n    }\r\n\r\nIn other words, the macro would turn the multis into a `case` statement.\r\n\r\nA couple of quick notes:\r\n\r\n* Consider symbols conjectural. We don't have them yet and I don't know if we will get them. The mechanism (make up an un-nameable name) is the important part.\r\n* There's an implicit process of \"unification\" which is used to reduce all the multi signatures into a single signature of the dispatcher. It contains lot of interesting logic, and it's similar in spirit to the type matching of `case`. Crucially, it will need to keep track of (combinations of) parameters that aren't covered by a multi.\r\n* Ordering is important. Also, the unification algorithm will need to yell in the case of statically-detectable ties.\r\n\r\nOverall, I feel this one is a very high goal to achieve for 007, but having it would be so cool. It would put the usefulness of macros in 007 beyond any shred of a doubt. Also, this particular one brings together the [\"generate, analyze, and typecheck code\"](http://scalamacros.org/) slogan into a single use case."},"comment":{"url":"https://api.github.com/repos/masak/007/issues/comments/241663374","html_url":"https://github.com/masak/007/issues/164#issuecomment-241663374","issue_url":"https://api.github.com/repos/masak/007/issues/164","id":241663374,"user":{"login":"masak","id":20627,"avatar_url":"https://avatars.githubusercontent.com/u/20627?v=3","gravatar_id":"","url":"https://api.github.com/users/masak","html_url":"https://github.com/masak","followers_url":"https://api.github.com/users/masak/followers","following_url":"https://api.github.com/users/masak/following{/other_user}","gists_url":"https://api.github.com/users/masak/gists{/gist_id}","starred_url":"https://api.github.com/users/masak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masak/subscriptions","organizations_url":"https://api.github.com/users/masak/orgs","repos_url":"https://api.github.com/users/masak/repos","events_url":"https://api.github.com/users/masak/events{/privacy}","received_events_url":"https://api.github.com/users/masak/received_events","type":"User","site_admin":false},"created_at":"2016-08-23T08:32:29Z","updated_at":"2016-08-23T08:32:29Z","body":"Another option would be to inline the multi variants directly into the dispatch routine. That would probably look better on the call stack as well.\r\n\r\nJust have to make sure to insert explicit returns. And possibly do alpha renaming."}}
{"actor":{"display_login":"masak"}}