datetimelispcommon-lisppgloader

How can I call a LISP function with &optional arg and colon like `(formato '((:year 0 4) (:month 4 6) (:day 6 8)))`


I am trying to perform a DB migration with pgloader and I would like to define a custom lisp transformation file for a datetime, but I don't know LISP (!)

So I have cut&paste one of the pgloader transform functions and I tried to invoke it with no luck after spending a bunch of hours (!) in studying LISP.

I have extracted and simplified the function

(defun date-with-no-separator
    (date-string
     &optional (formato '((:year     0  4)
                          (:month    4  6)
                          (:day      6  8)
                          (:hour     8 10)
                          (:minute  10 12)
                          (:seconds 12 14))))
  "Apply this function when input date in like '20041002152952'"

  (let ((str-length      (length date-string))
        (expected-length (reduce #'max (mapcar #'third formato))))
    (print str-length)
    (print expected-length)))

I have changed format to formato in order to be sure that it is a variable and not the format LISP function. It seems to me that I have been right at least in this assumption. Am I?

I have tried:

(setq my-date "20041002152952")
(date-with-no-separator my-date)

and by running clisp test.lisp I got the output

14
14

and then I have done some failing attempts that you can see below with ANY LUCK:

(setq my-date "2004")
; (setf (get 'formato 'year) '(0 4))
(setq formato (#':year 0 4))

(date-with-no-separator my-date formato) ;(formato (:year 0 4))) ; '((12 16) (6 8) (1 3)) ))

At this time I just expect to get

4
4

when I set my-date to "2004" and my format to (:year 0 4) but also

10
10

when I set my-date to "01/01/1970" and my format to (:year 6 10) (:month 3 5) (:day 0 2)

I am a pythonist if it could be useful to make me understanding the topic with pythonic examples.


Solution

  • You're right, format is a variable here, but Common Lisp is Lisp2, so variables can have the same name as functions and you don't overwrite core function.

    Optional argument formato is a list, containing triplets (keyword number number)- so if you want to provide your own format, it has to have exactly this form.

    And you probably don't need setq here- you can write the values of arguments into a function call or use let.

    Here are some examples:

    > (date-with-no-separator "2004" '((:year 0 4)))
    
    4 
    4 
    4
    
    > (date-with-no-separator "01/01/1970" '((:year 6 10) (:month 3 5) (:day 0 2)))
    
    10 
    10 
    10
    
    > (let ((date "01/01/1970")
            (format '((:year 6 10) (:month 3 5) (:day 0 2))))
       (date-with-no-separator date format))
    
    10 
    10 
    10