<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Il y a quelques années, je travaillais sur la construction d'un script pour générer automatiquement un plan d'échantillonnage pour une analyse de systèmes de mesure de style attribut. Tout se passait bien, jusqu'à ce que je rencontre un gros problème : comment faire en sorte que le script affiche une fenêtre pour générer la liste principale "Pass/Fail" des pièces utilisées, si le nombre de pièces était choisi au moment de l'exécution ? Maintenant, vous pensez peut-être déjà à un moyen simple de le faire. Cependant, je suis toujours fier de la méthode que j'ai mise au point, et je la partagerai dans cet article de blog.
Cachées dans la partie Programmation de l'index de script JSL se trouvent 2 entrées apparemment anodines : Eval et Parse. Ces fonctions permettent à un scripteur astucieux d'exécuter une chaîne comme s'il s'agissait d'un morceau de code. Être capable de faire cela a des implications stupéfiantes. Cela peut également résoudre mon problème de plus tôt.
Creusons en créant un script simple :
//section 1:
//obtenir les critères de réussite/échec pour une partie
// initialise certaines variables
je = 1 ;
listeParties = {} ;
//construire une fenêtre modale pour obtenir des critères
Nouvelle fenetre ( "Obtenir la liste réussite/échec" ,
<< Modal ,
H Zone de liste (
Zone de liste V (
Boîte de programmation ( 2 ,
Zone de texte ( carboniser ( je )) , listeParties [ je ] = Zone d'édition de texte ( "Passer" ) ,
Boîte à boutons ( "D'ACCORD" , listeParties [ je ] = listeParties [ je ] << Obtenir du texte ; ) , Boîte à boutons ( "Annuler" )
)
)
)
) ;
// regarde la liste
montrer ( listeParties [ je ]) ;
Assurez-vous que le journal s'affiche, puis exécutez ce script. Le script lui-même affiche une fenêtre et demande, pour une seule partie, si la partie est un "Pass" ou un "Fail". Lorsque vous appuyez sur le bouton OK, le texte qui se trouve dans la fenêtre est transmis à l'i e emplacement dans la liste listParts et listParts est affiché dans le journal. Stocker les résultats dans une liste d'un seul élément semble un peu idiot pour l'instant, mais cela a du sens lorsque nous avons plus d'une partie pour laquelle stocker les critères de réussite/échec. Voir l'exemple ci-dessous, pour voir à quoi ressemble le script pour 3 parties :
//section 2:
// répétition du script ci-dessus, mais en saisissant les critères pour 3 parties
je = 1 ;
listeParties = {} ;
Nouvelle fenetre ( "Obtenir la liste réussite/échec" ,
<< Modal ,
H Zone de liste (
Zone de liste V (
Boîte de programmation ( 2 ,
Zone de texte ( carboniser ( 1 )) , listeParties [ 1 ] = Zone d'édition de texte ( "Passer" ) ,
Zone de texte ( carboniser ( 2 )) , listeParties [ 2 ] = Zone d'édition de texte ( "Passer" ) ,
Zone de texte ( carboniser ( 3 )) , listeParties [ 3 ] = Zone d'édition de texte ( "Passer" ) ,
Boîte à boutons ( "D'ACCORD" , pour ( je = 1 , je <= 3 , je ++, listeParties [ je ] = listeParties [ je ] << Obtenir du texte ; )) , Boîte à boutons ( "Annuler" )
)
)
)
) ;
montrer ( listeParties ) ;
Mais, nous n'avons pas encore résolu le problème. Comment pouvons-nous faire en sorte que ce script affiche un nombre dynamique de zones de texte, basé sur un nombre arbitraire de parties, qui n'est connu qu'après le démarrage du script et qui pourrait être différent à chaque fois que le script est exécuté ? Entrez Eval et Parse, les prodiges susmentionnés, à la rescousse. Jetez un oeil au code suivant :
//section 3:
// déterminer le nombre de pièces
Nouvelle fenetre ( « Combien de pièces ? » ,
<< Modal ,
bec = Zone d'édition de nombre ( dix ) ,
Boîte à boutons ( "D'ACCORD" , numParts = bec << Obtenir ; )
) ;
montrer ( numParts ) ;
listeParties = {} ;
//Construire la première partie du script pour la fenêtre modale
//Séquence de caractères d'échappement pour " est \!"
un = "
Nouvelle fenêtre(\!"Obtenir la liste réussite/échec\!",
<
H Zone de liste(
Zone de liste V(
Boîte de programmation( 2,
" ;
//for loop crée une deuxième partie, qui construit autant de zones de saisie qu'il y a de parties
// || est le raccourci pour concaténer
b = "" ;
pour ( je = 1 , je <= numParts , je ++,
b1 = carboniser ( "Zone de texte(car(" || carboniser ( je ) || ")), listeParties[" || carboniser ( je ) || "] = Zone d'édition de texte (\!"Passer\!")," ) ;
b = b || b1 ;
) ;
//construit la dernière partie du script pour la fenêtre modale
c = "
Button Box(\!"OK\!", for (i = 1, i <=numParts, i++, listParts = listeParties << Obtenir le texte
), Boîte à boutons (\!"Annuler\!")
)
)
)
)
" ;
//combine des parties de script et exécute
d = un || b || c ;
eval ( analyser ( d )) ;
// regarde ce qui a été créé
montrer ( d ) ;
montrer ( listeParties ) ;
Tout d'abord, il y a une section pour demander à l'utilisateur combien de pièces, qui est stockée dans numParts. Ensuite, le script crée trois chaînes distinctes qui ressemblent étrangement à JSL, sauf qu'elles sont toutes en violet. La première chaîne est juste une copie exacte (avec un code spécial pour que les guillemets ne terminent pas la chaîne) du script d'avant, jusqu'à la partie où les zones de texte sont insérées. La deuxième partie est une boucle for pour construire une chaîne composée du nombre de parties saisies précédemment (numParts) répétitions de zones de texte. La troisième section est les derniers morceaux du script d'avant.
Une fois cette chaîne créée, nous les combinons ( d = un || b || c ; ), puis utilisez le eval ( analyser ( d )) ; pour évaluer ce qui se passe lorsque JMP analyse la chaîne d (notre chaîne créée dynamiquement avec un nombre ajustable de zones de texte) comme si la chaîne d était un script JSL, et pas seulement une chaîne. Regardez le journal pour voir à la fois la commande super longue pour afficher de nombreuses zones de texte, ainsi que la liste des réussites/échecs qui a été générée (affichée ci-dessous si vous acceptez simplement les valeurs par défaut) :
ré = "
Nouvelle fenêtre(\!"Obtenir la liste réussite/échec\!",
<
H Zone de liste(
Zone de liste V(
Boîte de programmation( 2,
Zone de texte(car(1)), listParts[1] = Zone d'édition de texte(\!"Pass\!"), Zone de texte(char(2)), listParts[2] = Zone d'édition de texte(\!"Pass\ !"), Zone de texte (car(3)), listParts[3] = Zone d'édition de texte (\!"Pass\!"), Zone de texte (car(4)), listParts[4] = Zone d'édition de texte (\ !"Pass\!"),Text Box(char(5)), listParts[5] = Texte Edit Box(\!"Pass\!"),Text Box(char(6)), listParts[6] = Texte Edit Box(\!"Pass\!"),Text Box(char(7)), listParts[7] = Texte Edit Box(\!"Pass\!"),Text Box(char(8)), listParts[ 8] = Zone d'édition de texte(\!"Pass\!"),Zone de texte(car(9)), listParts[9] = Zone d'édition de texte(\!"Pass\!"),Zone de texte(char(10) ), listParts[10] = Zone d'édition de texte(\!"Pass\!"),
Button Box(\!"OK\!", for (i = 1, i <=numParts, i++, listParts = listeParties << Obtenir du texte
), Boîte à boutons(\!"Annuler\!")
)
)
)
)
" ;
listParts = {"Pass", "Pass", "Pass", "Pass", "Pass", "Pass", "Pass", "Pass", "Pass", "Pass"} ;
Prenez un moment pour réfléchir aux implications, ici. Avec ces concepts, vous pouvez créer du code qui s'ajuste de lui-même, puis s'exécute de lui-même. Les scripts dynamiques, autoréférentiels, récursifs et fous pourraient n'être qu'un début. Avec suffisamment de temps et de patience, vous pourriez probablement utiliser ce concept pour créer Skynet. À la réflexion, ce n'est peut-être pas une si bonne idée…
Le problème ici est que <
Vous ne pouvez pas envoyer de messages à des choses qui ne sont pas des objets, et les listes ne sont pas des objets au même sens que, disons, les tables de données. J'ai récemment corrigé un bogue de longue date dans l'un des compléments de mes clients en réalisant que j'avais essayé de faire
list<<INSERT item=""></INSERT>
au lieu de
insert item(list, item)
Je pense que là où beaucoup d'entre nous sont confus, c'est que les tableaux associatifs SONT des objets qui peuvent prendre des <
map=associative array(:Name, :Weight);
map<<INSERT item=""></INSERT>
Revenons à la question posée, je ne sais pas vraiment pourquoi l'exemple utilise listparts[i]<Re : Eval (), Parse () et Recursion, une aventure dans la méta-programmation
Super exemple, merci @Jed_Campbell .J'ai un problème que je n'arrive pas à résoudre.J'obtiens une erreur : Send Expects Scriptable Object in access or evaluation of 'List' , {/*###*/"Pass", "Fail"}
Je pense que c'est cette commande d'envoi qui cause le problème.Je n'obtiens l'erreur que si je choisis plus d'un numéro.Des pensées?
listParts = listParts << Get Text;