Frank GOENNINGER
12/28/2015 12:41:00 PM
"Pascal J. Bourguignon" <pjb@informatimago.com> writes:
> Frank DG1SBG <dg1sbg@googlemail.com> writes:
>
>> Objective:
>>
>> (define-config-var frgo 42)
>>
>> shall expand into the followimg code:
>>
>> (eval-when (:compile-toplevel :load-toplevel)
>> (defc +frgo+ 42)
>> (defv *frgo* #.+frgo+)
>> (export +frgo+)
>> (export *frgo*))
>
> You cannot evaluate the value of +frgo+ when you are reading the form
> that WILL in the future, perhaps in 10000 years, and perhaps in a galaxy
> far far away, eventually define +frgo+.
>
>
Yes, clear.
>> I have:
>>
>> (defun mkstr (&rest args)
>> "Convert all args into a concatenated string."
>> (with-output-to-string (s)
>> (dolist (a args) (princ a s))))
>
> This is bad, because the output of PRINC depends on variables such as
> *PRINT-CASE*.
Ouch - didn't think of that. Thanks.
> cl-user> (princ 'hello)
> hello
> hello
> cl-user> (princ (symbol-name 'hello))
> HELLO
> "HELLO"
> cl-user> *print-case*
> :downcase
> cl-user>
>
> At the very least, you should use WITH-STANDARD-IO-SYNTAX here, but I
> would advise to just use symbol-name for symbols.
Noted.
>> (defmacro define-config-var (name val)
>> (alexandria:with-gensyms (g-default-var-name
>> g-var-name
>> g-default-var
>> g-var
>> g-var-name-str)
>> `(let* ((,g-var-name-str (mkstr ',name))
>> (,g-default-var-name (concatenate 'string "+" ,g-var-name-str "+"))
>> (,g-var-name (concatenate 'string "*" ,g-var-name-str "*")))
>> (defconstant (symbol-value ,g-default-var-name) ,val))
>>
>> ;; ... some code deleted as even this statement doesnt work ...
>> ))
>
> The name is known at compilation time, therefore the generated names can
> be known at compilation time too, therefore you don't need with-gensym,a
> nd you don't need to bind them at run-time.
>
> Run time is TOO LATE to compute those variable names, since defconstant
> etc, need to have the variable name AT COMPILATION TIME!
>
>
> Also, buying a clock or a watch might help you get some notion of
> time.
Santa was not kind enough to bring me the Breitling Navitimer I so much
wished for. So, sorry, but time is still a relative concept for me.
(I had a good laugh when reading your comment on the watch - and, due to the
quite loud laugh, then had to explain all this to my son. Result: Nice
discussion about Lisp macros and the specialties around them. Special
thanks for this !)
>> I. Am. Lost. - Would want to get this sorted out myself. Any small
>> hints appreciated.
>
> You need a time machine to zap all around the clock, or you need to sort
> out your times.
You know, the Navitimer ...
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (defun generate-define-config-var-code (name value)
> (let ((cname (intern (concatenate
> 'string "+" (symbol-name name) "+")
> (symbol-package name)))
> (vname (intern (concatenate
> 'string "*" (symbol-name name) "*")
> (symbol-package name))))
> `(eval-when (:compile-toplevel :load-toplevel)
> (defconstant ,cname 42)
> (defvar ,vname ,cname)
> (export '(,cname ,vname))))))
>
> (generate-define-config-var-code 'frgo 42)
> ;; --> (eval-when (:compile-toplevel :load-toplevel)
> ;; (defconstant +frgo+ 42)
> ;; (defvar *frgo* +frgo+)
> ;; (export '(+frgo+ *frgo*)))
>
>
> (defmacro define-config-var (name value)
> (generate-define-config-var-code name value))
>
> (macroexpand '(define-config-var frgo 42))
> ;; --> (eval-when (:compile-toplevel :load-toplevel)
> ;; (defconstant +frgo+ 42)
> ;; (defvar *frgo* +frgo+)
> ;; (export '(+frgo+ *frgo*)))
> ;; t
This clearly shows that I was indeed messing up with times and also
that trying to solve trivial problems after more than 8 hours may
occasionally turn into embarrasing questions that still spark
new enlightenment by always providing new insights from you folks of c.l.l.
> Also, I find it strange that you don't want to create the configuration
> variable in the REPL (or loading the configuration source file):
>
> cl-user> (define-config-var frgo 42)
> nil
> cl-user> +frgo+ ; since we don't define in the :execute situation:
>> Debug: Unbound variable: +frgo+
>> While executing: (:internal swank::invoke-default-debugger), in process
>> repl-thread(1915).
>> Type :GO to continue, :POP to abort, :R for a list of available restarts.
>> If continued: Retry getting the value of +frgo+.
>> Type :? for other options.
> 1 > :q
> ; Evaluation aborted on #<unbound-variable #x30235F343D5D>.
>
> cl-user> (with-open-file (src "/tmp/conf.lisp"
> :direction :output
> :if-does-not-exist :create
> :if-exists :supersede)
> (print '(define-config-var frgo 42) src))
> (define-config-var frgo 42)
> cl-user> (load (compile-file "/tmp/conf.lisp"))
> #P"/tmp/conf.lx64fsl"
> cl-user> +frgo+
> 42
> cl-user> *frgo*
> 42
> cl-user>
Thanks, yes, I know but there's more code around all this than I showed
here. It may still turn out that I need the execution time included in
the eval-when.
Regards
Frank