Spanish sous-titres

← Conferencia 1A MIT 6.001 Estructura e interpretacion, 1986

Overview and Introduction to Lisp

Despite the copyright notice on the screen, this course is now offered under a Creative Commons license: BY-NC-SA. Details at http://ocw.mit.edu/terms

Obtenir le code d’intégration
6 langues

Afficher la révision 41 créée 05/14/2016 par Nicolás Vallejo.

  1. Quisiera darles la bienvenida
  2. a este curso de ciencias del computador.
  3. En realidad, esta es una manera
    terrible de empezar
  4. Ciencias del computador
    es un nombre terrible para este negocio.
  5. En primer lugar,
    no es una ciencia.
  6. Podría ser ingeniería o podría ser arte,
  7. pero veremos que la así llamada
    ciencia del computador
  8. tiene mucho en común con la magia,
    y eso lo veremos
  9. en este curso.
  10. Así que no es una ciencia.
  11. Tampoco es acerca de computadoras.
  12. Y no es acerca de computadoras
    en el mismo sentido que la física
  13. no es acerca de aceleradores de partículas,
    y la biología
  14. no es acerca de microscopios y cápsulas de Petri.
  15. Y no acerca de computadores,
    de la misma manera que
  16. la geometría no es acerca
    de usar elementos de inspección.
  17. De hecho, hay mucho en común
    con las ciencias de la computación
  18. y la geometría.
  19. La geometría, en principio, es otra área
  20. con un nombre malísimo.
  21. El nombre proviene de Gaia,
    que significa la Tierra, y metron,
  22. que significa medir.
  23. Geometría originalmente
    significaba la medición
  24. de la Tierra o la inspección.
  25. Y la razón de eso es que,
    hace miles de años,
  26. los sacerdotes egipcios desarrollaron
    los rudimentos de
  27. la geometría para poder determinar
    como restaurar los
  28. límites de los campos que eran destruídos
    en la inundaciones
  29. anuales del Nilo.
  30. Y para los egipcios que hacían eso,
    la geometría era de hecho
  31. el uso de instrumentos de inspección.
  32. Ahora bien, la razón por la que pensamos
    que las ciencias del computador son acerca
  33. de computadoras es la misma razón
    por la que los egipcios
  34. pensaban que la geometría era
    acerca de instrumentos de inspección.
  35. Y es que, cuando un campo recién
    está comenzando
  36. y no es realmente comprendido muy bien,
    es muy fácil
  37. confundir la esencia de los que se hace
    con las herramientas
  38. que se utilizan.
  39. En efecto, en alguna escala absoluta,
    probablemente sabemos
  40. menos sobre la esencia
    de las ciencias del computador
  41. que los antiguos egipcios
    acerca de la geometría.
  42. Bueno, ¿ qué quiero decir con esencia
    de las ciencias del computador?
  43. ¿Qué quiero decir con la esencia
    de la geometría?
  44. Verán, es cierto que esos egipcios
    salían y usaban
  45. instrumentos de inspección, pero
    cuando cuando los miramos
  46. un par de miles de años después,
    decimos que lo que
  47. estaban haciendo, lo realmente importante
    que estaban haciendo, era
  48. empezar a formalizar las nociones del
    espacio y del tiempo, a comenzar
  49. a hablar acerca de verdades matemáticas
    formalmente.
  50. Eso llevó al método axiomático.
  51. Y eso llevó a casi todas
    las matemáticas modernas.
  52. Descubriendo una manera de hablar
    precisamente acerca del así llamando
  53. conocimiento declarativo.
    Acerca de lo que es verdadero.
  54. Similarmente, pienso que en futuro,
    la gente observará hacia atrás
  55. y dirá que sí, que esos primitivos del
    siglo XX
  56. estaban jugueteando con esos
    dispositivos llamados
  57. computadoras, pero que en realidad lo que
    estaban haciendo era comenzar
  58. a aprender a formalizar intuiciones
    acerca del proceso, acerca de cómo
  59. hacer cosas. Empezar a desarrollar
    una manera para hablar
  60. precisamente acerca del conocimiento
    del 'cómo', en contraste con
  61. con la geometría que habla sobre
    lo que es verdad.
  62. Déjenme darles un ejemplo de esto.
  63. Echemos un vistazo.
  64. Aquí está una pieza matemática
    que dice qué
  65. es una raíz cuadrada.
  66. La raíz cuadrada de X es el número Y,
    tal que Y al cuadrado
  67. es igual a X e Y es mayor a cero.
  68. Ahora bien, esa es una pieza
    matemática, pero solamente decirte
  69. qué es una raíz cuadrada no dice
    realmente nada
  70. acerca de cómo uno puede ir
    y encontrar una.
  71. Así que contrastemos eso con una pieza
    de conocimiento imperativo,
  72. cómo ir y encontrar la raíz cuadrada.
  73. Esto, de hecho, también proviene de
    Egipto,
  74. pero no el antiguo, antiguo Egipto.
  75. Este es un algoritmo de
    Herón de Alejandría, llamado
  76. cómo encontrar la raíz cuadrada
    mediante promedios sucesivos.
  77. Y lo que dice es que,
    para hallar la raíz cuadrada,
  78. uno hace una estimación y luego
    la mejora.
  79. Y la manera en la que mejora esa
    estimación es promediándola
  80. con X sobre la estimación.
    Luego hablaremos un poco acerca de
  81. por qué eso es algo razonable.
  82. Y se sigue mejorando la estimación
    hasta que sea lo suficientemente buena.
  83. Eso es un método.
  84. Eso es cómo hacer algo
    en oposición al conocimiento
  85. declarativo que dice
    qué es lo que están buscando.
  86. Eso es un proceso.
  87. Ahora bien,
    ¿Qué es un proceso en general?
  88. Es difícil de decir.
  89. Uno podría pensarlo como un espíritu
    mágico que
  90. vive en la computadora y hace algo.
  91. Y aquello que dirige a un proceso
    es una patrón de reglas
  92. llamado procedimiento.
  93. Así que los procedimientos son hechizos,
    por así decirlo, que controlan
  94. a estos espíritus mágicos
    que son los procesos.
  95. Imagino que saben que todos necesitan
    un lenguaje mágico y que
  96. los hechiceros, los verdaderos hechiceros,
    usaban antiguo Arcadio o Sumerio
  97. o Babilonio o lo que sea.
  98. Nosotros conjuraremos nuestros espíritus
    en un lenguaje mágico
  99. llamado Lisp, que es un lenguaje
    diseñado para hablar sobre
  100. y para realizar los hechizos
    que son los procedimienntos que dirigen
  101. los procesos.
  102. Ahora bien, es muy fácil aprender Lisp.
  103. De hecho, en unos pocos minutos,
    les enseñaré,
  104. esencialmente, todo Lisp.
  105. Les voy a enseñar, esencialmente,
    todas las reglas.
  106. Y no deberían encontrar eso
    particularmente sorprendente.
  107. Es como decir que es muy fácil aprender
  108. las reglas del ajedrez.
  109. Y en efecto, en unos pocos minutos,
    le pueden contar a alguien
  110. las reglas del ajedrez.
  111. Pero por supuesto, eso es muy diferente
    a que tu digas que
  112. entiendes las implicaciones de esas reglas
    y cómo usarlas
  113. para convertirte en un excelente
    jugador de ajedrez.
  114. Bueno, Lisp es así.
  115. Declararemos las reglas en unos minutos
  116. y serán muy fácil de ver.
  117. Pero lo que será realmente difícil
    son las implicaciones
  118. de esas reglas, cómo explotarlas
    para ser
  119. un maestro programador.
  120. Y las implicaciones de esas reglas
    nos llevarán
  121. bueno, el resto de la materia y,
    por supuesto,
  122. mucho más.
  123. Así que es ciencias de la computación,
    estamos en el negocio de
  124. formalizar esta forma de
    conocimiento imperativo.
  125. Cómo hacer cosas.
  126. Y los verdaderos problemas de
    las ciencias de la computación son,
  127. por supuesto, no decirle a la gente
    cómo calcular raíces cuadradas.
  128. Porque si eso fuera todo lo que hay,
  129. no sería un gran inconveniente.
  130. Los verdaderos problemas vienen cuando
    intentamos construir sistemas muy grandes,
  131. programas de computadoras que
    tienen miles de páginas de longitud.
  132. Tan largos que nadie puede realmente
    mantenerlo en su cabeza
  133. todo al mismo tiempo.
  134. Y la razón por la que eso es posible,
    es porque
  135. hay técnicas que controlan la complejidad
  136. de estos sistemas grandes.
    Y esas técnicas
  137. que controlan la complejidad son
  138. el verdadero objeto de este curso.
  139. Y de alguna manera,
    eso es acerca de lo que
  140. las ciencias de la computación son.
  141. Ahora bien, eso puede parecer
    algo muy extraño de decir.
  142. Porque, después de todo, un montón
    de gente al margen de los computadores
  143. científicos lidian con el control de
    la complejidad.
  144. Una gran aerolínea un es sistema
    extremadamente complejo y
  145. los ingenieros aeronáuticos que la
    diseñan lidian con
  146. una complejidad inmensa.
  147. Pero hay una diferencia entre esa clase
  148. de complejidad y lo que nos enfrentamos
    en las ciencias de la computación.
  149. Y eso es que es la ciencias de
    la computación
  150. en algún sentido, no son reales.
  151. Verán, cuando un ingeniero está
    diseñando un sistema físico,
  152. eso está hecho de piezas reales.
  153. Los ingenieros que se preocupan de eso
    tienen que resolver problemas
  154. de tolerancia, aproximación
    y ruido en el sistema.
  155. Por ejemplo, como un ingeniero eléctrico,
    puedo ir
  156. y construir fácilmente un amplificador
    de un nivel
  157. o un amplificador de dos niveles,
    y puedo imaginar apilar muchos de ellos
  158. para construir un amplificador
    de millones de niveles.
  159. Pero es ridículo construir algo así,
    porque mucho antes
  160. del millonésimo nivel,
    el sonido térmico en esos
  161. componentes en el principio será
  162. amplificado y dejará toda la construcción
    sin sentido.
  163. Las ciencias de la computación lidian
    con componentes idealizados.
  164. Sabemos tanto como queremos acerca
    de estos pequeños programas y
  165. piezas de datos que estamos juntando.
  166. No nos tenemos que preocupar
    acerca de la tolerancia.
  167. Y eso significa que, al construir
    un programa grande,
  168. no hay mucha diferencia
    entre lo que puedo
  169. construir y lo que puedo imaginar,
    porque las partes son estas
  170. entidades abstractas de las que
    conozco tanto como quiero.
  171. Conozco sobre ellas con tanta
    precisión como quiera.
  172. Así que en contraste con otras
    formas de ingeniería, donde
  173. las restricciones sobre lo que puedo
    construir son aquellas de los
  174. sistemas físicos, las restricciones
    de la física y
  175. del ruido y de la aproximación,
    las restricciones impuestas
  176. sobre los grandes sistemas de software
    son las limitaciones
  177. de nuestras propias mentes.
  178. Así que de alguna manera,
    las ciencias de la computación son
  179. una forma abstracta de ingeniería.
  180. Es la clase de ingeniería donde
    se ignoran las
  181. restricciones que se imponen
    sobre la realidad
  182. Bueno, ¿cuáles son algunas
    de estas técnicas?
  183. No son únicas de las
    ciencias de la computación
  184. La primera técnica, que se usa
    en toda forma de ingeniería, es
  185. una especie de abstracción llamada
    abstracción de caja negra.
  186. Agarrar algo y
    construir una caja alrededor.
  187. Por ejemplo, si miramos el método para
    obtener raíces cuadradas,
  188. podría querer agarrarlo
    y construir una caja
  189. que dijera cómo encontrar la raíz
    cuadrada de X. Y eso
  190. podría ser complejo conjunto de reglas.
  191. Y eso podría terminar siendo una cosa
    donde puedo poner,
  192. digamos, 36 y preguntar cuál es la
    raíz cuadrada de 36.
  193. Y saldrá un 6.
  194. Y lo importante es que me gustaría
    diseñarlo para que si
  195. George viniese y quisiese computar,
  196. digamos, la raíz cuadrada de A
    más la raíz cuadrada de B, él podría
  197. agarrar esta cosa y usarla
    como un módulo sin tener
  198. que mirar adentro y construir algo
    que se parezca a esto:
  199. Una A, una B y una
    caja de raíz cuadrada y otra
  200. caja de raíz cuadrada y luego
    algo que sume
  201. que devuelva la respuesta.
  202. Y pueden ver, que solo
    por el hecho de que quiero hacer eso,
  203. desde el punto de vista de George,
    lo que hay adentro de esto
  204. no debería ser importante.
  205. Así que, por ejemplo, no debería
    importar que, cuando escribo esto,
  206. digo que quiero hallar
    la raíz cuadrada de X. Podría
  207. haber dicho la raíz cuadrada de Y,
    o la raíz cuadrada de A, o
  208. ninguna cosa.
  209. Esa es la noción fundamental
    de poner algo en una caja,
  210. usar abstracción de caja negra
    para suprimir detalle.
  211. Y la razón de eso es que uno
    querría ir construir
  212. cajas más grandes.
  213. Hay otra razón para hacer
    abstracción de caja negra
  214. más allá de queres suprimir
    detalles para
  215. construir cajas más grandes.
  216. A veces, uno quiere decir que
    la manera de hacer algo,
  217. el método, es una instancia
    de algo más general,
  218. y uno quisiera que el lenguaje
    sea capaz de expresar
  219. esa generalidad.
  220. Déjenme darles otro ejemplo,
  221. siguiendo con raíces cuadradas.
  222. Miremos de vuelta la diapositiva
  223. del algoritmo de la raíz cuadrada.
  224. Recuerden lo que dice.
  225. Dice que, para hacer algo,
    hago una estimación y
  226. mejoro esa estimación y sigo
  227. mejorándola.
  228. Así que es la estrategia general.
    Busco algo
  229. y la forma en la que lo encuentro es
  230. seguir mejorándolo.
  231. Ahora bien, eso es un caso particular
    de otra clase de estrategia
  232. para hallar un punto fijo de algo.
  233. Así que tienes un punto fijo
    de una función
  234. Un punto fijo de una función es algo,
    un valor.
  235. Un punto fijo de una función F
    es un valor Y, tal que F(Y)
  236. es igual a Y. Y la forma en que podría
    hacerlo es empezando con una estimación.
  237. Y luego si quiero que algo no cambie
    cuando
  238. le sigo aplicando F, sigo aplicando F
    una y otra vez hasta
  239. que el resultado no cambie
    demasiado.
  240. Así que hay una estrategia general.
  241. Y luego, por ejemplo, para computar
    la raíz cuadrada de X
  242. puedo intentar y hallar un punto fijo
    de la función que
  243. lleva a Y al promedio de X/Y.
    Y la idea es que si
  244. realmente tuviera en Y la raíz
    cuadrada de X, entonces Y y
  245. X/Y serían el mismo valor.
  246. Ambos serían la raíz cuadrada de X,
    porque X sobre
  247. la raíz cuadrada de X
    es la raíz cuadrada de X.
  248. Así que si Y fuera
    la raíz cuadrada de X,
  249. entonces el promedio no cambiaría.
  250. Así que la raíz cuadrada de X es
    un punto fijo
  251. de una función en particular.
  252. Ahora bien, lo que me gustaría tener,
    lo que me gustaría expresar es
  253. una estrategia general para hallar
    puntos fijos.
  254. Así que lo podría imaginar hacer,
    es ser capaz de
  255. usar mi lenguaje para definir una caja
    que dijera "punto fijo",
  256. de la misma manera que podría hacer una
    caja que dijera "raíz cuadrada".
  257. Y me gustaría poder expresar
    esto en mi lenguaje.
  258. Así que me gustaría expresar
    no sólo el conocimento imperativo
  259. de una cosa en particular
    como la raíz cuadrada, sino que
  260. me gustaría poder expresar el
    conocimiento imperativo de
  261. cómo hacer algo general como hallar un
    punto fijo.
  262. Y de hecho, miremos la diapositiva
    de vuelta.
  263. No sólo es una pieza de conocimento
    imperativo, cómo
  264. hallar un punto fijo,
    pare aquí debajo hay
  265. otra pieza de conocimento imperativo que
  266. dice que una forma de computar
    la raíz cuadrada es aplicar este
  267. método general de punto fijo.
  268. Así que quiero ser capaz
    de expresar
  269. ese conocimiento imperativo.
  270. ¿Cómo se vería eso?
  271. Diría, esta caja de punto fijo
    es tal que si
  272. le introduzco la función que
    lleva a Y de al promedio de Y
  273. y X/Y, entonces lo que saldrá
    de esa caja de punto fijo será
  274. un método para hallar raíces cuadradas.
  275. Así que en estas cajas que estamos
    construyendo, no sólo estamos
  276. construyendo cajas que reciben números
    y devuelven números,
  277. sino también construiremos cajas que,
    en efecto, computan
  278. métodos como hallar la raíz cuadrada.
  279. Y lo hago introduciendo funciones,
    como Y va
  280. al promedio de Y y X/Y. Y la razón por
    la queremos hacer eso,
  281. la razón por la que es un procedimiento,
    que terminará siendo un procedimiento,
  282. cuyo valor es, como veremos, otro
    procedimiento, la razón por la que
  283. queremos hacer eso es porque
    los procedimientos van a ser nuestros
  284. medios para hablar acerca de
    conocimiento imperativo.
  285. Y la forma de hacer eso muy
    poderoso es poder hablar
  286. acerca de otros tipos de conocimiento.
  287. Así que aquí hay un procedimiento que,
    en efecto, habla sobre otro
  288. procedimiento. Una estrategia general que
    por sí misma habla sobre
  289. estrategias generales.
  290. El primer tema de este curso
    -- habrá tres grandes temas--
  291. será abstracción de caja negra.
  292. Miremos eso con un poco más de detalle.
  293. Lo que haremos es empezar a hablar sobre
  294. como Lisp está construido con
    objetos primitivos.
  295. ¿Qué nos provee el lenguaje?
  296. Y veremos que hay
    procedimientos primitivos
  297. y datos primitivos.
  298. Luego veremos cómo tomar esas primitivas
  299. y combinarlas para hacer cosas más
    complicadas.
  300. Medio de combinación.
  301. Y lo que veremos es que hay formas
    de poner
  302. cosas juntas, poner primitivas juntas
  303. para hacer procedimientos más
    complicados.
  304. Y veremos cómo combinar datos primitivos
  305. para hacer datos compuestos.
  306. Luego diremos, bueno, habiendo hecho
    estas cosas compuestas,
  307. ¿cómo las abstraemos?
  308. ¿Cómo ponemos esas cajas negras
    alrededor para
  309. usarlas como componentes en cosas más
    complejas?
  310. Y veremos que eso se hace
    definiendo procedimientos y
  311. una técnica para lidiar con datos
    compuestos llamada
  312. abstracción de datos.
  313. Y luego, lo que quizá es lo
    más importante, es ir
  314. desde sólo las reglas a como
    trabaja un experto.
  315. ¿Cómo expresar patrones comunes para
    hacer cosas, como
  316. digamos, bueno, hay un método
    general del punto fijo
  317. y la raíz cuadrada es un caso particular
    de eso?
  318. Y usaremos,
  319. ya les di la pista, algo llamado
    procedimientos
  320. de alto orden. Procedimientos
    cuyas entradas y salidas
  321. son procedimientos.
  322. Y luego veremos algo muy interesante.
  323. Veremos, mientras avanzamos más
    y más y nos volvamos
  324. más abstractos, que
  325. la línea entre lo que consideramos datos
    y lo que
  326. consideramos procedimientos se hará difusa
  327. a un ritmo increíble.
  328. Bueno, ese el primer tema:
    Abstracciones
  329. de caja negra.
  330. Miremos el segundo tema
  331. Puedo introducirlo así>
  332. Supongan que quiero expresar la idea --
  333. recuerden, estamos hablando de ideas --
  334. Supongan que quiero expresa la idea de
    puedo tomar algo
  335. y multiplicarlo por la suma de dos otras cosas.
  336. Por ejemplo, so tuviera 1 y 3
    y multiplico
  337. eso por 2, obtendría 8.
  338. Pero estoy hablando de la idea general
    de lo que se conoce como
  339. combinación lineal, que puedas
    sumar dos cosas
  340. y multiplicarlas por otra.
  341. Es muy fácil cuando lo pienso para
    números, pero
  342. supongan que quiero usar la misma idea
  343. para sumar dos vectores a1 y a2,
    y luego escalarlos por
  344. algún factor X y obtener otro vector.
  345. O podría decir,
    quisiera pensar a a1 y a2
  346. como polinomios y quisiera sumar
    esos dos polinomios
  347. y luego multiplicarlos por 2
    para obtener otro más complicado.
  348. O a1 y a2 pueden ser señales eléctricas
    y podría
  349. pensar acerca de sumar esas dos señales
  350. eléctricas y luego poner resultado
    a travéz
  351. de un amplificador, multiplicándolo
    pr un facto de 2 o algo.
  352. La idea es que quiero pensar sobre
  353. la noción general de eso.
  354. Ahora, si nuestro lenguaje va ser
    un buen lenguaje
  355. para expresar ese tipo de ideas
    generales, si yo pudiera
  356. realmente hacer eso, me gustaría
    ser capaz de decir que voy a
  357. multiplicar por X la suma de a1 y a2,
    y me gustaría que eso
  358. expresra la idea general de
    todas las cosas diferentes que
  359. a1 y a2 puedan ser.
  360. Si piensan sobre eso,
    hay un problema porque
  361. después de todo, las verdaderas
    operaciones primitivas que van
  362. a la máquina serán obviamente diferentes
  363. si estuviera sumando dos números
    o si estuviera sumando
  364. dos polinomios, o si estuviera
    sumando la representación de dos
  365. señales eléctricas o formas de ondas.
  366. En algún lugar, tiene que haber
    un conocimiento de la clase de
  367. distintas cosas que uno puede sumar
  368. y la forma de sumarlas.
  369. Para construir un sistema así,
    la pregunta es, ¿dónde
  370. pongo ese conocimiento?
  371. ¿Cómo hago para pensar acerca de
    las diferentes clases
  372. de opciones que tengo?
  373. Y si mañana George viene con una
    nueva clase de objeto
  374. que puede ser sumado y multiplicado,
    ¿Cómo agrego
  375. el nuevo objeto de George
    al sistema sin arruinar
  376. todo lo que ya estaba allí?
  377. Bueno, ese será el segundo gran tema.
  378. La forma de controlar esa clase de complejidad.
  379. Y la forma de hacerlo es
    establecimiento interfaces
  380. convencionales, poniendo de acuerdo
    en formas de combinar cosas.
  381. De la misma manera que la ingeniería
    eléctrica, la gente
  382. tiene impedancias estándar para conectores,
    y luego sabes
  383. que si construyes algo con uno de esas
    impedancias
  384. estándard, entonces puedes conectarlo
    con otra cosa.
  385. Así que ese será nuestro
    segundo gran tema,
  386. interfaces convencionales.
  387. Lo que veremos es que,
    primero, hablaremos
  388. sobre el problema de operaciones
    genéricas, que es aquél
  389. al que aludí, cosas como "suma"
    que tiene que trabajar con
  390. diferentes tipos de datos.
  391. Así que hablamos de operaciones
    genéricas.
  392. Luego vamos a hablar sobre
    estructuras de larga escala.
  393. ¿Cómo combinar programs muy grandes
    que modelan
  394. la clase de sistemas complejos del mundo real
  395. que queremos modelar?
  396. Y vermos que hay dos
  397. metáforas muy importantes para combinar
    dichos sistemas.
  398. Una se llama programación orientada
    a objetos, donde uno
  399. piensa al sistema como una sociedad
    llena de pequeñas coasa
  400. que interactúan enviándose
  401. información entre ellos.
  402. Y la segunda es operaciones
    en agregados,
  403. llamados flujos, donde uno piensa
    a un sistema grande combinado
  404. de la misma forma que un ingeniero
    de procesamiento de señales
  405. construye un sistema eléctrico.
  406. Ese será nuestro segundo tema.
  407. La tercer forma veremos,
    la tercer ténica
  408. básica para controlar complejidad
  409. es crear nuevos lenguajes.
  410. Porque a veces, cuando uno está
    sobrepasado
  411. por la complejidad del diseño,
    la manera en que controlas
  412. esa complejidad es elegir
    un nuevo lenguaje de diseño.
  413. Y el propósito de este nuevo lenguaje
    de diseño será
  414. resaltar diferentes
    aspectos del sistema.
  415. Suprimirá algunos detalles y
    enfatizará
  416. otros tipos de detalles.
  417. Esa va a ser la parte
    más mágica del curso.
  418. Vamos a empezar por mirar
  419. a la tecnología para construir
    nuevos lenguajes de computadora.
  420. Lo primero que haremos es
    construir en Lisp.
  421. Vamos a expresar en Lisp
    el proceso de interpretar
  422. el propio Lisp.
  423. Y eso va a ser algo
    medio meta circular.
  424. Hay un pequeño símbolo místico
  425. que tiene que ver con eso.
  426. El proceso de interpretar Lis
    es como una rueda gigante
  427. de dos procesos, apply y eval,
    que constantente
  428. reducen expresiones entre sí.
  429. Luego veremos todo tipo
    de otras cosas mágicas.
  430. Este es otro símbolo mágico.
  431. Este es como el operador Y,
    que es, de alguna manera,
  432. la expresión de infinito
  433. dentro de nuestro lenguaje procedural.
  434. Le echaremos un vistazo a eso.
  435. En cualquier caso, esta sección
    del curso se llama
  436. Abstracción Metalinguística,
    abstrayendo hablando acerca de
  437. cómo construir nuevos lenguajes.
  438. Como dije, vamos a empezar mirando al
  439. proceso de interpretación.
  440. Miraremos este ciclo de apply-eval
  441. y contruiremos Lisp.
  442. Luego, solo para mostrarles que
    es estoy es muy general,
  443. vamos a usar la misma tecnología
    para construir un muy
  444. diferente tipo de lenguaje, un lenguaje
    conocido como lenguaje de
  445. programación lógica, donde no se
    habla de procedimientos
  446. que tienen entradas y salidas.
  447. Lo que se hace es hablar de relaciones
    entre cosas.
  448. Y luego, finalmente, vamos a hablar
    sobre cómo
  449. implementar estas cosas de manera
    muy concreta en
  450. los tipos de máquinas más simples.
  451. Veremos algo así.
  452. Esta es una imagen de un chip,
    que es el intérprete de Lisp
  453. del que hablaremos en hardware.
  454. Bueno, hay un bosquejo del curso,
    tres grande tópicos.
  455. Abstracción de caja negra,
    interfaces convencionales,
  456. abstracción metalinguística.
  457. Ahora, tomémonos un descanso
    y luego empezaremos.
  458. Empecemos aprendiendo Lisp ahora.
  459. De hecho, empezaremos aprendiendo
    algo mucho más
  460. importante, quizá la cosa más importante
  461. de este curso, que no es Lisp, en particular,
    por supuesto, sino
  462. un framework general para pensar
    sobre lenguajes al que
  463. ya aludí.
  464. Cuando alguien te dice que te va
    mostrar un
  465. lenguaje, lo que deberían decir es,
    lo que me gustaría que dijeras es
  466. cuáles son los elemento primitivos.
  467. ¿Con qué viene el lenguaje?
  468. Luego, ¿cuáles son las formas
    de combinar esas cosas?
  469. ¿Cuáles son los medios de combinación?
  470. ¿Cuáles son las cosas que te
    permiten tomar esos elementos
  471. primitivos y construir
    cosas más grandes con ellos?
  472. ¿Cuáles con las formas de
    combinar cosas?
  473. Y luego,
    ¿cuáles son los medios de abstracción?
  474. ¿Cómo tomamos esas cosas
    complicadas y dibujamos
  475. cajas alrededor de ellas?
  476. ¿Cómo las nombramos
    para que las podamos usar
  477. como elementos primitivos para hacer
  478. cosas aún más complejas?
  479. Y así y así y así.
  480. Así que cuando alguien te dice,
    "tengo un gran lenguaje
  481. de computadora nuevo", no le preguntes
    cuántos caracteres necesita
  482. para invertir una matriz.
  483. Es irrelevante.
  484. Lo que dices es,
    si el lenguaje no viene con matrices
  485. o con otra cosa, ¿cómo
  486. puedo hacer para contruirla?
  487. ¿Cuáles son los medio de combinación
    que me permiten
  488. hacer eso?
  489. Y luego, ¿cuáles son los medios
    de abstracción que me permiten
  490. usar esos elementos para hacer
  491. cosas más complicadas?
  492. Bueno, veremos que Lisp
    tiene algunos datos primitivos
  493. y algunos procedimientos primitivos.
  494. De hecho, empecemos realmente.
  495. Aquí hay una pieza de dato primitivo
  496. en Lisp, el número 3.
  497. En realidad, si estuviera muy pedante,
  498. ese no es el número 3.
  499. Ese es un símbolo que representa
    el concepto de Platón
  500. del número 3.
  501. Y aquí hay otro.
  502. Aquí hay más datos primitivos
    en Lisp, 17.4.
  503. O, en realidad, alguna representación
    del 17.4.
  504. Y aquí hay otra, 5.
  505. Aquí hay otro objetivo primitivo
    que está construido
  506. en Lisp, la suma.
  507. En verdad, para ser igual de pedante,
    este es un nombre
  508. para el método primitivo
    para sumar cosas.
  509. De la misma manera que esto es un
    nombre para el número 3 de Platón, esto es
  510. un nombre para el concepto platónico
    de cómo sumar cosas.
  511. Así que esos son elementos primitivos.
  512. Los puedo poner juntos.
  513. Puedo decir, ¿cuál es la suma de
    3 y 17.4 y 5?
  514. Y la forma de hacerlo es decir,
    apliquemos el operador de suma
  515. a estos tres números.
  516. Y debo obtener, ¿qué?
  517. 8,17.
  518. 25.4.
  519. Así que debería poder preguntarle
    a Lisp cuál es el valor de esto
  520. y me devolverá 25.4.
  521. Introduzcamos algunos nombres.
  522. Eso que escribí se llama
    una combinación.
  523. Y una combinación consiste,
    en general,
  524. en aplicar un operador --
  525. esto es un operador--
  526. a algunos operandos.
  527. Estos son los operandos.
  528. Y por supuesto, puedo hacer
    cosas más complejas.
  529. La razón por la que puede obtener
    complejidad de esto es
  530. porque en los operandos mismo,
    en general, pueden ser
  531. combinaciones.
  532. Así que por ejemplo, podría decir
    ¿cuál es la suma de 3 y
  533. el producto de 5 y 6 y 8 y 2?
  534. Y debería obtener, veamos.
  535. 30, 40, 43.
  536. Así que Lisp debería
    decirme que eso es 43.
  537. Formar combinaciones es la
    necesidad de combinación
  538. más básica que veremos.
  539. Y luego, bueno,
    verán un poco de sintaxis aquí.
  540. Lisp usa lo que se llama notación
    prefija, que quiere decir que
  541. el operador se escribe a la izquierda
    de los operandos.
  542. Sólo es una convención.
  543. Y noten, está totalmente
    entre paréntesis.
  544. Y los paréntesis lo dejan
    completamente sin ambiguedades.
  545. Asi que mirando esto, puedo ver
    que está el operador,
  546. y que hay 1,2,3,4 operandos.
  547. Y puedo ver que el segundo operando
    aquí es en sí mismo una
  548. combinación que tiene
    un operador y dos operandos.
  549. Los paréntesis en Lisp, son un poco,
    o muy diferentes,
  550. a los paréntesis de la matemática
    convencional.
  551. En matemática, lo usamos para indicar
    una agrupación,
  552. y a veces no molesta que no los pongas
  553. si la gente entiende
  554. que eso es un grupo.
  555. Y en general,
    no molesta si pones paréntesis
  556. de más, porque quizá distinga
  557. más aún la agrupación.
  558. Lisp no es así.
  559. En Lisp, no puede dejar los paréntesis,
    y no puede poner paréntesis
  560. de más, porque agregar
    paréntesis
  561. siempre significa de manera
    exacta y precisa que esto es
  562. una combinación que
    tiene sentido, aplicando
  563. operadores a operandos.
  564. Y si no los pongo,
    si no pongo esos paréntesis,
  565. significaría otra cosa.
  566. De hecho, la manera de pensar sobre esto
    es que lo que realmente estoy
  567. haciendo cuando escribo algo así
    es estar escribiendo un árbol.
  568. Así que esta combinación es un árbol
    que tiene un más y luego un 3
  569. y luego algo más y un 8 y un 2.
  570. Y entonces esta otra cosa
    es en sí misma un pequeño
  571. subárbol que tiene una estrella
    y un 5 y un 6.
  572. Y la manera de pensar en eso
    es que lo que en verdad
  573. estamos escribiendo estos árboles
    y los paréntesis son una forma
  574. de escribir esta estructura
    de dos dimensiones como
  575. una cadena de caracteres lineal.
  576. Porque, por lo menos al principio,
    cuando Lisp comenzaba y la gente
  577. tenía teletipo o tarjetas perforadas
    o lo que sea, esto
  578. era más conveniente.
  579. Quizá si Lisp apareciera hoy,
    la sintaxis de Lisp
  580. se vería así.
  581. Bueno, observemos cómo
    se ve eso
  582. en una computadora.
  583. Aquí tengo establecida
    una interacción Lisp.
  584. Hay un editor.
  585. Y arriba, voy a tipear algunos valores
    y preguntarle a Lisp
  586. lo que son.
  587. Por ejemplo, puedo preguntarle a Lisp,
    cuál es
  588. el valor de este símbolo.
  589. Es un 3.
  590. Y le pido a Lisp que lo evalúe.
  591. Y ahí ven que Lisp ha terminado
    debajo y ha dicho
  592. oh sí, es un 3.
  593. O puedo decir, ¿cuál es la suma de 3 y
    4 y de 8?
  594. ¿Cuánto da esa combinación?
  595. Y pedirle a Lisp que lo evalúe.
  596. Es 15.
  597. O puedo tipear algo
    más complicado.
  598. Puedo preguntar cuál es la suma
    del producto de 3 y la suma
  599. de 7 y 19.5.
  600. Y notarán que Lisp viene
    con algo incorporado
  601. que ayuda para dar seguimiento
    a todos estos paréntesis.
  602. Miren que al tipear el próximo
    paréntesis de cierre, que va
  603. a cerrar la combinación que
    comienza con la estrella,
  604. el paréntesis de apertura
    se remarcará.
  605. Borraré estos y lo haré de nuevo.
  606. Tipeo el cierre y
    verán que cierra el más.
  607. Cierro de nuevo y
    eso cierra la estrella.
  608. Ahora vuelvo a la suma,
    y quizá voy a sumar
  609. a todo eso un 4.
  610. Eso cierra el más.
  611. Ahora tengo una combinación
    completa y puedo preguntarle
  612. a Lisp el valor de eso.
  613. Ese balanceo de paréntesis
    está incorporado en un montón
  614. de sistemas Lisp para dar seguimiento
    porque es realmente
  615. difícil de hacer a mano con todos
    esos paréntesis.
  616. Hay otra convención
    para mantener un seguimiento
  617. de los paréntesis.
  618. Déjenme escribir otra
    combinación complicada.
  619. Tomemos la suma del producto
    de 3 y de 5 y sumemos eso
  620. a algo más.
  621. Y lo que voy a hacer es
    indentar para que
  622. los operandos se escriban
    verticalmente.
  623. Que es la suma de eso y
    el producto de 47 y --
  624. digamos el producto el 47 con la
  625. diferencia de 20 y 6.8.
  626. Eso quiere decir restarle 6.8 a 20.
  627. Y luego ven los
    paréntesis cerrarse.
  628. Cierro el menos.
  629. Cierro la estrella.
  630. Y ahora pongamos otro operando.
  631. Verán que el editor de Lisp
    está indentando a la derecha
  632. de la posición automáticamente
    para ayudarme a dar seguimiento.
  633. Lo haré de nuevo.
  634. Cerraré ese último
    paréntesis de nuevo.
  635. Verán que balancea el más.
  636. Ahora puedo preguntar,
    ¿cuál es el valor de eso?
  637. Así que esas dos cosas,
    indentar a la derecha, que se conoce
  638. como impresión bonita,
    y remarcar paréntesis, son dos
  639. cosas que muchos sistemas Lisp
    tienen incorporadas para ayudar
  640. a dar seguimiento.
  641. Y deberían aprender cómo usarlos.
  642. Bueno, esas son las primitivas.
  643. Hay un medio de combinación.
  644. Ahora vayamos a los medios
    de abstracción.
  645. Me gustaría poder tomar la idea
    de que hago una
  646. combinación como esta
    y abstraerla y darle un
  647. nombre simple, para que la pueda
    usar como un elemento.
  648. Y eso lo hago en Lisp con "define".
    Y puedo decir,
  649. por ejemplo, define A para que sea
    el producto de 5 y 5.
  650. Y luego puedo preguntarle a Lisp,
    por ejemplo, cuál es el
  651. producto de A y A.
  652. Y esto debería ser 25,
    y esto otro debería ser 625.
  653. Y luego, algo crucial,
    puedo usar ahora A--
  654. aquí lo usé como una combinación--
  655. pero puedo usarlo en cosas
    más complicadas que puedo
  656. nombrar también.
  657. Así que puedo decir, define B para
    que sea la suma de, digamos, A y
  658. el producto de 5 y A.
    Y luego cierro el más.
  659. Miremos esto en la computadora y
  660. observemos cómo se ve.
  661. Solo tipearé lo que escribí
    en el pizarrón.
  662. Puedo decir, define A como
    el producto de 5 y 5.
  663. Y contarle eso a a Lisp.
  664. Y noten que Lisp
    respondió ahí con
  665. una A debajo.
  666. En general, cuando tipeas
    una definición en Lisp,
  667. éste responde con el símbolo
    que se está definiendo.
  668. Ahora podría preguntarle a Lisp
    cuál es el producto de A y A.
  669. Y dice que es 625.
  670. Puedo definir B como la suma
    de A y el producto de 5 y A.
  671. Cierro el paréntesis de la estrella.
  672. Cierro el más.
  673. Cierro el "define". Lisp dice, OK,
    B, ahí debajo.
  674. Y ahora puedo preguntarle a Lisp
    el valor de B.
  675. O puedo pedirle algo más complicado,
    como cuál es
  676. la suma de A y el cociente entre B y 5.
  677. Esa barra es dividir, otro
    operador primitivo.
  678. Dividí B por 5 y se lo sumé a A.
    Lisp dice,
  679. OK, eso es 55.
  680. Así que así es que cómo se ve.
  681. Ahí está el medio básico
    para definir algo.
  682. Es la manera más simple de nombrar,
    pero no es realmente
  683. muy poderoso.
  684. Verán, lo que en verdad
    quisiera nombrar --
  685. recuerden que estamos hablando
    de métodos generales --
  686. Me gustaría nombrar la idea general de,
  687. por ejemplo, multiplicar 5 por 5,
    o 6 por 6, o 1001
  688. por 1001, o 1001.7 por 1001.7.
  689. Me gustaría poder nombrar
    la idea general de
  690. multiplicar algo por sí mismo.
  691. Bueno, ustedes saben qué es.
  692. Se llama elevar al cuadrado.
  693. Y la forma en que puedo
    hacerlo en Lisp es definir
  694. "square" de algo X como
    multiplicar X por sí mismo.
  695. Y al hacer eso, puedo
    preguntarle a Lisp, por ejemplo,
  696. cuánto es 10 al cuadrado.
  697. Y Lisp dirá 100.
  698. Ahora miremos esto
    un poco más de cerca.
  699. Aquí está la definición de "square".
  700. Para elevar algo al cuadrado,
    multiplicarlo por sí mismo.
  701. Ven esta X aquí.
  702. Es algo así como un pronombre,
    algo a lo que
  703. voy a elevar al cuadrado.
  704. Y lo que hago con él es
    multiplico X,
  705. lo multiplico por sí mismo.
  706. OK.
  707. Esa es la notación para definir
    un procedimiento.
  708. De hecho, esto es un poco confuso,
    porque es
  709. algo así a cómo usaría "square".
  710. Y digo "square" de X,
    o "square" de 10, pero
  711. no estoy dejando muy en claro
    que estoy en efecto nombrando algo.
  712. Así que déjenme escribir esta
    definición de otra forma
  713. que deja un poco más claro
  714. que estoy nombrando algo.
  715. Diré, "define square" como
    lambda de x , multiplicar X por X.
  716. Aquí estoy nombrando algo como "square",
    de la misma manera que aquí
  717. estoy nombrando algo A. Pero aquello a
    lo que estoy llamando "square"--
  718. Aquí, lo que nombro A
    es el valor de esta combinación.
  719. Aquí, lo que estoy llamando "square"
    es esta cosa que
  720. comienza con un lambda, y
    lambda es la forma de Lisp de decir
  721. "haz un procedimiento".
  722. Miremos esto más de cerca
    en la diapositiva.
  723. La manera en leo esta definición es
    defino "square" como
  724. un procedimiento --
  725. eso es lo que la lambda es--
  726. Haz un procedimiento
    con un argumento llamado X.
  727. Y lo hace es retorna el resultado de
  728. multiplicar X por sí mismo.
  729. Ahora bien, en general,
    vamos a usar esta anterior forma
  730. de definir, solamente porque
    es un poco más conveniente.
  731. Pero no pierdan de vista el hecho
    que en realidad es esto.
  732. De hecho, en lo que al intérprete
    de Lisp respecta,
  733. no hay diferencia entre tipear esto
  734. o tipear esto otro.
  735. Y hay una palabra para eso,
    azúcar sintáctico.
  736. Lo que azúcar sintáctico significa,
    es tener formas más
  737. convenientes para escribir algo.
  738. Así que esto es en realidad esto es
    azúcar sintáctico para
  739. esta cosa griega con la lambda.
  740. Y la razón por la que deben recordar
    esto es que no se olviden que,
  741. al escribir algo así,
  742. estoy realmente nombrando algo.
  743. Estoy nombrando algo como "square",
    y ese algo que estoy
  744. nombrando como "square" es un
    procedimiento que se está construyendo.
  745. Miremos eso en la computadora también.
  746. Así que diré, "define square" de
  747. X como multiplicar X por X.
  748. Ahora digámosle eso a Lisp.
  749. Dice "square". Ven, he nombrado algo
    como "square". Ahora,
  750. habiendo hecho esto,
    le puedo preguntar a Lisp cuál es
  751. "square" de 1001?
  752. O , en general, podría decir,
    ¿cuánto es elevar al cuadrado la suma de
  753. de 5 y de 7?
  754. Eso es elevar al cuadrado 12, 144.
  755. O puedo usar "square" en sí mismo
    como un elemento en alguna
  756. combinación.
  757. Puedo preguntar,
    ¿cuál es la suma del "square" de 3 y
  758. el "square"de 4?
  759. 9 más 16 es 25.
  760. O puedo usar "square" como un elemento
    en una cosa mucho más
  761. complicada.
  762. Puedo preguntar, ¿cuál es el "square" del
    "square" del
  763. "square" de 1001?
  764. Y eso elevar al cuadrado
    el cuadrado del cuadrado de 1001.
  765. O puedo preguntarle a Lisp
    ¿qué es "square"?
  766. ¿Cuál es el valor de eso?
  767. Y Lisp retorna una manera
    convencional para decirme
  768. que eso es un procedimiento.
  769. Dice, "procedimiento compuesto square".
    Recuerden que el valor de
  770. "square" es este procedimiento,
    y las estrellas
  771. y los corchetes es la forma
    convencional de Lisp
  772. para describir eso.
  773. Ahora veamos dos
    ejemplos más de definición.
  774. Aquí hay dos procedimientos más.
  775. Defino el promedio de X e Y
    como la suma de X y de Y
  776. dividido por 2.
  777. O teniendo el promedio
    y el cuadrado medio, teniendo el promedio
  778. y el cuadrado, puedo usarlos para definir
    el "mean square" o cuadrado medio de
  779. algo, que es el promedio
    del cuadrado de X y el
  780. cuadrado de Y.
  781. Así que por ejemplo, habiendo hecho eso,
    podría preguntar cuál es
  782. el "mean square" de 2 y 3?
  783. Y debería obtener el promedio
    de 4 y 9, que es 6.5.
  784. Lo clave aquí es que, al haber
    definido "square", puedo
  785. usarlo como si fuera una primitiva.
  786. Así que si miramos en
    la diapositiva, si miro a
  787. "mean square", la persona que define
    el cuadrado medio no tiene que
  788. saber, en este punto, si "square"
    vino incorporado
  789. en el lenguaje o si fue
  790. un procedimiento que fue definido.
  791. Y eso es algo clave en Lisp,
    que uno no hace
  792. distinciones arbitrarias entre
    cosas que resultan que son
  793. primitivas del lenguaje
    y cosas que
  794. resultan que viene incorporadas.
  795. Una persona usándolo
    ni siquiera debería tener que saberlo.
  796. Así que las que cosas que construimos
    son usada con todo el poder
  797. y la flexibilidad
    a que si fueran primitivas.
  798. De hecho, podemos asentar esto
    mirando en la
  799. computadora una vez más.
  800. Ya hablamos del "plus".
  801. Y de hecho, si vengo aquí en la
    pantalla de la computadora y pregunto
  802. cuál es el valor de "plus".
  803. Noten lo que escribe Lisp.
  804. Aquí debajo, escribió
    "procedimiento compuesto
  805. plus". Porque en este sistema,
    resulta que el
  806. operador de adición es en sí mismo
    un procedimiento compuesto.
  807. Y si no hubiera tipeado esto,
    ustedes nunca lo hubieran sabido, y
  808. de cualquier manera no habría
    marcado la diferencia.
  809. No nos interesa.
  810. Está por debajo del nivel de
    abstracción
  811. con el que estamos lidiando.
  812. Así que la clave es que uno no puede
    determinar, no debería ser capaz
  813. de determinar, en general, la diferencia
    entre cosas que
  814. están incorporadas y
    cosas que son compuestas.
  815. ¿Por qué es esto?
  816. Porque las cosas compuestas
    tienen una abstracción
  817. alrededor de ellas.
  818. Ya hemos visto casi todos los
    elementos de Lisp.
  819. Solo queda una cosa más que tenemos
    que mirar, y eso cómo
  820. hacer un análisis de casos.
  821. Déjenme mostrarles lo que quiero decir.
  822. Querríamos pensar acerca de la
    definición matemática del
  823. de la función de valor absoluto.
  824. Podría decir que el valor absoluto
    de X es al función que tiene la
  825. propiedad que es el negativo de X
  826. para X menor a cero. Cero si X es igual a cero.
  827. Y es X para X mayor a cero.
  828. Y Lisp tiene una forma de hacer
    análisis de casos.
  829. Déjenme definirles el valor absoluto.
  830. Defino el valor absoluto de X
    como un condicional.
  831. Esto significa análisis de casos, COND.
  832. Si X es menor a 0,
    la respuesta es negar X.
  833. Lo que escribí aquí es una cláusula.
  834. Toda esta cosa
    es una cláusula condicional,
  835. y tiene dos partes.
  836. Esta parte es el
    predicado de la condición.
  837. Eso es una condición.
  838. Y la condición se expresa
    con algo llamado
  839. predicato. Y un predicado en Lisp
    es una cosa
  840. que devuelve o verdadero o falso.
  841. Y puede ver que Lisp tiene un
    procedimiento primitivo,
  842. "less-than", menor que,
    que prueba si algo es verdadero o falso.
  843. Y la parte de la cláusula es
    un acción o algo para hacer
  844. en el caso en el que eso
    sea verdadero.
  845. Y aquí, lo que estoy
    haciendo es negar X.
  846. El operador de negación,
    el símbolo menos en Lisp,
  847. es un poco gracioso.
  848. Si hay dos o más argumentos, si hay dos
  849. argumentos, le resta el segundo al primero, y
  850. ya vimos eso.
  851. Y si hay un único argumento, lo niega.
  852. Así que eso se corresponde con aquello.
  853. Y luego hay otra cláusula COND.
  854. Dice que en el caso
    en que X es igual a cero,
  855. la respuesta es cero.
  856. Y en el caso donde X es mayor a cero,
  857. la respuesta es X.
  858. Cierro la cláusula.
  859. Cierro el COND.
  860. Cierro la definición.
  861. Y esa es la definición
    de valor absoluto.
  862. Y verán que el análisis de casos
    es muy parecido
  863. al análisis de casos
    que usan en matemáticas.
  864. Hay una manera algo diferente
    de escribir un caso de
  865. análisis restringido.
  866. A menudo, uno tiene un caso de
    análisis donde hay un único
  867. caso, donde pruebas una condición,
    y luego, dependiendo de
  868. si es verdadero o falso, haces algo.
  869. Y hay otra definición
    de valor absoluto que es
  870. muy parecida y que dice que
    si X es menor a cero, entonces
  871. el resultado es el negado de x.
  872. En otro caso, la respuesta es X.
  873. Y usaremos el "IF" un montón.
  874. Pero de nuevo, lo que hay que
    recordar es que esta form
  875. de valor absoluto que están mirando
    aquí, y esta otra
  876. aquí que escribí en el pizarrón, son
  877. esencialmente lo mismo.
  878. Y "IF" y "COND" son--
  879. Bueno, de la manera que quieran.
  880. Pueden pensar en "COND"
    como azúcar sintáctico para "IF", o
  881. pueden pensar en "IF"
    como azúcar sintáctico para "COND", y
  882. no marca la diferencia.
  883. La persona que implemente un
    sistema Lisp, elegirá una de las dos
  884. e implementará la otra
    en términos del elegido.
  885. Y no importa cuál elijas.
  886. ¿Por qué no nos tomamos un descanso?
    Y luego respondemos algunas preguntas.
  887. ¿Cómo es que a veces cuando escribo
    "define", abro un
  888. paréntesis aquí y digo, "define"
    abro paréntesis algo u otra cosa,
  889. y a veces cuando escribo esto,
  890. no abro paréntesis?
  891. La respuesta es que esta forma
    particular de "define", donde uno
  892. dice "define" alguna expresión es
    una cosa muy especial para
  893. definir procedimientos.
  894. Pero de nuevo, lo que realmente
    significa es que estoy definiendo este
  895. símbolo, "square", como eso.
  896. Así que la manera en que deberían pensar
    en eso es que lo que hace "define"
  897. es uno escribe "define" y la segunda
    cosa que escribe es e
  898. símbolo aquí -- sin paréntesis--
  899. el símbolo que uno está definiendo
    y qué uno esta definiendo que sea.
  900. Como aquí y aquí.
  901. Esa es la manera básica de
    usar "define". Y luego,
  902. hay una truco sintáctico especial
    que le permite a uno
  903. definir un procedimiento que se ve así.
  904. Así que la diferencia es si uno
    está o no definiendo
  905. un procedimiento.
  906. Bueno, créanlo o no,
    ya saben suficiente Lisp
  907. para esencialmente escribir
    cualquier procedimento numérico
  908. que escribirían es un lenguaje como
    FORTRAN o Basic o lo que sea,
  909. o esencialmente, cualquier
    otro lenguaje.
  910. Y probablemente digan que
    eso no es creíble porque
  911. saben que esos lenguajes
    tiene cosas como "for"
  912. o sentencias como "do until while"
    o algo así.
  913. Pero en realidad no necesitamos
    nada de eso.
  914. De hecho, no usaremos
    nada de eso
  915. en este curso.
  916. Déjenme mostrarles.
  917. De nuevo, mirando a la raíz cuadrada,
    volvamos al
  918. algoritmo de raíz cuadrada de
    Herón de Alejandría.
  919. Recuerden lo que decía.
  920. Decía, para hallar una
    aproximación de la raíz
  921. cuadrada de X, hacer una estimación
    y mejorar esa estimación
  922. promediándola con X sobre la estimación.
  923. Se sigue mejorándola hasta que la
    estimación sea lo suficientemente buena.
  924. Ya aludí a la idea.
  925. La idea es que si
    la estimación inicial que uno hizo
  926. fuera igual a la raíz cuadrada de X,
    entonces G aquí
  927. sería igual a X/G.
  928. Así que si uno alcanza
    la raíz cuadrada, promediarla
  929. no cambiaría nada.
  930. Si la G que uno elige es más grande
    que la raíz cuadrada de
  931. X, entonces X/G será menor que
    la raíz cuadrada de X, así que
  932. cuando uno promedie G y X/G, obtendrá
  933. algo en el medio.
  934. Así que si uno elige un G
    que es muy pequeño,
  935. la respuesta será muy grande.
  936. Si uno elige un G que es muy grande,
    si el G de uno es más grande
  937. que la raíz cuadrada de X y
    X/G será menor que
  938. la raíz cuadrada de X.
  939. Así que promediar siempre
    de algo en el medio.
  940. Y luego, no es trivial,
    pero es posible
  941. mostrar que, de hecho, si G es ligeramente
    distinto a la raíz cuadrada de X,
  942. el promedio de G y X/G seguirá
  943. acercándose a la raíz cuadrada de X.
    Así que si uno sigue
  944. haciendo esto lo suficiente,
    eventualmente estará
  945. tan cerca como quiera.
  946. Y luego está el otro hecho de que
    uno siempre puede empezar este
  947. proceso usando un 1 como
    estimación inicial.
  948. Y siempre convergerá
    a la raíz cuadrada de X. Así
  949. que ese es el método de promedios sucesivos
  950. de Herón de Alejandría.
  951. Escribámoslo en Lisp.
  952. Bueno, la idea central es:
    ¿qué significa hacer una
  953. estimación de la raíz cuadrada de X?
  954. Escribamos eso.
  955. Diremos, "define" para probar
    una estimación de la raíz cuadrada de X.
  956. ¿Qué hacemos?
  957. Diremos, si la estimación es lo
    suficientemente buena para
  958. la raíz cuadrada de X, entonces,
    como respuesta,
  959. tomaremos la estimación.
  960. En otro caso, intentaremos
    mejorar la estimación.
  961. Mejoraremos la estimación
    para la raíz cuadrada de X y
  962. la probaremos como una estimación
    para la raíz cuadrada de X. Cierro
  963. el "TRY". Cierro el "IF".
    Cierro el "define". Así que así
  964. es como probamos una estimación.
  965. Y luego, la otra parte del proceso
    dice que, para
  966. computar las raíces cuadradas, diremos
    "define" para computar las
  967. raíces cuadradas de X, probaremos
    1 como una estimación de la raíz
  968. cuadrada de X. Bueno,
    tenemos que definir un par de cosas más.
  969. Tenemos que decir cómo es una estimación
    lo suficientemente buena.
  970. Y cómo mejoramos esa estimación.
  971. Miremos eso.
  972. El algoritmo para mejorar la estimación
    de la raíz cuadrada de
  973. X, promediamos--
  974. ese era el algoritmo--
  975. promediamos la estimación con el
    cociente de
  976. dividir X por la estimación.
  977. Así es como mejoramos una estimación.
  978. Y para determinar si una estimación
    es lo suficientemente buena, bueno,
  979. tenemos que dedicir algo.
  980. Esto se supone que es una estimación
    de la raíz cuadrada de X, así
  981. que una posible cosa que pueden hacer
    es preguntar si al tomar
  982. la estimación y elevarla al cuadrado
    se obtiene algo muy cercano a X.
  983. Una forma de decir eso es decir
    elevo al cuadrado la estimación,
  984. le resto X a eso y veo
    si el valor absoluto
  985. de toda esa cosa es menor que algún
    número pequeño, que depende
  986. de mi propósito.
  987. Así que ese es un procedimento
    completo para cómo computar
  988. la raíz cuadrada de X.
    Veamos la estructura de eso
  989. un poco.
  990. Tengo toda la cosa.
  991. Tengo la noción de cómo computar
    la raíz cuadrada.
  992. Es una especie de módulo.
  993. Es una especie de caja negra.
  994. Está definido en términos de cómo
    probar una estimación para la raíz
  995. cuadrada de X.
  996. "TRY" está definido en términos de,
    bueno, poder determinar
  997. si algo es lo
    suficientemente bueno y decir
  998. cómo mejorar algo.
  999. Lo suficientemente bueno.
  1000. "TRY" está definido en términos de
    "GOOD-ENOUGH" e "IMPROVE".
  1001. Y vemos que más puedo completar.
  1002. Bueno, bajaré por este árbol.
  1003. "GOOD-ENOUGH"
    está definido en términos del
  1004. valor absoluto y de "SQUARE"".
  1005. E "IMPROVE" está definido en términos de
    algo llamado
  1006. promedio y
    luego otro operador primitivo.
  1007. La raíz cuadrada está definida en
    términos de "TRY". "TRY" está
  1008. definido en términos de "GOOD-ENOUGH"
    e "IMPROVE",
  1009. pero también
    en términos del mismo "TRY".
  1010. Así que "TRY" está definido en términos
    de "TRY" en sí mismo.
  1011. Bueno, eso podría darles algunos
    problemas. Su profesor de geometría
  1012. de secundario probablemente les dijo
    que está mal definir ir y
  1013. definir cosas en términos
    de sí mismos, porque
  1014. no tiene sentido.
  1015. Pero eso es falso.
  1016. A veces tiene perfecto sentido
    definir cosas en
  1017. términos de ellas mismas.
  1018. Y este es el caso.
  1019. Y podemos mirar eso.
  1020. Podemos escribir lo que esto significa
    y decir, supongan que
  1021. le pregunto a Lisp
    qué es la raíz cuadrada de 2.
  1022. ¿Qué significa la raíz
    cuadrada de 2?
  1023. Bueno, eso significa que pruebo con 1
    como una estimación
  1024. para la raíz cuadrada de 2.
  1025. Y ahora miro.
  1026. Pregunto si 1 es una estimación
    lo suficientemente buena
  1027. para la raíz cuadrada de 2.
  1028. Y eso depende de la prueba
    que hace "GOOD-ENOUGH".
  1029. Y en este caso, "GOOD-ENOUGH" dice
    que no, que 1 no es
  1030. una estimación lo suficientemente buena
    de la raíz cuadrada de 2.
  1031. Y eso se reduce en decir,
    tengo que probar una mejora--
  1032. mejorar 1 como estimación para la
    raíz cuadrada de 2, y probar eso
  1033. como una estimación de la
    raíz cuadrada de 2.
  1034. Mejorar 1 como una estimación
    de la raíz cuadrada de 2 significa que
  1035. promedio 1 y 2 dividido 1.
  1036. Así que está será un promedio.
  1037. Esta cosa de aquí será el promedio
    de 1 y del
  1038. cociente entre 2 y 1.
  1039. Es esta pieza de aquí.
  1040. Y eso es 1.5.
  1041. Así que la raíz cuadrada de 2
    se reduce a probar 1 para
  1042. la raíz cuadrada 2, que se reduce
    a probar 1.5 como la
  1043. estimación para la raíz cuadrada de 2.
  1044. Así que eso tiene sentido.
  1045. Miremos el resto del proceso.
  1046. Si probarmos 1.5, eso reduce.
  1047. 1.5 resulta que no es una estimación
    lo suficientemente buena para
  1048. la raíz cuadrada de 2.
  1049. Y eso reduce en probar el promedio
    de 1.5 y 2 dividido por
  1050. 1.5 como estimación para
    la raíz cuadrada de 2.
  1051. Y ese promedio resulta ser 1.333.
  1052. Así que toda esta cosa reduce
    en probar 1.333 como una estimación
  1053. de la raíz cuadrada de 2.
  1054. Y luego seguimos así.
  1055. Eso reduce a otro llamado
    a "GOOD-ENOUGH", 1.4
  1056. algo u otro.
  1057. Y sigo así hasta que el proceso
    finalmente se detiene con
  1058. algo que es lo suficientemente bueno,
    cree que es lo suficientemente bueno, que
  1059. en este caso, es 1.4142, algo u otro.
  1060. Así que el proceso
    tiene perfecto sentido.
  1061. Esto se llama, por cierto,
    una definición recursiva.
  1062. Y la habilidad de poder hacer
    definiciones recursivas es
  1063. una fuente de increíble poder.
  1064. Y como pueden ver que di la pista,
    es la cosa
  1065. que efectivamente nos permite
    hacer estos cómputos infinitos
  1066. que continúan hasta que algo
    se hace verdadero, sin tener otra
  1067. restricción más que la posibilidad
    de llamar a un procedimiento.
  1068. Bueno, veamos, hay una cosa más.
  1069. Déjenme mostrarles una variante
    de la definición de raíz cuadrada
  1070. aquí en la diapositiva.
  1071. Es casi la misma cosa.
  1072. Lo que hemos hecho es
    empaquetar las definiciones de
  1073. "IMPROVE", "GOOD-ENOUGH" y "TRY"
    dentro de "SQUARE-
  1074. ROOT". Así que, de hecho, lo que hice fue
    construir una
  1075. caja de raíz cuadrada.
  1076. Así que construí una caja
    que el procedimiento de raíz cuadrada
  1077. que alguien puede usar.
  1078. Podrían poner 36 y saldría un 6.
  1079. Y luego, empaquetados dentro de esta caja,
    están las definiciones de
  1080. "TRY", "GOOD-ENOUGH" e "IMPROVE",
  1081. Están escondidas dentro
    de la caja.
  1082. Y la razón para hacer eso
    es que si, si alguien está usando
  1083. la raíz cuadrada, si George está
    usando la raíz cuadrada, a George
  1084. probablemente no le interese que
    cuando implementé
  1085. la raíz cuadrada, tenía cosa dentro
    llamadas "TRY" y
  1086. "GOOD-ENOUGH" e "IMPROVE".
    Y, de hecho, Harry podría tener
  1087. un procedimiento de raíz cúbica
    que tiene "TRY" y "GOOD-ENOUGH" e
  1088. "IMPROVE". Y para no confundir
    a todo el sistema,
  1089. sería bueno que Harry
    empaquetara los procedimientos
  1090. internos dentro de su procedimiento
    de raíz cúbica.
  1091. Bueno, esto se llama estructura
    de bloque, esta forma particular
  1092. de empaquetar las entrañas dentro
    de la definición.
  1093. Volvamos y miremos la diapositiva
    de nuevo.
  1094. La manera de leer esta especie
    de procedimiento es decir, para definir
  1095. la raíz cuadrada, bueno, dentro
    de la definición tengo la
  1096. definición de "IMPROVE" y la
    definción de "GOOD-
  1097. ENOUGH" y la definición de "TRY".
    Y luego, sujeto a
  1098. esas definiciones, la manera de hacer
    la raíz cuadrada es probar con 1.
  1099. Y noten que aquí no tengo que decir que
    1 es una estimación para la
  1100. raíz cuadrada de X, porque como
    todo está dentro de
  1101. raíz cuadrada, casi que tiene
    este X conocido.
  1102. Déjenme resumir.
  1103. Empezamos con la idea
    de que lo vamos a estar
  1104. haciendo es expresar
    conocimiento imperativo.
  1105. Y de hecho, aquí hay una diapositiva
    que resume la manera en que
  1106. miramos en Lisp.
  1107. Empezamos mirando algunos
    elementos primitivos en
  1108. la adición y la multiplicación,
    algunos predicados para probar
  1109. si algo es menor o igual que otra cosa.
  1110. Y de hecho, vimos que en el sistema que
  1111. estamos usando, estas ni siquiera son
    en efecto primitivas, pero
  1112. que no importa.
  1113. Lo que importa es que vamos
    a usarlas como si fueran
  1114. primitivas.
  1115. No vamos a mirar adentro.
  1116. También tenemos algunos datos
    primitivos y algunos números.
  1117. Vimos algunos medios de
    composición, medios de
  1118. combianción, siendo el básico
    la composición de funciones y
  1119. la construcción de combinaciones
    con operadores y operandos.
  1120. Y luego hay otras cosas,
    como "COND" e "IF" y
  1121. "DEFINE". Pero lo principal de
    "DEFINE" en particular,
  1122. era que un medio de abstracción.
  1123. Era la forma en la que nombramos cosas.
  1124. También pueden ver de esta
    diapositiva que no sólo dónde
  1125. hemos estado, sino los agujeros
    que tenemos que llenar.
  1126. En algún punto, tenemos que
    hablar acerca de cómo combinar
  1127. datos primitivos para obtener
    datos compuestos y cómo abstraer
  1128. datos para poder usar grandes
    pedazos de datos como
  1129. si fueran primitivos.
  1130. Así que ahí es hacia donde vamos.
  1131. Pero antes de hacer eso, por
    el próximo par de clases, vamos
  1132. a estar hablando, en primer lugar,
    cómo es que uno
  1133. enlaza estos procedimiento
    que escribimos y los procesos
  1134. que ocurren dentro de la máquina.
  1135. Y luego, cómo es que uno puede
    empezar a usa el poder de Lisp
  1136. para hablar no sólo acerca
    estos pequeños cómputos
  1137. individuales, sino también acerca
    de métodos de convención general
  1138. para hacer cosas.
  1139. OK. ¿Hay alguna pregunta?
  1140. AUDIENCIA: Sí.
  1141. Si definimos A usando paréntesis
    en vez de como lo
  1142. hicimos, ¿cuál sería la diferencia?
  1143. PROFESOR: Si escribo esto,
    si escribo aquello, lo que estaría
  1144. haciendo es definir un procedimiento
    llamado A. En este caso, un
  1145. procedimiento sin argumentos,
    que, cuando lo corra, me
  1146. devolverá 5 multiplicado por 5.
  1147. AUDIENCIA: Bien.
  1148. Quiero decir, obtienes el mismo
    resultado, excepto que para uno
  1149. realmente tiene diferentes--
  1150. PROFESOR: Correcto.
  1151. Y la diferencia sería, en el viejo --
  1152. Déjenme ser un poco más claro aquí.
  1153. Llamemos a esto A, como aquí.
  1154. Y pretendan que aquí, solo para
    contrastar, defino D como
  1155. el producto de 5 y 5.
  1156. Y la diferencia entre ambos,
    pensemos acerca de
  1157. interacciones con el
    intérprete de Lisp.
  1158. Podría tipear A y Lisp devolvería 25.
  1159. Podría tipear D, y si solo tipeo D,
    Lisp retornaría un
  1160. procedimiento compuesto D,
    porque eso es lo que es.
  1161. Es un procedimiento.
  1162. Podría correr D. Podría decir,
    ¿cuál es el valor de correr D?
  1163. Esta es una combinación sin operandos.
  1164. Veo que no hay operandos.
  1165. No puse ninguno después de D.
  1166. O podría decir, sólo por completitud,
    si tipeara,
  1167. ¿cuál es el valor de correr A?
  1168. Y obtendría un error.
  1169. El error sería el mismo que allí.
  1170. El error diría, lo siento, 25,
    que es el valor de
  1171. A, no es un operador
    que pueda aplicar a algo.