No
realmente la respuesta a la pregunta original, pero me di cuenta de que mucha gente se interesó en #0
cosas, así here pongo un par de ejemplos no triviales, esperamos que se sé útil.
En cuanto a la afirmación de que para funciones anidadas se deben usar funciones con argumentos nombrados: aunque esto es cierto en general, siempre se debe tener en cuenta que el ámbito léxico para funciones puras (y generalmente) se emula en Mathematica y se puede romper . Ejemplo:
In[71]:=
Clear[f,g];
f[fun_,val_]:=val/.x_:>fun[x];
g[fn_,val_]:=f[Function[{x},fn[#1^#2==x&,{x,x}]],val];
g[Array,3]
During evaluation of In[71]:= Function::flpar: Parameter specification {3} in
Function[{3},Array[#1^#2==3&,{3,3}]] should be a symbol or a list of symbols. >>
During evaluation of In[71]:= Function::flpar: Parameter specification {3} in
Function[{3},Array[#1^#2==3&,{3,3}]] should be a symbol or a list of symbols. >>
Out[74]= Function[{3},Array[#1^#2==3&,{3,3}]][3]
Este comportamiento tiene que ver con la naturaleza intrusiva de sustituciones de reglas - es decir, con el hecho de que Rule
y RuleDelayed
no se preocupan por posibles colisiones de nombres entre en construcciones de alcance que pueden estar presentes en expresiones sujetas a aplicaciones de reglas y nombres de variables de patrones en reglas. Lo que empeora las cosas es que g
y f
funcionan completamente bien cuando se toman por separado. Es cuando se mezclan, que ocurre este enredo, y solo porque tuvimos la mala suerte de usar la misma variable de patrón x
en el cuerpo de f
, como en una función pura. Esto hace que estos errores sean muy difíciles de detectar, mientras que tales situaciones suceden a veces en la práctica, por lo que recomendaría no pasar funciones puras con argumentos con nombre como parámetros en funciones de orden superior definidas a través de patrones.
Editar:
Ampliando un poco en la emulación del ámbito léxico.Lo que quiero decir es que, por ejemplo, cuando creo una función pura (que es una construcción de alcance léxico que une los nombres de las variables en su cuerpo a los valores de los parámetros pasados), espero que no pueda alterar esta unión después de haber creado una función. Esto significa que, no importa dónde use Function[x,body-that-depends-on-x]
, debería poder tratarlo como una caja negra con parámetros de entrada y salidas resultantes. Pero, en Mathematica, Function[x,x^2]
(por ejemplo) también es una expresión, y como tal, se puede modificar como cualquier otra expresión. Por ejemplo:
In[75]:=
x = 5;
Function[Evaluate[x],x^2]
During evaluation of In[75]:= Function::flpar: Parameter specification 5 in Function[5,x^2] should
be a symbol or a list of symbols. >>
Out[76]= Function[5,x^2]
o, aún más simple (la esencia de mi advertencia anterior):
In[79]:= 1/.x_:>Function[x,x^2]
During evaluation of In[79]:= Function::flpar: Parameter specification 1 in Function[1,1^2] should
be a symbol or a list of symbols. >>
Out[79]= Function[1,1^2]
Me picaron por esta última comportamiento algunas veces muy dolorosa. Este comportamiento también fue notado por @WReach en la parte inferior de su publicación en la página this; obviamente, él tuvo experiencias similares. Hay otras formas de romper el alcance, basadas en el conocimiento exacto de cómo Mathematica cambia el nombre de las variables durante los conflictos, pero en la práctica son comparativamente menos nocivas. En general, no creo que este tipo de cosas se puedan evitar si se insiste en el nivel de transparencia representado por las expresiones de Mathematica. Simplemente parece ser "demasiado transparente" para funciones puras (y construcciones de ámbito léxico en general), pero por otro lado también tiene su uso, por ejemplo, podemos forjar una función pura en tiempo de ejecución como esta:
In[82]:= Block[{x},[email protected]@{x,Integrate[HermiteH[10,y],{y,0,x}]}]
Out[82]= Function[x,-30240 x+100800 x^3-80640 x^5+23040 x^7-2560 x^9+(1024 x^11)/11]
Donde la integral se calcula solo una vez, en el tiempo de definición (también podría usarse Evaluate
). Entonces, esto parece una compensación. De esta forma, la abstracción funcional está mejor integrada en Mathematica, pero tiene fugas, como lo señaló @WReach. Alternativamente, podría haber sido "resistente al agua", pero quizás por el precio de estar menos expuesto. Esta fue claramente una decisión de diseño.
Esto me hizo mirar los documentos para 'Slot' (+1). La definición de función recursiva y pura para el factorial: 'f = Si [# 1 == 1, 1, # 1 # 0 [# 1 - 1]] &' ¡es bastante astuto! – Simon
@ Simon Yep. Ese # 0 también me preocupaba: D –
@Simon, nunca antes había leído la documentación de Slot. El '# 0' es definitivamente molesto, y potencialmente muy útil. – rcollyer