Skip to content

Instantly share code, notes, and snippets.

@goose121
Created May 25, 2020 06:16
Show Gist options
  • Save goose121/14a7713f731de0898c759e81cca92426 to your computer and use it in GitHub Desktop.
Save goose121/14a7713f731de0898c759e81cca92426 to your computer and use it in GitHub Desktop.
A setf expander for member-if
(defun member-if* (test list &key (key #'identity))
"Does the same thing as MEMBER-IF."
(loop :for sublist :on list
:if (funcall test (funcall key (car sublist)))
:return sublist))
(define-setf-expander member-if* (test list &key (key #'identity) &environment env)
(with-gensyms (store-var found-cons test-sym list-sym key-sym sublist prev-sublist)
(multiple-value-bind (list-vars list-vals list-stores list-set list-get)
(get-setf-expansion list env)
(values
`(,test-sym
,@list-vars
,list-sym
,(car list-stores)
,key-sym
,found-cons)
`(,test
,@list-vals
,list-get
,nil
,key
(loop :for ,prev-sublist := :head :then ,sublist
:for ,sublist :on ,list-sym
:if (funcall ,test-sym (funcall ,key-sym (car ,sublist)))
:return ,prev-sublist))
`(,store-var)
`(case ,found-cons
(:head
(setf ,(car list-stores) ,store-var)
,list-set)
((nil)
())
(otherwise
(setf (cdr ,found-cons) ,store-var)))
`(case ,found-cons
(:head ,list-get)
((nil) ())
(otherwise (cdr ,found-cons)))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment