correct way to provide initial slot value using a variable #312
-
i'm defining some custom classes and methods, and it's unclear to me what the correct way is to provide an initial value to the here's what i currently have: (defclass tp-choices (transient-option)
((format :initform " %k %d %v")
(choices :initarg :choices :initform
'(lambda () tp-choices-var)))
"An option class with a variable in the choices slot.") the lambda is quoted, and so then in the transient methods for this class, it has to be funcalled to return the variable's value, like so: (let* ((choices-slot (oref obj choices))
(choices (if (eq (car choices-slot) 'lambda)
(funcall choices-slot)
choices-slot)))
... if i don't provide a lambda at all but just the variable, it doesn't work, as it tries to operate on the variable name instead of its value. and if i don't quote the lambda, a closure object is returned, which i am unable to do much of anything with to obtain its value. but then if i also want to set the slot to a different variable when defining an infix in a transient prefix, i can't quote the lambda, as nothing is evaluated in this context. ie this doesn't work: (transient-define-prefix tp-transient ()
"A transient for setting some settings."
:value (lambda () (tp-get-value))
["Group"
("o" "option" "option=" :class tp-choices
:choices '(lambda () tp-choices-var-different))]
...
) here i also can't provide a variable without a lambda, as its not evaluated to its value. not quoting the lambda here mostly works, but again it means that the value is a lambda and not a list of valid values. but i also feel like it has led to more problems than if i had provided a literal list. is it correct to quote the lambda in the class definition, and then not quote the lambda in the prefix definition? or is there a more reliable way to make both approaches play nicely with the same methods? |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 2 replies
-
sorry if this has been discussed already, it's hard to search for. |
Beta Was this translation helpful? Give feedback.
-
Let's start here; why do you want to use a variable instead of a hard-coded value? Is the list of choices not constant? Can the list of choices change at runtime? |
Beta Was this translation helpful? Give feedback.
-
I have a variety of choice options for different infixes. Some use a variable because the options must match a list used elsewhere in the package (e.g. a list of legit values for a given API parameter). Any data of that nature gets put in a variable so if it ever changes it's not inconsistent anywhere. Some use a variable because its a huge unwieldly list (e.g. a list of ISO language codes). Some use a function to fetch currently valid options from the server. The latter works, so i was trying to do In general I would think as soon as I have the same thing hard-coded in two different places it should be a variable.
(if (functionp choices) (funcall choices) choices)) is it not ok to also handle symbols there and treat them as variables? (let ((slot (oref obj choices)))
(cond ((functionp slot)
(funcall slot))
((symbolp slot)
(eval slot))
(t slot)))) is there a reason a literal list or a function are the only two possibilities? |
Beta Was this translation helpful? Give feedback.
-
Think of the closure object not as something scary, but as the evaluated |
Beta Was this translation helpful? Give feedback.
-
Thanks for the further details. I know quoting a lambda is nuts, but i was stumped. i realize now how i ended up with this issue (and so have solved it): when implementing my own methods, i wasn't (always) replicating the funcall of the choices slot, so i thought a closure there would not work. OOP newb mistake! answer to question in title: use a lambda. ie (lambda () your-variable) |
Beta Was this translation helpful? Give feedback.
lambda
expressions should virtually never be quoted. If you don't quote them, then it just works in both of these places.Think of the closure object not as something scary, but as the evaluated
lambda
. If you quote alambda
, it won't be evaluated but remain data. If the latter appears(funcall HERE)
, for example, then that will still work, because there is a special case somewhere that wo…