C'è stata una discussione su Kotlin Slack sulla possibilità di aggiungere alberi di codice per supportare cose come C # LINQ.
In C # LINQ ha molte applicazioni, ma voglio concentrarmi solo su una (perché altre già presumibilmente trattate dalla sintassi di Kotlin): comporre query SQL su database remoti.
Prerequisiti:
Abbiamo uno schema di dati di un database SQL espresso in qualche modo nel codice in modo che gli strumenti statici (o il sistema di tipi) possano verificare la correttezza (almeno la denominazione) di una query SQL
Dobbiamo generare le query come stringhe
Vogliamo una sintassi vicina agli stream SQL o Java
Domanda : cosa aggiungono gli alberi di espressione alla sintassi che è così cruciale per l'attività in corso? Quanto può essere buono un costruttore SQL senza di loro?
Come ha dimostrato JINQ, è possibile arrivare molto lontano analizzando il bytecode per comprendere l'intento dello sviluppatore e quindi tradurre il predicato in SQL. Quindi in linea di principio gli alberi di espressione non sono essenziali per creare una query dsl dall'aspetto accattivante:
val alices = database.customerStream().where { it.name == "Alice" }
Anche senza un hackery come l'analisi bytecode è possibile ottenere una query decente con la generazione del codice dsl. Querydsl e JOOQ sono ottimi esempi. Con un po 'di codice di avvolgimento di Kotlin puoi scrivere
val alices = db.findAll(QCustomer.customer, { it.name.eq("Alice") })
L'albero delle espressioni è una struttura che rappresenta un codice che si risolve in un valore. Avendo tale struttura generata dal compilatore non è necessario l'analisi bytecode per capire cosa si suppone debba fare. Dato l'esempio
val alices = database.customerStream().where { it.name == "Alice" }
L'argomento su where
funzione sarebbe expression
che possiamo esaminare in runtime e tradurlo in SQL o in un altro linguaggio di query. Poiché le strutture di espressione rappresentano il codice, non è necessario passare da Kotlin a SQL paradigma per scrivere query. Il codice della query espresso usando linq / jinq sembra praticamente lo stesso, indipendentemente dal fatto che siano eseguiti in memoria usando POCO / POJO o nel motore del database usando il suo linguaggio di query. Il compilatore può anche fare più controlli di tipo. Inoltre è molto facile sostituire il database sottostante con la rappresentazione in memoria per rendere i test di esecuzione molto più veloci.
Ulteriori letture: