-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
-defun macro to flexibly handle arguments (better than cl-defun) #268
Comments
(-let (((&plist :foo foo) (list :foo nil)))
foo) but you are using (-if-let (((&plist :foo foo) (list :foo nil)))
"yes"
"no") |
Is there any reason why you have multiple signatures ((type number &keys :salted salted)
(type &keys :salted salted)
(type number)
(type)
:defaults ((number 10) (salted t))) I assume that what happens is that it tries to match the first which structurally fits, right? In which case I see where the problem with the keys matching occurs and why it is a problem. I think we could have a "stricter" version of |
Ah, yes, I see. It seemed like the most natural
Well, yes, the point is that the function can accept arguments in any of those formats.
I don't think that structurally fits. The arg list is
Yes, that would be great! Would you be interested in implementing that? If not, do you have any pointers? I don't know the Dash internals the way you do... |
About the stricter version, that actually might be quite difficult, because the (I was thinking in |
LOL, at the very moment I finished expanding the series of macros and arrived at: (let
((salted
(when
(plist-member --dash-source-267-- :salted)
(plist-get --dash-source-267-- :salted))))
(if salted
(progn
(funcall g1383)))) ...I see your message that's way ahead of me. :) |
If we could make it expand to something like this, maybe that would work? But I don't know where to begin implementing that. (let ((--dash-source-267-- args))
(if --dash-source-267--
(let ((type (pop --dash-source-267--)))
(if type
(let ((number (pop --dash-source-267--))
(salted-set-p (plist-member --dash-source-267-- :salted)))
(if (and number
salted-set-p)
(let ((salted (plist-get --dash-source-267-- :salted)))
(progn
(funcall g1383)))))))))
|
Well, not exactly on the topic of Dash, but I found a way to implement it with (defun plist-p (list)
(when list
(cl-loop for (keyword value) on list by #'cddr
always (keywordp keyword))))
(let ((args '((peanuts :salted nil)
(peanuts 20 :salted nil)
(peanuts 20)
(peanuts))))
(cl-loop for set in args
collect (a-list :args set
:result (let ((number 10)
(salted t))
(pcase set
(`(,type . ,(and rest
(guard (plist-p rest))
(let (map salted) rest)))
(list :type type :number number :salted salted))
(`(,type ,number . ,(and rest
(guard (plist-p rest))
(let (map salted) rest)))
(list :type type :number number :salted salted))
(`(,type ,number)
(list :type type :number number :salted salted))
(`(,type)
(list :type type :number number :salted salted))
(_ (user-error "Invalid args")))))))
;; =>
;; (((:args peanuts :salted nil)
;; (:result :type peanuts :number 10 :salted nil))
;; ((:args peanuts 20 :salted nil)
;; (:result :type peanuts :number 20 :salted nil))
;; ((:args peanuts 20)
;; (:result :type peanuts :number 20 :salted t))
;; ((:args peanuts)
;; (:result :type peanuts :number 10 :salted t))) Now the issue is transforming a list like: ((type number &keys :salted salted)
(type &keys :salted salted)
(type number)
(type)
:defaults ((number 10) (salted t))) Into the expansion. :) |
Sorry, I haven't really been following this thread, but just a quick question: Are plist keywords required to satisfy |
@basil-conto Are you talking about #269? |
@alphapapa I'm asking how opinionated AFAICT from a quick glance, the PRs relevant to this question are #81, #111, #268, and #269. I haven't looked at |
@basil-conto Your question may be answered by #111 (comment) (at least, with regard to that PR). |
That comment, as well as the following quick test run of #269: (-let [(&plist :foo x) '(:foo 1 foo 2 x 3)] x) ; => 1
(-let [(&plist 'foo x) '(:foo 1 foo 2 x 3)] x) ; => 2
(-let [(&plist :foo) '(:foo 1 foo 2 x 3)] foo) ; => 1
(-let [(&plist 'foo) '(:foo 1 foo 2 x 3)] foo) ; => 2 both indicate that
What prompted my initial question, however, was your definition of This suggests that only plists with |
My definition of that function has nothing to do with Dash. :) |
OK, thanks for clarifying, and sorry about the noise. |
@Fuco1 Do you have any general advice for building lists containing backquotes and unquotes? Or alternatives to doing that in the first place? As you can see in #268 (comment), I figured out a way to make a |
@alphapapa Not really no, I struggle with those myself. They are handled in quite annoying way. I think it would still be better to maybe invent a notation where we could have just one arg declaration. Ideally |
Sorry, I don't understand what you mean.
Yes, definitely. |
@alphapapa Well right now you have
which is not aligned with |
@alphapapa @Fuco1 what is the status of this PR? Can we add |
I'm not sure if this helps but, I've written a (defmacro -defun (name match-form &rest body)
"Macro that allows desctructuring for defun."
(declare (doc-string 3)
(indent defun)
(debug (&define sexp
[&optional stringp]
[&optional ("interactive" interactive)]
def-body)))
(let* ((docstring (when (stringp (car-safe body)) (car body)))
(body (if docstring (cdr body) body)))
(cond
((not (consp match-form))
(signal 'wrong-type-argument "match-form must be a list"))
((-all? 'symbolp match-form)
`(defun ,name ,match-form ,docstring ,@body))
(t
(let* ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index)))
match-form)))
`(defun ,name ,(--map (cadr it) inputs) ,docstring
(-let* ,inputs ,@body))))))) Also, I would like a more detailed specification of how the pattern matching suggested by @alphapapa will work so that I (and others seeing this issue) could potentially start working on it. Right now I have a general idea of what it will do, but there are some use cases where I am unsure what the result will be. For example one question I have is: how will the ((one two three) (four five) (six)) This could be an example of patten matching suggested by alphapapa where Another question is should |
Wanting more flexible argument handling, I tried to implement this with
pcase
, but I couldn't get it to match the plist at the end. It was much easier with-let
, however I ran into a problem that I'm not sure how to overcome, or if it's even possible to do so.That all works great, but when I try to set
:salted
tonil
, it doesn't work, because-let
doesn't match the plist key'snil
value:If this could be fixed, this could be a really useful way to define functions that accept arguments. It would allow one to avoid manually looping over argument lists.
Any ideas would be appreciated. :)
In case anyone is interested, here's my aborted attempt using
pcase
:The text was updated successfully, but these errors were encountered: