Pregunta

¿Qué significa el término transparencia referencial ? He escuchado que se describe como " significa que puedes reemplazar iguales por iguales " pero esto parece una explicación inadecuada.

¿Fue útil?

Solución

El término " transparencia referencial " proviene de filosofía analítica , la rama de la filosofía que analiza las construcciones, declaraciones y argumentos en lenguaje natural basados ??en el Métodos de lógica y matemáticas. En otras palabras, es el tema más cercano fuera de la informática a lo que llamamos semántica del lenguaje de programación . El filósofo Willard Quine fue responsable de iniciar el concepto de transparencia referencial, pero también estaba implícito en el Enfoques de Bertrand Russell y Alfred Whitehead.

En su núcleo, " transparencia referencial " Es una idea muy simple y clara. El término " referente " se usa en filosofía analítica para hablar sobre lo que una expresión hace referencia a . Es más o menos lo mismo que queremos decir con " significado " o " denotación " En la semántica del lenguaje de programación. Usando el ejemplo de Andrew Birkett ( publicación de blog ), el término " la capital de Escocia " se refiere a la ciudad de edimburgo. Este es un ejemplo sencillo de un " referente " ;.

Un contexto en una oración es " referencialmente transparente " si la sustitución de un término en ese contexto por otro término que hace referencia a la misma entidad no altera el significado. Por ejemplo

  

El Parlamento escocés se reúne en la capital de Escocia.

significa lo mismo que

  

El Parlamento escocés se reúne en Edimburgo.

Así que el contexto " El Parlamento escocés se reúne en ... " Es un contexto referencialmente transparente. Podemos reemplazar " la capital de Escocia " con " Edimburgo " Sin alterar el significado. Para decirlo de otra manera, al contexto solo le importa a qué se refiere el término y nada más. Ese es el sentido en el que el contexto es " referencialmente transparente. & Quot;

Por otro lado, en la oración,

  

Edimburgo ha sido la capital de Escocia desde 1999.

no podemos hacer tal reemplazo. Si lo hiciéramos, obtendríamos "Edimburgo ha sido Edimburgo desde 1999", lo cual es una locura, y no transmite el mismo significado que la oración original. Por lo tanto, parece que el contexto "Edimburgo ha sido ... desde 1999" es referencialmente opaco (lo opuesto a referencialmente transparente). Al parecer, se preocupa por algo más de lo que se refiere el término. ¿Qué es?

Cosas como " la capital de Escocia " se denominan términos definidos y durante mucho tiempo no causaron mucho dolor de cabeza a los lógicos y filósofos. Russell y Quine los clasificaron diciendo que no son realmente referenciales, es decir, es un error pensar que los ejemplos anteriores se usan para referirse a entidades. La forma correcta de entender "Edimburgo ha sido la capital de Escocia desde 1999" es decir

  

Escocia ha tenido una capital desde 1999 y esa capital es Edimburgo.

Esta oración no se puede transformar en una loca. ¡Problema resuelto! El objetivo de Quine era decir que el lenguaje natural es complicado, o al menos complicado, porque está diseñado para ser práctico para el uso práctico, pero los filósofos y los lógicos deben aportar claridad entendiéndolos de la manera correcta. La transparencia referencial es una herramienta que se utiliza para brindar esa claridad de significado .

¿Qué tiene todo esto que ver con la programación? No mucho, en realidad. Como dijimos, la transparencia referencial es una herramienta que se utiliza para comprender el lenguaje, es decir, para asignar significado . Christopher Strachey , quien fundó el campo de la semántica del lenguaje de programación, lo utilizó en su estudio del significado. Su artículo de base " Conceptos fundamentales en lenguajes de programación " Está disponible en la web. Es un hermoso papel y todos pueden leerlo y entenderlo. Así que, por favor, hazlo. Estarás muy iluminado. Él introduce el término "transparencia referencial" en este párrafo:

  

Una de las propiedades más útiles de las expresiones es la llamada por Quine referencial.   transparencia. En esencia, esto significa que si deseamos & # 64257; encontrar el valor de una expresión que   contiene una subexpresión, lo único que necesitamos saber sobre la subexpresión es su   valor. Cualquier otra característica de la sub-expresión, como su estructura interna, el número   y la naturaleza de sus componentes, el orden en que se evalúan o el color de la tinta.   en el que están escritos, son irrelevantes para el valor de la expresión principal.

El uso de " en esencia " sugiere que Strachey lo está parafraseando para explicarlo en términos simples. Los programadores funcionales parecen entender este párrafo a su manera. Hay otras 9 apariciones de " transparencia referencial " en el periódico, pero no parecen preocuparse por ninguno de los otros. De hecho, todo el documento de Strachey está dedicado a explicar el significado de lenguajes de programación imperativos . Pero, en la actualidad, los programadores funcionales afirman que los lenguajes de programación imperativos no son no referencialmente transparentes. Strachey estaría girando en su tumba.

Podemos salvar la situación. Dijimos que el lenguaje natural es "complicado" o, al menos, complicado " Porque está hecho para ser conveniente para el uso práctico. Los lenguajes de programación son de la misma manera. Son " sucios, o al menos complicados " Porque están hechos para ser convenientes para el uso práctico. Eso no significa que deban confundirnos. Solo tienen que ser entendidos de la manera correcta, utilizando un lenguaje meta que sea referencialmente transparente para que tengamos claridad de significado. En el documento que cité, Strachey hace exactamente eso. Explica el significado de los lenguajes de programación imperativos desglosándolos en conceptos elementales, sin perder nunca claridad en ninguna parte. Una parte importante de su análisis es señalar que las expresiones en los lenguajes de programación tienen dos tipos de "valores", denominados valores-l y valores-r . Antes del artículo de Strachey, esto no se entendía y la confusión reinaba de manera suprema. Hoy en día, la definición de C lo menciona rutinariamente y cada programador de C entiende la distinción. (Es difícil decir si los programadores en otros idiomas lo entienden bien).

Tanto Quine como Strachey estaban preocupados por el significado de las construcciones de lenguaje que implican alguna forma de dependencia del contexto. Por ejemplo, nuestro ejemplo "Edimburgo ha sido la capital de Escocia desde 1999" significa el hecho de que " capital de Escocia " Depende del momento en que se esté considerando. Dicha dependencia del contexto es una realidad, tanto en los lenguajes naturales como en los lenguajes de programación. Incluso en la programación funcional, las variables libres y limitadas deben interpretarse con respecto al contexto en el que aparecen. La dependencia del contexto de cualquier tipo bloquea la transparencia referencial de una forma u otra. Si intenta comprender el significado de los términos sin tener en cuenta los contextos de los que dependen, nuevamente terminará con confusión. A Quine le preocupaba el significado de la lógica modal. Sostuvo que lógica modal era referencialmente opaca y debería limpiarse traduciéndola a un marco referencialmente transparente (por ejemplo, considerando la necesidad como probabilidad). En gran parte perdió este debate. Tanto los lógicos como los filósofos consideraron que la posible semántica mundial de Kripke era perfectamente adecuada. Situación similar también reina con la programación imperativa. La dependencia del estado explicada por Strachey y la dependencia de la tienda explicada por Reynolds (de una manera similar a la posible semántica mundial de Kripke) son perfectamente adecuadas. Los programadores funcionales no saben mucho de esta investigación. Sus ideas sobre la transparencia referencial deben tomarse con un gran grano de sal.

[Nota adicional: los ejemplos anteriores ilustran que una frase simple como " capital of Scotland " Tiene múltiples niveles de significado. En un nivel, podríamos estar hablando de la capital en el momento actual. En otro nivel, podríamos hablar de todas las capitales posibles que Escocia podría haber tenido a lo largo del tiempo. Podemos " zoom en " un contexto particular y " alejar " abarcar todos los contextos con bastante facilidad en la práctica normal. La eficiencia del lenguaje natural hace uso de nuestra capacidad para hacerlo. Los lenguajes de programación imperativos son muy eficientes de la misma manera. Podemos usar una variable x en el lado derecho de una asignación (el r-value ) para hablar sobre su valor en un estado particular. O bien, podríamos hablar de su l-value que abarca todos los estados. Las personas rara vez son confundidas por tales cosas. Sin embargo, pueden o no ser capaces de explicar con precisión todas las capas de significado inherentes a las construcciones del lenguaje. Todas estas capas de significado no son necesariamente "obvias" y es un asunto de la ciencia estudiarlas correctamente. Sin embargo, la falta de articulación de la gente común para explicar tales significados en capas no implica que estén confundidos acerca de ellos.]

Un " postscript " a continuación se relaciona esta discusión con las preocupaciones de la programación funcional e imperativa .

Otros consejos

Transparencia referencial, un término comúnmente usado en la programación funcional, significa que dada una función y un valor de entrada, siempre recibirá la misma salida. Es decir, no se utiliza ningún estado externo en la función.

Aquí hay un ejemplo de una función transparente referencial:

int plusOne(int x)
{
  return x+1;
}

Con una función transparente referencial, dada una entrada y una función, podría reemplazarla con un valor en lugar de llamar a la función. Así que en lugar de llamar a plusOne con un parámetro de 5, podríamos reemplazarlo con 6.

Otro buen ejemplo son las matemáticas en general. En matemáticas, dada una función y un valor de entrada, siempre se asignará al mismo valor de salida. f (x) = x + 1. Por lo tanto, las funciones en matemáticas son referencialmente transparentes.

Este concepto es importante para los investigadores porque significa que cuando tiene una función transparente referencial, se presta para una fácil paralelización automática y almacenamiento en caché.

La transparencia referencial se usa siempre en lenguajes funcionales como Haskell.

-

En contraste, existe el concepto de opacidad referencial. Esto significa lo contrario. Llamar a la función no siempre produce la misma salida.

//global G
int G = 10;

int plusG(int x)
{//G can be modified externally returning different values.
  return x + G;
}

Otro ejemplo, es una función miembro en un lenguaje de programación orientado a objetos. Las funciones miembro normalmente operan en sus variables miembro y, por lo tanto, serían opacas referenciales. Sin embargo, las funciones de los miembros pueden ser referencialmente transparentes.

Otro ejemplo más es una función que lee un archivo de texto e imprime la salida. Este archivo de texto externo podría cambiar en cualquier momento, por lo que la función sería referencialmente opaca.

Una función transparente referencial es aquella que solo depende de su entrada.

[Esta es una posdata a mi respuesta del 25 de marzo, en un esfuerzo por acercar la discusión a las preocupaciones de la programación funcional / imperativa.]

La idea de la transparencia referencial de los programadores funcionales parece diferir de la noción estándar en tres formas:

  • Mientras que los filósofos / lógicos usan términos como "referencia", "denotación", "designatum" y " bedeutung " (El término alemán de Frege), los programadores funcionales usan el término "valor". (Esto no es del todo lo que hacen. Noté que Landin, Strachey y sus descendientes también usaron el término "valor" para hablar de referencia / denotación. Puede ser solo una simplificación terminológica que Landin y Strachey introdujeron, pero parece que una gran diferencia cuando se usa de manera ingenua.)

  • Los programadores funcionales parecen creer que estos " valores " Existen dentro del lenguaje de programación, no fuera. Al hacer esto, difieren tanto de los filósofos como de los semánticos del lenguaje de programación.

  • Parece que creen que estos " valores " se supone que deben obtenerse mediante evaluación.

Por ejemplo, el artículo de Wikipedia en transparencia referencial dice, esta mañana:

  

Se dice que una expresión es referencialmente transparente si se puede reemplazar con su valor sin cambiar el comportamiento de un programa (en otras palabras, se obtiene un programa que tiene los mismos efectos y resultados en la misma entrada).

Esto está completamente en desacuerdo con lo que dicen los filósofos / lógicos. Dicen que un contexto es referencial o referencialmente transparente si una expresión en ese contexto puede ser reemplazada por otra expresión que se refiera a la misma cosa (una expresión coreferential ). ¿Quiénes son estos filósofos / lógicos? Incluyen Frege , Russell , Whitehead , Carnap , Quine , Iglesia y muchos otros. Cada uno de ellos es una figura imponente. El poder intelectual combinado de estos lógicos es conmovedor para decir lo menos. Todos ellos son unánimes en la posición de que los referentes / denotaciones existen fuera del lenguaje formal y las expresiones dentro del lenguaje solo pueden hablar sobre sobre ellos. Entonces, todo lo que uno puede hacer dentro del lenguaje es reemplazar una expresión por otra expresión que se refiera a la misma entidad. Los referentes / denotaciones en sí mismos no existen dentro del idioma. ¿Por qué los programadores funcionales se desvían de esta tradición bien establecida?

Se podría suponer que los semánticos del lenguaje de programación podrían haberlos engañado. Pero, no lo hicieron.

