Como você já notou, o fato de a mutabilidade ser desencorajada no Clojure não significa que ela é proibida e que não há construções que a suportem. Portanto, você está certo que o uso def
pode alterar / alterar uma ligação no ambiente de maneira semelhante à atribuição feita em outros idiomas (consulte a documentação do Clojure em vars ). Ao alterar as ligações no ambiente global, você também altera os objetos de dados que usam essas ligações. Por exemplo:
user=> (def x 1)
#'user/x
user=> (defn f [y] (+ x y))
#'user/f
user=> (f 1)
2
user=> (def x 100)
#'user/x
user=> (f 1)
101
Observe que, após redefinir a ligação para x
, a função f
também mudou, porque seu corpo usa essa ligação.
Compare isso com os idiomas nos quais a redefinição de uma variável não exclui a ligação antiga, mas apenas a obscurece , ou seja, torna-a invisível no escopo que vem após a nova definição. Veja o que acontece se você escrever o mesmo código no SML REPL:
- val x = 1;
val x = 1 : int
- fun f y = x + y;
val f = fn : int -> int
- f 1;
val it = 2 : int
- val x = 100;
val x = 100 : int
- f 1;
val it = 2 : int
Observe que após a segunda definição de x
, a função f
ainda usa a ligação x = 1
que estava no escopo quando foi definida, ou seja, a ligação val x = 100
não substitui a ligação anterior val x = 1
.
Bottomline: Clojure permite alterar o ambiente global e redefinir as ligações nele. Seria possível evitar isso, como outros idiomas, como o SML, mas a def
construção no Clojure tem o objetivo de acessar e alterar um ambiente global. Na prática, isso é muito semelhante ao que a atribuição pode fazer em linguagens imperativas como Java, C ++, Python.
Ainda assim, o Clojure fornece muitas construções e bibliotecas que evitam a mutação, e você pode percorrer um longo caminho sem usá-lo. Evitar a mutação é de longe o estilo de programação preferido no Clojure.
Clojure é cerca de gerir o estado mutável, controlando os pontos de mutação (isto é,
Ref
s,Atom
s,Agent
s, eVar
s). Embora, é claro, qualquer código Java usado por meio de interoperabilidade possa fazer o que bem entender.Se você quer dizer vincular a
Var
(em oposição a, por exemplo, uma variável local) a um valor diferente, então sim. De fato, como observado em Vars e no ambiente global ,Var
s são especificamente incluídos como um dos quatro "tipos de referência" de Clojure (embora eu diria que eles se referem principalmente a s dinâmicosVar
).Com o Lisps, há uma longa história de execução de atividades de programação interativa e exploratória via REPL. Isso geralmente envolve definir novas variáveis e funções, além de redefinir as antigas. No entanto, fora do REPL,
def
a aVar
é considerada má forma.fonte
De Clojure para os bravos e verdadeiros
fonte