Re: Local predeterminado vs Declaración explícita de localesMe gusta la lista de declaraciones locales explícitas. Cuando pierdo uno, aterriza en el espacio de nombres global y showglobals() lo identifica.Haga espuma, enjuague, repita hasta que el espacio global permanezca limpio.
Re: Local predeterminado vs Declaración explícita de locales¿Puedo preguntar cuál es su flujo de trabajo para verificar esto? ¿Agrega "Show Globals ()" al final de sus funciones durante el desarrollo y verifica manualmente que no haya agregado nada involuntario al espacio de nombres global? ¿O es algo que puede hacer cumplir con las pruebas?
Pregunta secundaria: ¿Es Show Globals o Show Symbols lo que debería usar? No veo ningún resultado de Show Globals incluso cuando omito intencionalmente las variables locales de mis funciones, pero cuando uso Show Symbols obtengo tantos resultados que no notaría ninguna lista nueva de todos modos.
Si ayuda, tengo activado el modo "Nombres predeterminados aquí" en todos mis archivos de script.
Re: Local predeterminado vs Declaración explícita de localesMi flujo de trabajo en el pasado es no usar Nombres predeterminados hasta aquí y simplemente mantener limpio el espacio de nombres global. Show Globals() probablemente nunca vea nada si siempre está usando Names Default To Here. Show Symbols() es ruidoso porque informa información a través de la pila de llamadas si lo usa en una función profundamente anidada. Aquí está mi ejemplo de flujo de trabajo, reelaborado para usar Nombres predeterminados hasta aquí y Mostrar símbolos. Ejecútelo, tal como está, y no tendrá fugas. comente la línea 17 (g3) y arrojará un error porque g3 se coloca en el espacio de nombres 'aquí'. El uso de g2 en el ejemplo resalta un problema feo; locales predeterminados resuelve ese problema pero agrega problemas que anotó. Podría intentar volver a cambiar a Local predeterminado en un proyecto futuro. Creo que podría ser una opción más segura para mí; Es más probable que deje una variable fuera de los locales explícitos que leer una variable antes de escribirla.
Creo que estás tratando de hacer una prueba más detallada que yo; Solo pruebo (globales o aquí) al final. Es posible que pueda usar algunas de estas ideas si necesita probar la fuga de espacio de nombres en cada función.
// **** you will probably need to restart JMP to really understand each change you make. ****
xyzzy = "before names default to here"; // this goes into globals. If you run again it goes into 'here'.
Names Default To Here( 1 ); // takes effect when executed
New Namespace( // don't put the functions in the here namespace, keep them in appDemo.
"appDemo" // this keeps the here namespace free of voluminous function definitions.
);
appDemo:originalLeakState = Log Capture( Show Symbols() ); // remember the original state
appDemo:f1 = Function( {p1}, // parameter list
{
//g2, // <<<< comment this use f2's local
g3, // <<<< comment this to make a leak
g1}, // local list
Write( "\!ng2=", g2 );
g1 = 1; // very local to this function
g2 = 2; // not local, in this example it is local to f2, a bug if unintentional
g3 = 3; // not local, lands in the 'here'
);
appDemo:f2 = Function( {p2},
{g2},
g2 = 42; // this will be over written by f1
appDemo:f1( p2 );
);
appDemo:f2( "x" );
// if you call f1 from here, the here:g2 gets written
// g2 = 142;
// appDemo:f1( "x" );
// a test might look like this
If( Log Capture( Show Symbols() ) != appDemo:originalLeakState,
Write( "\!n=============leak report==============" );
Show Symbols();
Throw( "variable namespace leaks, see log!" );
,
Write( "\!n========= no change to symbols =======" );
If( Length( appDemo:originalLeakState ),
Write(
"\!n========= original leak state: =======",
appDemo:originalLeakState
)
);
);Re: Local predeterminado vs Declaración explícita de locales¡Gracias esto es muy útil! Creo que debería poder usar algo de lo que ha escrito aquí para escribir algunas comprobaciones automáticas que aseguren que nada se filtre.
Re: Local predeterminado vs Declaración explícita de localesTambién hay algo raro en DEFAULT LOCAL.En realidad, lee el script y crea las asignaciones locales en función de su interpretación de las variables que se están creando.Hay más de unas pocas maneras de arruinar esto. El que probablemente veo con más frecuencia de las personas es cuando intentan crear dinámicamente un nombre de variable.Lo que yo diría que no es genial de hacer y tampoco podrías decirlo explícitamente, así que es más o menos lo mismo.
Names default to here(1);
f = function({},
{DEFAULT LOCAL},
x = 14;
Eval(Parse("x"||char(x)||"=28"));//not that anyone should ever do this BUT ...
return(x);
);
f();
namespace("here"); // notice how x14 is in the here namespace
/*
New Namespace(
{
f = Function( {},
{Default Local},
x = 14;
Eval( Parse( "x" || Char( x ) || "=28" ) );
Return( x );
),
x14 = 28
}
)
/*Re: Local predeterminado vs Declaración explícita de localesPara cualquier futuro lector, finalmente escribí un asistente de prueba que uso para hacer cumplir que todos los locales se declaren explícitamente
/*
* Test that `invocation` does not add any variables to the Here namespace. It is important that
* this test be run first, else whatever variables may leak will leak before running this test and
* so they will already be present in `hereVariablesBefore`.
*
* Example:
* someFunction1 = Function( {}, {}, leakedVar = 1);
* someFunction2 = Function( {}, {safeVar}, safeVar = 1);
* assertNoLeakedVariables( Function( {}, {}, someFunction1() ) ); // Fails
* assertNoLeakedVariables( Function( {}, {}, someFunction2() ) ); // Passes
*/
assertNoLeakedVariables = Function( {invocation},
{hereVariablesBefore, hereVariablesAfter},
Try(
// Declare both of these in advance, because otherwise the key `hereVariablesBefore` will not be
// present in `hereVariablesBefore` and it makes the assertion confusing.
hereVariablesBefore = .;
hereVariablesAfter = .;
hereVariablesBefore = Namespace( "here" ) << Get Keys;
invocation();
hereVariablesAfter = Namespace( "here" ) << Get Keys;
UT Assert( Expr( Length( hereVariablesBefore ) ), Length( hereVariablesAfter ) );
If( Length( hereVariablesBefore ) != Length( hereVariablesAfter ),
showLeakedVariableNames( hereVariablesBefore, hereVariablesAfter )
);
,
UT Assert( exception_msg, "" )
)
);Re: Local predeterminado vs Declaración explícita de localesEsto me ha surgido con bastante frecuencia; puede ser muy frustrante:
este script elimina los nombres (los nombres escapan del alcance local de la función):
Names Default to Here( 1 );
some expr = Expr(
a = 4;
b = 5;
g = 6;
);
f = Function( {input expr},
{Default Local},
Print( "running expr" );
input expr
);
f( Name Expr( some expr ) );
show( a, b, g )Aquí hay una solución, pero el problema con esta solución es que técnicamente son dos llamadas de función (cuenta como 2 elementos de pila, por lo que alcanzará el límite de 225 pilas más rápido)
Names Default to Here( 1 );
some expr = Expr(
a = 4;
b = 5;
g = 6;
Show( Eval List( {a, b, g} ) );
);
f = Function( {input expr},
{Default Local},
Print( "running expr" );
Eval( Eval Expr(
Local( {Default Local},
Expr( Name Expr( input expr ) )
)
) );
1
);
f( Name Expr( some expr ) );
show( a, b, g )Sería bueno si la directiva "Local predeterminado" no fuera una directiva de tiempo de análisis sino una marca de tiempo de ejecución, pero tal vez lo que está sucediendo es que la resolución de nombres se realiza en el tiempo de análisis, lo que hace que las reglas de búsqueda de nombres en tiempo de ejecución sean discutibles. .
Local por defecto vs Declaración explícita de localesHola, estoy tratando de entender cuál es la mejor manera de limitar mi riesgo con respecto al alcance local de las funciones. Según tengo entendido, mis opciones para limitar el potencial de contaminar el alcance Here desde dentro de la ejecución de una función son declarar mis variables locales o usar Default Local. Sin embargo, cada uno de estos tiene algunos problemas:
Local predeterminado:
- Los valores de referencia pueden depender del contexto, ya que los nombres que no se han definido localmente recurren a Aquí y luego posiblemente (si Nombres predeterminados a aquí está desactivado) Global y luego a la tabla actual. Como se indica en los documentos, esto puede significar que el comportamiento es menos predecible ya que los valores dependen del contexto.
Declaración explícita:
- Los valores de referencia pueden depender del contexto, ya que los nombres aún usan este comportamiento alternativo hasta que se declaran si no se declaran en los nombres locales.
- Las asignaciones pueden filtrarse accidentalmente en el ámbito Aquí. Es decir, si un nombre que pretende ser local se omite de las declaraciones de nombres locales, contaminará el ámbito Here circundante.
- En general, esta contaminación de alcance externo es difícil de rastrear.
- Por ejemplo, si llama a una función en un For donde usa "i" como un iterador y esa función también tiene un For que usa i y no puede declararlo como local, esto afectará su bucle For externo. De acuerdo, este es un error obvio del programador, pero es fácil de hacer y difícil de depurar.
En mi opinión, la opción ideal sería poder declarar algo como "Local estricto", que siempre trataría los nombres no calificados (tanto al asignar valores como al hacer referencia a valores) como ámbitos locales y circundantes que solo serían accesibles con nombres calificados. Esto me permitiría no arriesgarme a contaminar los ámbitos circundantes y me obligaría a declarar cuándo estoy dependiendo de esos ámbitos, limitando así la contaminación local de los ámbitos circundantes.
Modelado Estadístico AvanzadoInvestigación del Consumidor y del MercadoAcceso a los datosExploración y visualización de datosLa personalización en masaRe: Declaración local predeterminada frente a declaración explícita de variables localesRespecto al “Flujo de trabajo”: un pequeño ayudante como este #NamespaceInspector será de gran ayuda para realizar un seguimiento de las variables.
¿Aparecen en un espacio de nombres aquí o en un espacio de nombres local?
Una vez finalizada la depuración, lo subiré como complemento...
Este vídeo se está procesando actualmente. Inténtalo de nuevo en unos minutos.
(ver en Mis Videos)