<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Hace unos años, estaba trabajando en la creación de un script para generar automáticamente un plan de muestreo para un análisis de sistemas de medición de estilo de atributos. Todo iba bien, hasta que me encontré con un gran problema: ¿cómo podía hacer que la secuencia de comandos abriera una ventana para generar la lista maestra de "Aprobado/Fallado" de las piezas que se usaban, si la cantidad de piezas se elegía en tiempo de ejecución? Ahora, es posible que ya esté pensando en una manera fácil de hacer esto. Sin embargo, todavía estoy orgulloso del método que se me ocurrió, y lo compartiré en esta publicación de blog.
Escondidos en la parte de programación del índice de secuencias de comandos JSL hay 2 entradas aparentemente inocuas: Eval y Parse. Estas funciones permiten que un scripter astuto ejecute una cadena como si fuera una pieza de código. Ser capaz de hacer esto tiene implicaciones asombrosas. Hacer esto también puede resolver mi problema anterior.
Profundicemos construyendo un script simple:
//sección 1:
//obtener criterios de aprobación/reprobación para una parte
//inicializar algunas variables
i = 1 ;
listaPartes = {} ;
//construir ventana modal para obtener criterios
Nueva ventana ( "Obtener lista de aprobados/reprobados" ,
<< Modal ,
Cuadro de lista H (
Cuadro de lista V (
Cuadro de alineación ( 2 ,
Caja de texto ( carbonizarse ( i )) , listaPartes [ i ] = Cuadro de edición de texto ( "Aprobar" ) ,
Caja de botones ( "DE ACUERDO" , listaPartes [ i ] = listaPartes [ i ] << Obtener texto ; ) , Caja de botones ( "Cancelar" )
)
)
)
) ;
// mira la lista
espectáculo ( listaPartes [ i ]) ;
Asegúrese de mostrar el registro, luego ejecute este script. El guión en sí muestra una ventana y pregunta, solo para una parte, si la parte es "Pasa" o "Falla". Cuando se presiona el botón Aceptar, cualquier texto que esté en la ventana se pasa a la i el ubicación en la lista listParts y listParts se muestra en el registro. Almacenar los resultados en una lista de solo 1 elemento parece un poco tonto por ahora, pero tiene sentido cuando tenemos más de una parte para almacenar criterios de Pasa/Falla. Vea el ejemplo a continuación, para ver cómo se ve el script en 3 partes:
//sección 2:
//repetir el guión anterior, pero tomando criterios para 3 partes
i = 1 ;
listaPartes = {} ;
Nueva ventana ( "Obtener lista de aprobados/reprobados" ,
<< Modal ,
Cuadro de lista H (
Cuadro de lista V (
Cuadro de alineación ( 2 ,
Caja de texto ( carbonizarse ( 1 )) , listaPartes [ 1 ] = Cuadro de edición de texto ( "Aprobar" ) ,
Caja de texto ( carbonizarse ( 2 )) , listaPartes [ 2 ] = Cuadro de edición de texto ( "Aprobar" ) ,
Caja de texto ( carbonizarse ( 3 )) , listaPartes [ 3 ] = Cuadro de edición de texto ( "Aprobar" ) ,
Caja de botones ( "DE ACUERDO" , para ( i = 1 , i <= 3 , i ++, listaPartes [ i ] = listaPartes [ i ] << Obtener texto ; )) , Caja de botones ( "Cancelar" )
)
)
)
) ;
espectáculo ( listaPartes ) ;
Pero, no hemos resuelto el problema, todavía. ¿Cómo podemos hacer que esta secuencia de comandos muestre una cantidad dinámica de cuadros de texto, en función de una cantidad arbitraria de partes, que no se conoce hasta que la secuencia de comandos comienza a ejecutarse y podría ser diferente cada vez que se ejecuta la secuencia de comandos? Ingrese Eval y Parse, los niños prodigio antes mencionados, al rescate. Echa un vistazo al siguiente código:
//seccion 3:
// determina el numero de partes
Nueva ventana ( "¿Cuántas partes?" ,
<< Modal ,
Nebraska = Cuadro de edición de número ( 10 ) ,
Caja de botones ( "DE ACUERDO" , numParts = Nebraska << Conseguir ; )
) ;
espectáculo ( numParts ) ;
listaPartes = {} ;
// Construir la primera parte del script para la ventana modal
//Secuencia de caracteres de escape para " is \!"
a = "
Nueva ventana(\!"Obtenga la lista de Aprobados/Reprobados\!",
<
Cuadro de lista H(
Cuadro de lista V (
Cuadro de alineación (2,
" ;
// for loop crea una segunda parte, que crea tantos cuadros de entrada como partes haya
// || es el atajo para concatenar
b = "" ;
para ( i = 1 , i <= numParts , i ++,
b1 = carbonizarse ( "Cuadro de texto(char(" || carbonizarse ( i ) || ")), listParts[" || carbonizarse ( i ) || "] = Cuadro de edición de texto(\!"Pass\!")," ) ;
b = b || b1 ;
) ;
//construye la última parte del script para la ventana modal
C = "
Cuadro de botones(\!"OK\!", for (i = 1, i <=numParts, i++, listParts = listParts << Obtener texto;)), Cuadro de botones (\!"Cancelar\!")
)
)
)
)
" ;
//combina partes del script y ejecuta
d = a || b || C ;
evaluar ( analizar gramaticalmente ( d )) ;
// mira lo que fue creado
espectáculo ( d ) ;
espectáculo ( listaPartes ) ;
Primero, hay una sección para preguntarle al usuario cuántas partes, que se almacena en numParts. A continuación, el script crea tres cadenas separadas que se parecen sospechosamente a JSL, excepto que todas están en color púrpura. La primera cadena es solo una copia exacta (con algún código especial para que las comillas no terminen la cadena) del script anterior, hasta la parte donde se insertan los cuadros de texto. La segunda parte es un ciclo for para construir una cadena que consiste en la cantidad de partes que se ingresaron previamente (numParts) repeticiones de cuadros de texto. La tercera sección son los últimos fragmentos del guión de antes.
Una vez creada esta cadena, las combinamos ( d = a || b || C ; ), luego use el evaluar ( analizar gramaticalmente ( d )) ; para evaluar lo que sucede cuando JMP analiza la cadena d (nuestra cadena creada dinámicamente con un número ajustable de cuadros de texto) como si la cadena d fuera un script JSL, y no solo una cadena. Mire el registro para ver el comando súper largo para mostrar muchos cuadros de texto, así como la lista de Aprobado/Fallado que se generó (se muestra a continuación si solo acepta los valores predeterminados):
re = "
Nueva ventana(\!"Obtenga la lista de Aprobados/Reprobados\!",
<
Cuadro de lista H(
Cuadro de lista V (
Cuadro de alineación (2,
Cuadro de texto(char(1)), listParts[1] = Cuadro de edición de texto(\!"Pass\!"), Cuadro de texto(char(2)), listParts[2] = Cuadro de edición de texto(\!"Pass\ !"),Cuadro de texto(char(3)), listParts[3] = Cuadro de edición de texto(\!"Pass\!"),Cuadro de texto(char(4)), listParts[4] = Cuadro de edición de texto(\ !"Pass\!"),Cuadro de texto(char(5)), listParts[5] = Cuadro de edición de texto(\!"Pass\!"),Text Box(char(6)), listParts[6] = Texto Cuadro de edición(\!"Aprobado\!"),Cuadro de texto(char(7)), listParts[7] = Cuadro de edición de texto(\!"Aprobado\!"),Cuadro de texto(char(8)), listParts[ 8] = Cuadro de edición de texto(\!"Pass\!"), Cuadro de texto(char(9)), listParts[9] = Cuadro de edición de texto(\!"Pass\!"),Cuadro de texto(char(10) ), listParts[10] = Cuadro de edición de texto(\!"Pass\!"),
Cuadro de botones(\!"OK\!", for (i = 1, i <=numParts, i++, listParts = listParts << Obtener texto;)), Caja de botones(\!"Cancelar\!")
)
)
)
)
";
listParts = {"Pasó", "Pasó", "Pasó", "Pasó", "Pasó", "Pasó", "Pasó", "Pasó", "Pasó", "Pasó"};
Tómese un momento para pensar en las implicaciones, aquí. Con estos conceptos, puede crear código que se ajuste solo y luego se ejecute solo. Los scripts dinámicos, autorreferenciales, recursivos y locos podrían ser solo el comienzo. Con suficiente tiempo y paciencia, probablemente podría usar este concepto para crear Skynet. Pensándolo bien, tal vez esa no sea una buena idea...
El problema aquí es que <
No puede enviar mensajes a cosas que no son objetos, y las listas no son objetos en el mismo sentido que, por ejemplo, lo son las tablas de datos. Recientemente solucioné un error de larga data en uno de los complementos de mis clientes al darme cuenta de que había intentado hacer
list<<INSERT item=""></INSERT>
en lugar de
insert item(list, item)
Creo que donde muchos de nosotros nos confundimos es que las matrices asociativas SON objetos que pueden tomar <
map=associative array(:Name, :Weight);
map<<INSERT item=""></INSERT>
Volviendo a la pregunta en cuestión, no estoy muy seguro de por qué el ejemplo usa listparts[i]<Re: Eval (), Parse () y Recursion, una aventura en metaprogramación
Gran ejemplo, gracias. @Jed_Campbell .Tengo un problema que parece que no puedo resolver.Recibo un error: Enviar espera un objeto programable en el acceso o evaluación de 'Lista', {/*###*/"Pass", "Fail"}
Creo que es este comando de envío el que causa el problema.Solo recibo el error si elijo más de 1 número.¿Alguna idea?
listParts = listParts << Get Text;