Creazione di una libreria di funzioni per mutare le variabili globali arbitrarie

StackOverflow https://stackoverflow.com/questions/20353946

  •  25-08-2022
  •  | 
  •  

Domanda

AGGIORNAMENTO: se ho alcune funzioni che voglio mutere una variabile globale che viene passata come argomento funzione, alcune possono farlo passando solo il simbolo del globale (come nel caso di spingere qualcosa in una parte di un elenco) , ma altre funzioni richiederanno che il simbolo venga citato quando viene superato in modo da poter accedere al valore del simbolo e mutere la variabile esterna, richiesta per l'utilizzo di SetQ in una funzione. Questa domanda riguarda fondamentalmente la creazione di un'interfaccia coerente per un utente di queste funzioni senza confondarle che a volte si passa il simbolo, altri tempi si superano il simbolo citato

Esempio di modo per semplificare l'interfaccia per un mucchio di funzioni, usando un aiutante che ha lo stesso utilizzo reqardless su come funziona la funzione di mutazione:

Ecco 2 esempi di base della mia tecnica:

(defun push-something (global something)
  (push something global)
  global) ;; not necessary to return it here since the 
          ;; preceding line already does, but doing so 
          ;; for consistency with other functions and clarity

(defun push-cdr (global something)
  (push something (cdr global))
  global) ;; must return it if I am going to set the 
          ;; dynamic var to the result of this function, 
          ;; because the preceding line doesn't return the 
          ;; entire new result of the variable

;;; "dirty" function for mutating global variable using "clean" functions above:

(defun set-global (fn global &rest values)
  (setf (symbol-value global) (apply fn (copy-list (eval global)) values)))

In quest'ultimo, devo eval il global Dal momento che è citato per l'uso con symbol-value e poi io copy-list affinché global non è direttamente mutato per caso da qualunque cosa fn Scelgo (come sarebbe il caso di push-cdr che potrebbe essere non banale in funzioni più complicate).

Produzione:

CL-USER> (defparameter *g2* nil)
*G2*
CL-USER> (set-global #'push-something '*g2* 5)
(5)
CL-USER> *g2*
(5)
CL-USER> (set-global #'push-cdr '*g2* 99)
(5 99)
CL-USER> *g2*
(5 99)

... e le stesse funzioni potrebbero essere utilizzate con *g1* o *g3* ecc. Attraverso la funzione di accesso set-global.

È questo stile buono o cattivo o mi manca un modo molto migliore per ottenere questa funzionalità?

È stato utile?

Soluzione 2

Perché non ti sbarazzi di set-global funzione interamente e se vuoi che tutta la tua funzione abbia lo stesso stile di passaggio nella variabile globale, basta farli usare tutti symbol-value Quindi chiunque utilizzi queste funzioni non dovrà sapere quale fare e quali non richiedono un preventivo di fronte al nome della variabile globale che viene superato. Molto più facile, giusto?

Altri suggerimenti

Questo è un brutto stile e una perdita di tempo.

  1. push-something è equivalente a cons.

  2. push-cdr è non Funzionale: modifica l'argomento sul posto o fallisce con un errore nil discussione.

Se si desidera modificare il valore della variabile globale, utilizzando setf esplicitamente è molto più chiaro.

Se si desidera modificare gli interni di un valore globale in un modo intricato, potrebbe essere necessario scrivere una funzione speciale per quello - ma quella funzione dovrebbe essere agnostica del fatto che sta modificando il valore associato a una variabile globale rispetto a una variabile lessicale.

In breve, ci sono due problemi ortogonali separati: modificare una variabile globale (uso setq) e cambiare interno di un oggetto (essere agnostico della sua natura globale).

Ps. Non sono sicuro di cosa intendi per "setf non modifica il valore di una variabile globale quando è all'interno della funzione", ma:

(defvar *foo* 10)
*FOO* ==> 10
(defun change-foo (x) (setq *foo* x))
(change-foo 123)
*foo* ==> 123
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top