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.
CodePudding user response:
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
CodePudding user response:
(setq formato (#':year 0 4))
Above makes no sense.
#':year
is nothing useful:
#'foo
denotes a functionfoo
:year
denotes a keyword symbol.
( .... )
denotes a form to be evaluated, for example a function call.
(#':year 0 4)
thus tries to call the function object :year
, which does not exist and if it would exist, then it can't be called like this.
Remember: when you want to pass lists as data you have to quote them:
(:year 0 4)
this is a list of three items: a keyword symbol and two integer numbers.
If you want to pass that as data you have to quote it:
(list '(:year 0 4))
-> ((:year 0 4))
If you want to have a list of lists you have either compute it or quote a list of lists:
computed:
(list '(:year 0 4))
-> ((:year 0 4))
or
(list (list :year 0 4))
-> ((:year 0 4))
quote it:
'((:year 0 4))
-> ((:year 0 4))
summary
this (setq formato (#':year 0 4))
should be:
(setq formato '((:year 0 4)))