Landin :

  

(a) cada expresión tiene una   estructura de subexpresión de anidación, (b) cada subexpresión    denota algo (generalmente un número, valor de verdad o   función numérica) , (c) lo que una expresión denota,   es decir, su "valor" depende únicamente de los valores de su sub   Expresiones, no en otras propiedades de ellas. [Énfasis añadido]

Stoy :

  

Lo único que importa de una expresión es su valor, y cualquier subexpresión puede ser   reemplazado por cualquier otro valor igual [énfasis añadido]. Además, el valor de una expresión es, dentro de ciertos límites, el mismo cada vez que aparece " ;.

Bird and Wadler :

  

el valor de una expresión depende solo de los valores de su constituyente   Las expresiones (si las hay) y estas subexpresiones pueden ser reemplazadas libremente por otros   que posee el mismo valor [énfasis añadido].

Así que, en retrospectiva, los esfuerzos de Landin y Strachey para simplificar la terminología reemplazando la referencia / denotación " con " valor " podría haber sido imprudente. Tan pronto como uno oye un "valor", se siente la tentación de pensar en un proceso de evaluación que lo lleve a él. Es igualmente tentador pensar en lo que la evaluación produce como el "valor", aunque podría ser bastante claro que esa no es la denotación. Eso es lo que considero que sucedió con el concepto de " transparencia referencial " A los ojos de los programadores funcionales. Pero el " valor " de lo que se hablaba desde los primeros semantistas no es no el resultado de una evaluación o el resultado de una función o algo así. Es la denotación del término.

Una vez que entendamos el llamado " valor " de una expresión ("referencia" o "denotación" en el discurso de los filósofos clásicos) como un objeto matemático / conceptual complejo, se abren todo tipo de posibilidades.

  • Strachey interpretó las variables en lenguajes de programación imperativos como L-valores , como se menciona en mi respuesta del 25 de marzo, que es un objeto conceptual sofisticado que no tiene una representación directa dentro de la sintaxis de un lenguaje de programación .
  • También interpretó los comandos en lenguajes tales como funciones de estado a estado, otra instancia de un objeto matemático complejo que no es un "valor". dentro de la sintaxis.
  • Incluso una llamada de función de efecto secundario en C tiene un valor " bien definido " como un transformador de estado que mapea estados a pares de estados y valores (la llamada "mónada" en la terminología de los programadores funcionales).

La renuencia de los programadores funcionales a llamar a dichos lenguajes " referencialmente transparente " simplemente implica que son reacios a admitir objetos matemáticos / conceptuales complejos como "valores". Por otro lado, parecen perfectamente dispuestos a llamar a un transformador de estado un "valor" cuando se coloca en su propia sintaxis favorita y se viste con una palabra de moda como "mónada". Debo decir que están siendo totalmente inconsistentes, incluso si les concedemos que su idea de "transparencia referencial" Tiene cierta coherencia.

Un poco de historia podría arrojar algo de luz sobre cómo surgieron estas confusiones. El período entre 1962 y 1967 fue muy intenso para Christopher Strachey. Entre 1962-65, tomó un trabajo de medio tiempo como asistente de investigación con Maurice Wilkes para diseñar e implementar el lenguaje de programación que llegó a ser conocido como CPL. Este era un lenguaje de programación imperativo, pero estaba destinado a tener también potentes capacidades de lenguaje de programación funcional. Landin, que era empleado de Strachey en su compañía de consultoría, tuvo una gran influencia en la visión de Strachey de los lenguajes de programación. En el histórico documento de 1965 " Próximos 700 lenguajes de programación " ;, Landin promueve descaradamente los lenguajes de programación funcionales (llamándolos lenguajes denotativos ) y describe los lenguajes de programación imperativos como su "antítesis". En la discusión que sigue, encontramos a Strachey suscitando dudas sobre la fuerte posición de Landin.

  

... formulario DLs   Un subconjunto de todos los idiomas. Son un subconjunto interesante, pero uno   lo cual es un inconveniente de usar a menos que estés acostumbrado. Necesitamos   ellos porque en este momento no sabemos cómo construir   Pruebas con lenguajes que incluyen imperativos y saltos. [Énfasis añadido]

