Quando la gente dice "X non compone", ciò che significano per "comporre" in realtà significa solo "mettere insieme", e che e come hai messo loro insieme possono essere molto diversi, a seconda di cosa sia esattamente "X".
Inoltre, quando dicono "non compone", possono significare cose leggermente diverse:
- Non puoi mettere insieme due X, punto.
- puoi mettere insieme due X, ma il risultato potrebbe non essere una X (IOW: X non è chiuso nella composizione .)
- Puoi mettere insieme due X, ma la X risultante potrebbe non funzionare nel modo in cui ti aspetti.
Un esempio per # 1 è parser con scanner / lexer. Potresti sentire la frase "scanner / lessici non compongono". Questo in realtà non è vero. Quello che intendono è "parser che usa uno stadio di lexing separato non comporre".
Perché vorresti comporre i parser? Bene, immagina di essere un fornitore IDE come JetBrains, Eclipse Foundation, Microsoft o Embarcadero e vuoi creare un IDE per un framework web. Nel tipico sviluppo web, mescoliamo spesso le lingue. Hai file HTML con <script>
elementi contenenti ECMAScript e <style>
elementi contenenti CSS. Sono presenti file modello contenenti HTML, alcuni linguaggi di programmazione e alcuni metasintassi del linguaggio template. Non si desidera scrivere diversi evidenziatori di sintassi per "Python", "Python incorporato in un modello", "CSS", "CSS in HTML", "ECMASCript", "ECMAScript in HTML", "HTML", "HTML all'interno un modello ", e così via e così via. Si desidera scrivere un evidenziatore di sintassi per Python, uno per HTML, uno per il linguaggio del modello e quindi comporre i tre in un evidenziatore di sintassi per un file modello.
Tuttavia, un lexer analizza l'intero file in un flusso di token, il che ha senso solo per quella lingua. Il parser per l'altra lingua non può funzionare con i token che il lexer lo passa. Ad esempio, i parser Python sono tipicamente scritti in modo tale che il lexer tenga traccia dei rientri e inietta i token INDENT
e DEDENT
nel flusso di token, consentendo così al parser di essere privo di contesto anche se la sintassi di Python in realtà non è 't. Un lexer HTML tuttavia ignorerà completamente gli spazi bianchi, poiché non ha alcun significato in HTML.
Un parser senza scanner, tuttavia, che legge semplicemente caratteri, può trasferire il flusso di caratteri a un parser diverso, che può quindi restituirlo, semplificando così la composizione.
Un esempio per # 2 è stringhe con query SQL in esse. È possibile avere due stringhe, ognuna delle quali contiene una query SQL sintatticamente corretta, ma se si concatenano le due stringhe, il risultato potrebbe non essere una query SQL sintatticamente corretta. Ecco perché abbiamo algebre di query come ARel
, che fanno componi.
Le serrature sono un esempio di # 3. Se hai due programmi con blocchi e li combini in un singolo programma, hai ancora un programma con blocchi, ma anche se i due programmi originali erano completamente corretti, privi di deadlock e gare, il programma risultante non ha necessariamente questo proprietà. L'utilizzo corretto dei blocchi è una proprietà globale dell'intero programma e una proprietà che non viene conservata durante la composizione dei programmi. Ciò è diverso, ad esempio, dalle transazioni, che fanno compongono. Un programma che utilizza correttamente le transazioni può essere composto con un altro programma di questo tipo e produrrà un programma combinato che utilizza correttamente le transazioni.