40 | Funciones definidas por el usuario |
Como se ha podido ver hasta ahora, es muchísimo lo que se puede hacer con las funciones nativas que existen dentro de Wolfram Language. Sin embargo, se puede llegar aún más lejos si hay la posibilidad de que el usuario defina, además, sus propias funciones. En Wolfram Language esto se hace de una manera muy flexible.
Aquí se define la función pinks, que admite un argumento cualquiera:
In[1]:= |
Ahora se usa la definición de la función:
In[2]:= |
Out[2]= |
In[3]:= |
Out[3]= |
¿Cómo trabaja esta definición de función? La idea es que := define un valor para el patrón pinks[n_]. Al solicitar pinks[5], se encuentra que coincide con el patrón pinks[n_], y se usa entonces el valor definido para este.
Sin embargo, esto es solo el comienzo del asunto en lo que toca a la definición de funciones al usar Wolfram Language. Y es que, en Wolfram Language, puede darse una definición para cualquier cosa.
He aquí una lista de expresiones:
In[4]:= |
Out[4]= |
In[5]:= |
Ahora f[Red] y f[Green] se sustituyen por los valores definidos, mientras que los otros quedan igual:
In[6]:= |
Out[6]= |
A continuación, se añade una definición para el patrón f[x_]. Esta será utilizada por Wolfram Language cuando no sean aplicables las definiciones especiales, dadas previamente, para f[Red] y f[Green].
Se define un valor para f con un argumento cualquiera:
In[7]:= |
In[8]:= |
Out[8]= |
In[9]:= |
Otro ejemplo: se considera el ejercicio, muy utilizado en las ciencias de la computación, de definir la función factorial. Se comienza diciendo que factorial[1]=1. A continuación, se define cómo calcular recursivamente factorial[n_], en términos de otro caso de factorial.
Proporcione una definición recursiva del factorial:
In[10]:= |
Pida factorial[50]:
In[11]:= |
Out[11]= |
In[12]:= |
Out[12]= |
En lugar de dar separadamente las definiciones de factorial[1] y factorial[n_], se podría haber dado una sola definición y usar If. Pero al dar las definiciones por separado se facilita su lectura y su comprensión.
Una definición alternativa usando If:
In[13]:= |
Se ve bien el dar por separado los casos especiales, pero la contundencia real de la posibilidad de hacer definiciones para cualquier cosa va más allá de los casos simples tipo función[argumentos].
Se define un valor para un patrón:
In[14]:= |
Ahora, se usa esa definición:
In[15]:= |
Out[15]= |
Una forma menos elegante de hacer lo mismo, basada en la definición tradicional tipo función[argumento]:
In[16]:= |
Frecuentemente se quiere definir una función que se aplique solamente a objetos con una estructura determinada. Esto es muy sencillo si se usan patrones. He aquí un ejemplo.
Una lista con algunos objetos enmarcados (Framed):
In[17]:= |
Out[17]= |
Ahora, se define una función que sea solamente aplicable a objetos enmarcados:
In[18]:= |
Resalte con “highlight” cada uno de los elementos de la lista; la función sabe lo que debe hacer cuando se encuentra con un elemento enmarcado:
In[19]:= |
Out[19]= |
La definición que sigue se aplica a cualquier cosa que tenga el encabezado List:
In[20]:= |
Y ya no es necesario usar /@:
In[21]:= |
Out[21]= |
De un caso general para usarse cuando no es aplicable ninguno de los casos especiales:
In[22]:= |
Lo anterior usa los casos especiales cuando se puede y, cuando no es así, se aplica el caso general:
In[23]:= |
Out[23]= |
Nota: En estos ejercicios se definen funciones, así que no hay que olvidarse de usar Clear para borrar las definiciones al terminar cada ejercicio.
No expected output
Many possible solutions of the form _:=_ or _=_
40.2Defina una función poly que tome un entero y presente la imagen de un polígono regular, con ese número de lados y de color naranja. »
No expected output
Many possible solutions of the form _:=_ or _=_
No expected output
Many possible solutions of the form _:=_ or _=_
40.4Cree una función f que tome dos argumentos y dé el resultado de multiplicarlos y dividir su producto por su suma. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.5Defina una función f que tome una lista de dos elementos y genere la lista de su suma, su diferencia y la razón entre ellos. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.6Defina una función evenodd que dé Black si su argumento es par, y White si no lo es, y además que resulte en Red si su argumento es 0. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.7Defina una función f de tres argumentos, donde los últimos dos se sumen cuando el primero es 1; se multipliquen si es 2, y se eleven a una potencia si es 3. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.8Defina una función Fibonacci f, con f[0] y f[1] iguales a 1 y, para n entero, f[n] sea la suma de f[n-1] y f[n-2]. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.9Cree una función llamada animal que tome una cadena de caracteres, y proporcione la foto de un animal con ese nombre. »
No expected output
Many possible solutions of the form _:=_ or _=_
40.10Defina una función nearwords que tome una cadena de caracteres y un entero n, y dé las n palabras de WordList[ ] más cercanas a la cadena dada. »
No expected output
Many possible solutions of the form _:=_ or _=_
¿Qué tipo de patrón puede usarse en la definición de una función?
Absolutamente el patrón que se desee, incluyendo aquellos cuyo encabezado también sea un patrón.
Use ?f para ver las definiciones de f.
¿Cómo se puede modificar una definición ya existente para alguna función?
Simplemente se da una definición nueva para el mismo patrón. Y se usa Clear para desechar todas las definiciones.
¿Cómo se ordenan las diferentes definiciones que pueda haber de una función determinada?
Normalmente, de las más específicas a las menos específicas. Si hay definiciones que no puedan ordenarse de acuerdo con eso, se ponen antes las que se hayan hecho antes. Al usar las definiciones, las que se hicieron primero se prueban primero. ?f muestra cómo están ordenadas las definiciones hechas para f.
Por lo general, sí. Sin embargo, casi siempre hay que especificar Unprotect[Max], por ejemplo. Así, las definiciones que se añadan, se usarán con preferencia sobre las nativas. Algunas funciones, tales como Plus, son tan fundamentales que el sistema las bloquea y mantiene en estado protegido. Aun en ese caso, pueden hacerse definiciones con “valor ascendente” asociadas con estructuras determinadas de los argumentos.
¿Se puede hacer programación orientada a objetos en Wolfram Language?
Se puede hacer una generalización simbólica de la programación orientada a objetos. Dado un objeto “tipo” t, se quieren hacer definiciones, p.ej., para f[t[...]] y g[t[...]]. Pueden asociarse esas definiciones con t diciendo t/:f[t[...]]= ... En Wolfram Language, esto se conoce como la definición de un valor ascendente para t.
En algunas ocasiones. f[n_]=n^2 funciona correctamente, ya que el lado derecho no se evalúa al hacer la asignación. f[n_]=Now y f[n_]:=Now darán resultados diferentes. Y, en muchos casos, el lado derecho no puede evaluarse correctamente hasta que se den los argumentos específicos.
¿Cómo se pueden compartir definiciones de funciones con otras personas?
¡Simplemente se les envía el código! Una manera conveniente de hacerlo es a través de la nube, usando CloudSave y CloudGet, como se verá en la Sección 43.
- Muchos lenguajes de bajo nivel requieren que los argumentos de las funciones tengan tipos estáticos de argumentos (ej., enteros, reales, cadenas de caracteres). Otros lenguajes permiten la asignación dinámica de tipos, donde los argumentos pueden ser cualquiera de algún conjunto determinado de tipos. Esto se ha generalizado en Wolfram Language permitiendo que los argumentos estén definidos mediante estructuras simbólicas arbitrarias.
- El tener un patrón tal como {x_, y_} en la definición de una función permite una desestructuración inmediata y conveniente del argumento de la función.
- Las definiciones pueden asociarse con el encabezado de una función (“valores descendentes”), con los encabezados de sus argumentos(“valores ascendentes”) o con el encabezado del encabezado, etc. (“subvalores”). Los valores ascendentes son, de hecho, una generalización de los métodos en los lenguajes orientados a objetos.
- f=(#^2&) y f[n_]:=n^2 son dos formas de definir una función que dan, por ejemplo, el mismo resultado para f[10]. Las definiciones de funciones puras suelen ser más fáciles de combinarse con otras, aunque sean más burdas en el manejo de las estructuras de los argumentos.