En 1965, Strachey tomó la posición de lector en Oxford y parece haber trabajado esencialmente a tiempo completo en el desarrollo de una teoría de imperativos y saltos. Para 1967, estaba preparado con una teoría que enseñó en su curso sobre " Conceptos fundamentales en lenguajes de programación " En una escuela de verano de Copenhague. Se suponía que las notas de la conferencia se habían publicado, pero, desafortunadamente, debido a la dilatoria Edición, los procedimientos nunca se materializaron; me gusta gran parte del trabajo de Strachey en Oxford, sin embargo, el El papel tenía una circulación privada influyente. " ( Martin Campbell-Kelly )

La dificultad de obtener los escritos de Strachey podría haber llevado a la propagación de las confusiones, con personas que confían en fuentes secundarias y rumores. Pero, ahora que " Conceptos fundamentales " está disponible en la web, no hay necesidad de recurrir al trabajo de adivinación. Debemos leerlo y decidirnos a qué se refería Strachey. En particular:

  • En la sección 3.2, se ocupa de las expresiones " " donde habla de " transparencia referencial de valor-R " ;.
  • Su sección 3.3 trata con " comandos " donde habla de " transparencia referencial de valor L " ;.
  • En la sección 3.4.5, habla acerca de " funciones y rutinas " y declara que cualquier desviación de la transparencia referencial de valor R en un contexto de valor R debería o bien eliminarse al descomponer la expresión en varios comandos y más simple expresiones, o, si esto resulta difícil, el tema de un comentario. "

Cualquier conversación sobre " transparencia referencial " Sin entender la distinción entre valores L, valores R y otros objetos complejos que pueblan el imperativo del universo conceptual del programador, es fundamentalmente erróneo.

Una expresión es referencialmente transparente si puede reemplazarse con su valor, sin cambiar el algoritmo, lo que produce un algoritmo que tiene los mismos efectos y resultados en la misma entrada.

Una función referencialmente transparente es aquella que actúa como una función matemática; dadas las mismas entradas, siempre producirá las mismas salidas. Implica que el estado pasado no se modifica y que la función no tiene un estado propio.

Si está interesado en la etimología (es decir, por qué este concepto tiene este nombre en particular), eche un vistazo a mi publicación de blog sobre el tema. La terminología proviene del filósofo / lógico Quine.

Para aquellos que necesiten una explicación concisa, me arriesgaré a una (pero lea la información a continuación).

La transparencia referencial en un lenguaje de programación promueve el razonamiento ecuacional: cuanta más transparencia referencial tenga, más fácil será hacer el razonamiento ecuacional. P.ej. con una definición de función (pseudo),

f x = x + x,

la facilidad con la que puede (de manera segura) reemplazar f (foo) con foo + foo en el alcance de esta definición, sin tener demasiadas restricciones sobre dónde puede realizar esta reducción, es una buena indicación de cuánta transparencia referencial Tu lenguaje de programación tiene.

Por ejemplo, si foo fuera x ++ en el sentido de programación en C, no podría realizar esta reducción de forma segura (es decir, si tuviera que realizar esta reducción no terminaría con el mismo programa con el que comenzó) .

En los lenguajes de programación prácticos, no verá una transparencia de referencia perfecta, pero a los programadores funcionales les importa más que a la mayoría (cf Haskell, donde es un objetivo central).

(Revelación completa: soy un programador funcional, por lo que, por la primera respuesta, debería tomar esta explicación con un grano de sal).

  1. La semántica denotacional se basa en lenguajes de modelado mediante la creación de dominios que constituyen valores denotables .
  2. Los programadores funcionales utilizan el término valor para describir la convergencia de un cálculo basado en las reglas de reescritura del lenguaje, es decir. su semántica operacional.

En 1 hay una claridad de dos idiomas en cuestión:

  • el que se está modelando, el lenguaje del objeto
  • el lenguaje de modelado, el lenguaje meta

En 2, gracias a la cercanía del objeto y los metalenguajes, se pueden confundir.

Como implementador de lenguaje, encuentro que necesito recordar constantemente esta distinción.

Para que el Prof. Reddy pueda parafrasearlo así :-)

  

En los contextos de programación funcional y semántica, el término Referencial   La transparencia no es referencialmente transparente.

The following answer I hope adds to and qualifies the controversial 1st and 3rd answers.

