copecog / org.unaen.cl.util

Collection of arbitrary personal Common Lisp Utilities
Other
0 stars 0 forks source link

Just some code suggestions #1

Open gwangjinkim opened 2 months ago

gwangjinkim commented 2 months ago

Hello! Nice work!

I was passing by an read:

(defmacro plusplus (place &optional delta-form)
  "Destructively increment place value; However, return the original value."
  (let ((place-before (gensym)))
    `(let ((,place-before ,place))
       (incf ,place ,@(when delta-form (list delta-form)))
       ,place-before)))

this would do the same:

(defmacro plusplus (place &optional (delta-form 1))
  `(- (incf ,place ,delta-form) ,delta-form))

the incf expression returns the increased value, but the outer form decreases only the return value again.

For

(defmacro alias (old-call-name new-call-name)
  "Replace symbol in functional evaluation with another symbol."
  `(defmacro ,new-call-name (&rest args)
     `(,',old-call-name ,@args)))

This is wrong, because you make out of a function a macro. That means the defined alias is something fundamentally different (a macro) than the original function. The consequence is that you can't use it as argument in higher order functions. Even worse: A macro expands at macroexpansion time and not at runtime. In addition, with your (&rest args) you lose the lambda list specification of the function. So you should better do:

(defmacro function-alias (to fn)
  "Define alias function names."
    `(setf (fdefinition ',to) #',fn))

You can even define a macro for giving aliases to macros. https://stackoverflow.com/questions/43034254/common-lisp-function-macro-aliases

(defmacro macro-alias (to macro)
  "Define alias macro names."
  `(setf (macro-function ',to) (macro-function ',macro)))
(defmacro do-hash-keys ((var table &optional result) &body body)
  "Iterate over the keys of a hash-table in similar fashion to dolist."
  `(progn
     (alexandria:maphash-keys #'(lambda (,var)
                                  ,@body)
                              ,table)
     ,result))

An alternative way without dependencies would be:

(defmacro do-hash-keys ((var hash-table &optional default) &body body)
  "Iterate over the keys of a hahs-table in similar fashion to dolist."
  `(loop for ,var being the hash-keys of ,hash-table
             do (progn ,@body)
             finally (return ,default)))

I tried to first build a (dolist ( ...) ...) form in the macro, but this didn't work out as expected. I think it is because of to what the dolist macro then actually expands to. That then the scoping behaves differently than I expect.

gwangjinkim commented 2 months ago

What I really love from your repo is the way how you organized your packages in subpackages. I think it is a good idea to have such subpackages - especially in a utils package.

copecog commented 2 months ago

I'm a little rusty as I got distracted by my day job and haven't done any CL in a while :-P I believe for only numbers that should be equivalent. I tried to make something as generic as possible that returns a copy of a place before applying an increment form to it.

On Wed, Aug 28, 2024 at 10:45 AM Gwang-Jin Kim @.***> wrote:

Hello! Nice work!

I was passing by an read:

(defmacro plusplus (place &optional delta-form) "Destructively increment place value; However, return the original value." (let ((place-before (gensym))) `(let ((,place-before ,place)) (incf ,place ,@(when delta-form (list delta-form))) ,place-before)))

this would do the same:

(defmacro plusplus (place &optional (delta-form 1)) `(- (incf ,place ,delta-form) ,delta-form))

the incf expression returns the increased value, but the outer form decreases only the return value again.

— Reply to this email directly, view it on GitHub https://github.com/copecog/org.unaen.cl.util/issues/1, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATXGUMBGWKBOJ66YOZHXHJTZTX5EFAVCNFSM6AAAAABNIVZNBCVHI2DSMVQWIX3LMV43ASLTON2WKOZSGQ4TENJWHE2DCMA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

copecog commented 2 months ago

Thanks! I learned most of what I did from #commonlisp on librachat irc (which was formally on freenode). My method to everything is to try and find some organization principle from which everything can be naturally collected.

On Wed, Aug 28, 2024 at 11:58 AM Gwang-Jin Kim @.***> wrote:

What I really love from your repo however is the way how you organized your packages in subpackages. I think it is a good idea to have such subpackages - especially in a utils package.

— Reply to this email directly, view it on GitHub https://github.com/copecog/org.unaen.cl.util/issues/1#issuecomment-2315952294, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATXGUME4DDQC23YDU66KWPTZTYFTFAVCNFSM6AAAAABNIVZNBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMJVHE2TEMRZGQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

gwangjinkim commented 2 months ago

Thanks to your code I came along function-alias and macro-alias. I will add them into my - yet to be written - utils package. They are very powerful. I only wish that i could make emacs recognize these for its syntax highlighting. Because then this would be a perfect solution in future for using Common Lisp functions and macros along with their alias names.

copecog commented 2 months ago

Yeah, you're absolutely right about function-alias, macro-alias, and do-hash-keys.