Qual è il significato di "does not compose"?

33

Vedo molti testi, specialmente testi di programmazione funzionale, che affermano che certi concetti CS "non compongono" . Gli esempi sono: i blocchi non compongono, le monadi non compongono.

Ho avuto difficoltà a rintracciare esattamente il significato di questa frase. Quando penso alla composizione, penso sia alla composizione delle funzioni che all'aggregazione degli oggetti (come in "composizione dei favori sull'ereditarietà"), ma non sembra il senso in cui le persone lo stanno usando qui.

Qualcuno può spiegare cosa significa questa frase quando viene usata in espressioni come i due esempi sopra (vale a dire, serrature e monadi)?

    
posta Bill 17.07.2015 - 21:55
fonte

2 risposte

32

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:

  1. Non puoi mettere insieme due X, punto.
  2. puoi mettere insieme due X, ma il risultato potrebbe non essere una X (IOW: X non è chiuso nella composizione .)
  3. 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.

    
risposta data 18.07.2015 - 02:31
fonte
18

La componibilità significa che puoi combinare facilmente e in modo affidabile i componenti del programma per produrre componenti più grandi e funzionalità più complesse.

Alcune cose che aiutano a rendere i componenti più componibili:

  1. Idempotence. Una funzione idempotent produrrà sempre lo stesso output o gli stessi effetti collaterali, se chiamati più volte con gli stessi valori di parametro. Ciò migliora la componibilità perché il risultato di una chiamata di funzione è prevedibile.

  2. Trasparenza referenziale. Un'espressione referenzialmente trasparente valuterà sempre lo stesso risultato. Ciò migliora la componibilità permettendo che le espressioni identiche siano sostituite l'una dall'altra e consentendo alle espressioni di essere calcolate indipendentemente l'una dall'altra (cioè su thread differenti) senza usare i lock.

  3. Immutabilità. Lo stato di un oggetto immutabile non può essere modificato una volta creato. Ciò migliora la componibilità perché puoi contare su un valore stabile dell'oggetto, senza preoccuparti se qualche funzione o oggetto da qualche parte ha cambiato lo stato dell'oggetto dopo che è stato creato.

  4. Purezza. Le funzioni pure non hanno effetti collaterali. Hanno solo un input e un output, il che li rende più componibili perché puoi mettere l'output di una funzione nell'input di un'altra funzione senza preoccuparti se sia cambiato qualcosa al di fuori della funzione.

I lock non compongono perché sono un elemento esterno su cui si deve fare affidamento quando si combinano due operazioni che condividono uno stato, e per tutti i tipi di ragioni che hanno a che fare con la complessità insita nell'uso dei lock.

La frase "le monadi non compongono" non ha molto senso per me. L'intero punto di una monade è prendere una cosa di stato come l'input da tastiera o l'output dello schermo e trasformarlo in una forma matematica più pura, che è, in effetti, più componibile.

    
risposta data 17.07.2015 - 22:27
fonte