Let us grant that an expression denotes or refers to some referent. However, a question is whether these referents can be encoded isomorphically as part of expressions themselves, calling such expressions 'values'. For example, literal number values are a subset of the set of arithmetic expressions, truth values are a subset of the set of boolean expressions, etc. The idea is to evaluate an expression to its value (if it has one). So the word 'value' may refer to a denotation or to a distinguished element of the set of expressions. But if there is an isomorphism (a bijection) between the referent and the value we can say they are the same thing. (This said, one must be careful to define the referents and the isomorphism, as proven by the field of denotational semantics. To put an example mentioned by replies to the 3rd answer, the algebraic data type definition data Nat = Zero | Suc Nat does not correspond as expected to the set of natural numbers.)

Let us write E[·] for an expression with a hole, also known in some quarters as a 'context'. Two context examples for C-like expressions are [·]+1 and [·]++.

Let us write [[·]] for the function that takes an expression (with no hole) and delivers its meaning (referent, denotation, etc.) in some meaning-providing universe. (I'm borrowing notation from the field of denotational semantics.)

Let us adapt Quine's definition somewhat formally as follows: a context E[·] is referentially transparent iff given any two expressions E1 and E2 (no holes there) such that [[E1]] = [[E2]] (i.e. the expressions denote/refer-to the same referent) then it is the case that [[E[E1]]] = [[E[E2]]] (i.e. filling-in the hole with either E1 or E2 results in expressions that also denote the same referent).

Leibniz's rule of substituting equals for equals is typically expressed as 'if E1 = E2 then E[E1] = E[E2]', which says that E[·] is a function. A function (or for that matter a program computing the function) is a mapping from a source to a target so that there is at most one target element for each source element. Non-deterministic functions are misnomers, they are either relations, functions delivering sets, etc. If in Leibniz's rule the equality = is denotational then the double-brackets are simply taken for granted and elided. So a referentially transparent context is a function. And Leibniz's rule is the main ingredient of equational reasoning, so equational reasoning is definitely related to referential transparency.

Although [[·]] is a function from expressions to denotations, it could be a function from expressions to 'values' understood as a restricted subset of expressions, and [[·]] can be understood as evaluation.

Now, if E1 is an expression and E2 is a value we have what I think is meant by most people when defining referential transparency in terms of expressions, values, and evaluation. But as illustrated by the 1st and 3rd answers in this page, this is an inacurate definition.

The problem with contexts such as [·]++ is not the side effect, but that its value is not defined in C isomorphically to its meaning. Functions are not values (well, pointers to functions are) whereas in functional programming languages they are. Landin, Strachey, and the pioneers of denotational semantics were quite clever in using functional worlds to provide meaning.

For imperative C-like languages we can (roughly) provide semantics to expressions using the function [[·]] : Expression -> (State -> State x Value).

Value is a subset of Expression. State contains pairs (identifier,value). The semantic function takes an expression and delivers as its meaning a function from the current state to the pair with the updated state and a value. For example, [[x]] is the function from the current state to the pair whose first component is the current state and whose second component is the value of x. In contrast, [[x++]] is the function from the current state to the pair whose first component is a state in which the value of x is incremented, and whose second component is that very value. In this sense, the context [·]++ is referentially transparent iff it satisfies the definition given above.

I think functional programmers are entitled to use referential transparency in the sense that they naturally recover [[·]] as a function from expressions to values. Functions are first-class values and the state can also be a value, not a denotation. The state monad is (in part) a clean mechanism for passing (or threading) the state.

Note that this concept of "meaning" is something that happens in the mind of the observer. Thus, the same "reference" can mean different things to different people. So, for example, we have an Edinburgh disambiguation page in Wikipedia.

A related issue which can show up in the context of programming might be polymorphism.

And perhaps we should have a name for the special case of polymorphism (or perhaps even casting) where for our purposes the differing polymorphic cases are semantically equivalent (as opposed to just being similar. For example, the number 1 -- which might be represented using an integer type, or a complex type or any of a variety of other types -- can be treated polymorphically).

I found the definition of referential transparency in the book "Structure and Implementation of Computer Programs" (the Wizard Book) useful because it is complemented by an explanation of how referential transparency is violated by introducing the assignment operation. Check out the following slide deck I made about the subject: https://www.slideshare.net/pjschwarz/introducing-assignment-invalidates-the-substitution-model-of-evaluation-and-violates-referential-transparency-as-explained-in-sicp-the-wizard-book

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top