{"action":"created","issue":{"url":"https://api.github.com/repos/magnars/dash.el/issues/329","repository_url":"https://api.github.com/repos/magnars/dash.el","labels_url":"https://api.github.com/repos/magnars/dash.el/issues/329/labels{/name}","comments_url":"https://api.github.com/repos/magnars/dash.el/issues/329/comments","events_url":"https://api.github.com/repos/magnars/dash.el/issues/329/events","html_url":"https://github.com/magnars/dash.el/issues/329","id":547801969,"node_id":"MDU6SXNzdWU1NDc4MDE5Njk=","number":329,"title":"[Feature request] defun with &rest and &key","user":{"login":"ndwarshuis","id":6629118,"node_id":"MDQ6VXNlcjY2MjkxMTg=","avatar_url":"https://avatars2.githubusercontent.com/u/6629118?v=4","gravatar_id":"","url":"https://api.github.com/users/ndwarshuis","html_url":"https://github.com/ndwarshuis","followers_url":"https://api.github.com/users/ndwarshuis/followers","following_url":"https://api.github.com/users/ndwarshuis/following{/other_user}","gists_url":"https://api.github.com/users/ndwarshuis/gists{/gist_id}","starred_url":"https://api.github.com/users/ndwarshuis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ndwarshuis/subscriptions","organizations_url":"https://api.github.com/users/ndwarshuis/orgs","repos_url":"https://api.github.com/users/ndwarshuis/repos","events_url":"https://api.github.com/users/ndwarshuis/events{/privacy}","received_events_url":"https://api.github.com/users/ndwarshuis/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2020-01-10T00:44:09Z","updated_at":"2020-01-12T16:33:13Z","closed_at":null,"author_association":"NONE","body":"I am thinking of a macro to define a function like this:\r\n\r\n```elisp\r\n(-defun-kw foo (a b &key one (two \"2\") &rest args)\r\n  (list a b :one one :two two :rest args))\r\n\r\n(foo 1 2)                      ; => (1 2 :one nil :two \"2\" :rest nil)\r\n(foo 1 2 :two \"1\")             ; => (1 2 :one nil :two \"1\" :rest nil)\r\n(foo 1 2 :two \"1\" 'r1 'r2 'r3) ; => (1 2 :one nil :two \"1\" :rest (r1 r2 r3))\r\n(foo 1 2 'r1 'r2 'r3)          ; => (1 2 :one nil :two \"2\" :rest (r1 r2 r3))\r\n```\r\n\r\nThis behavior is impossible with `cl-defun` (both the one in Emacs and the official CL version according to the CL-hyperspec). This is because using &rest with &key with `cl-defun` will simply bind the entire plist consisting of the keyval pairs to the symbol after &rest; it won't interpret \"remaining arguments\" as non-keyed arguments.\r\n\r\nThe only way I know to almost do this with core code in emacs is to bind a plist to one of the positional arguments and use &rest after.\r\n\r\nI have code for this working in one of my repositories [here](https://github.com/ndwarshuis/om.el/blob/f8d25edcf2147de49f031da47aa08cb7d47f2d98/om.el#L966). Its more complex than what I'm proposing here because it has a predicate checker like `cl-defun` (I'm not sure I'm keeping that though).\r\n\r\nThe way it works is that for each function call, anything that is not a positional argument is bound to an intermediate &rest-like symbol, and the list bound to this symbol is partitioned into a plist for the &key arguments and another normal list with whatever is leftover for &rest. The values for each key are then bound to symbols matching the keys without the colon, and the rest argument list is bound to the symbol after &rest in the signature like normal.\r\n\r\nI don't think &optional is necessary since &key arguments can function like optional arguments, and adding &optional might not be worth the extra complexity."},"comment":{"url":"https://api.github.com/repos/magnars/dash.el/issues/comments/573432687","html_url":"https://github.com/magnars/dash.el/issues/329#issuecomment-573432687","issue_url":"https://api.github.com/repos/magnars/dash.el/issues/329","id":573432687,"node_id":"MDEyOklzc3VlQ29tbWVudDU3MzQzMjY4Nw==","user":{"login":"ndwarshuis","id":6629118,"node_id":"MDQ6VXNlcjY2MjkxMTg=","avatar_url":"https://avatars2.githubusercontent.com/u/6629118?v=4","gravatar_id":"","url":"https://api.github.com/users/ndwarshuis","html_url":"https://github.com/ndwarshuis","followers_url":"https://api.github.com/users/ndwarshuis/followers","following_url":"https://api.github.com/users/ndwarshuis/following{/other_user}","gists_url":"https://api.github.com/users/ndwarshuis/gists{/gist_id}","starred_url":"https://api.github.com/users/ndwarshuis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ndwarshuis/subscriptions","organizations_url":"https://api.github.com/users/ndwarshuis/orgs","repos_url":"https://api.github.com/users/ndwarshuis/repos","events_url":"https://api.github.com/users/ndwarshuis/events{/privacy}","received_events_url":"https://api.github.com/users/ndwarshuis/received_events","type":"User","site_admin":false},"created_at":"2020-01-12T16:33:13Z","updated_at":"2020-01-12T16:33:13Z","author_association":"NONE","body":"@Fuco1 thank you :) As far as `-defun` were you thinking of how to implement this using dash functions? Sorry if I wasn't clear; I have the implementation working for this already (although it could be simplified) and the OP was meaning to ask if this would be appropriate to include in dash."}}
{"actor":{"display_login":"ndwarshuis"}}