Lorsque les gens disent "X ne compose pas", ce qu'ils entendent par "composer" signifie en réalité simplement "assemblé", et quoi et comment vous les assemblez peut être très différent, en fonction de ce que "X" est exactement.
En outre, quand ils disent "ne compose pas", ils peuvent signifier des choses légèrement différentes:
- Vous ne pouvez pas mettre deux X ensemble, tout simplement.
- Vous pouvez mettre deux X ensemble, mais le résultat peut ne pas être un X (IOW: X n'est pas fermé sous composition .)
- Vous pouvez assembler deux X, mais le résultat X risque de ne pas fonctionner comme prévu.
Un exemple pour # 1 est les analyseurs avec les scanners / lexers. Vous pourriez entendre la phrase "les scanners / lexeurs ne composent pas". Ce n'est pas vraiment vrai. Ce qu'ils veulent dire, c'est "un analyseur qui utilise une étape de lexing distincte ne compose pas".
Pourquoi voudriez-vous composer des analyseurs? Imaginez que vous soyez un fournisseur IDE tel que JetBrains, Eclipse Foundation, Microsoft ou Embarcadero, et que vous souhaitez créer un environnement de développement intégré (IDE) pour un framework Web. Dans le développement Web typique, nous mélangeons souvent des langues. Vous avez des fichiers HTML avec des <script>
éléments contenant ECMAScript et<style>
éléments contenant CSS. Vous avez des fichiers de modèle contenant HTML, un langage de programmation et une métasyntaxe de langage de modèle. Vous ne voulez pas écrire différents surligneurs de syntaxe pour "Python", "Python incorporé dans un modèle", "CSS", "CSS dans HTML", "ECMASCript", "ECMAScript dans HTML", "HTML", "HTML dans un modèle ", et ainsi de suite. Vous souhaitez écrire un surligneur de syntaxe pour Python, un pour HTML, un pour le langage de modèle, puis composer les trois en un surligneur de syntaxe pour un fichier de modèle.
Cependant, un lexer analyse l'intégralité du fichier dans un flux de jetons, ce qui n'a de sens que pour cette langue. L'analyseur de l'autre langue ne peut pas fonctionner avec les jetons que le lexer le transmet. Par exemple, les analyseurs syntaxiques Python sont généralement écrits de manière à ce que le lexer garde une trace de l'indentation et injecte des faux INDENT
et des DEDENT
jetons dans le flux de jetons, permettant ainsi à l'analyseur d'être sans contexte, même si la syntaxe de Python ne l'est pas. Un lexer HTML ignorera toutefois complètement les espaces, car il n'a aucune signification en HTML.
Cependant, un analyseur sans scanner, qui lit simplement des caractères, peut transmettre le flux de caractères à un analyseur différent, qui peut ensuite le restituer, ce qui les rend beaucoup plus faciles à composer.
Un exemple pour # 2 est les chaînes contenant des requêtes SQL. Vous pouvez avoir deux chaînes, chacune contenant une requête SQL syntaxiquement correcte, mais si vous concaténez les deux chaînes, le résultat risque de ne pas être une requête SQL syntaxiquement correcte. Voilà pourquoi nous avons requête algèbres comme ARel
, qui font Compose.
Les serrures sont un exemple de # 3. Si vous avez deux programmes avec des verrous et que vous les combinez en un seul programme, vous avez toujours un programme avec des verrous, mais même si les deux programmes originaux étaient complètement corrects, sans impasses ni courses, le programme résultant ne possède pas nécessairement ce programme. propriété. L'utilisation correcte des verrous est une propriété globale de l'ensemble du programme et une propriété qui n'est pas conservée lorsque vous composez des programmes. Ceci est différent de, par exemple, des transactions qui font Compose. Un programme qui utilise correctement les transactions peut être composé avec un autre programme de ce type et donnera un programme combiné qui utilise correctement les transactions.