ΠΠΎΠΌΠΏΠ°Π½ΠΈΡ Apple ΠΎΡΠΊΡΡΠ»Π° ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠ·ΡΠΊΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ Pkl, ΠΏΡΠ΅Π΄Π½Π°Π·Π½Π°ΡΠ΅Π½Π½ΠΎΠ³ΠΎ Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΈ ΠΏΡΠΎΠ΄Π²ΠΈΠ³Π°ΡΡΠ΅Π³ΠΎ ΠΌΠΎΠ΄Π΅Π»Ρ «ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΠΊΠ°ΠΊ ΠΊΠΎΠ΄». Π‘Π²ΡΠ·Π°Π½Π½ΡΠΉ Ρ Pkl ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ Π½Π°ΠΏΠΈΡΠ°Π½ Π½Π° Kotlin ΠΈ ΠΎΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½ ΠΏΠΎΠ΄ Π»ΠΈΡΠ΅Π½Π·ΠΈΠ΅ΠΉ Apache. ΠΠ»Π°Π³ΠΈΠ½Ρ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΊΠΎΠ΄ΠΎΠΌ Π½Π° ΡΠ·ΡΠΊΠ΅ Pkl ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½Ρ Π΄Π»Ρ ΡΡΠ΅Π΄ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ IntelliJ, Visual Studio Code ΠΈ Neovim. Π Π±Π»ΠΈΠΆΠ°ΠΉΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° LSP (Language Server Protocol).
Pkl ΡΠΎΡΠ΅ΡΠ°Π΅Ρ ΡΠ²ΠΎΠΉΡΡΠ²Π° ΠΏΡΠΎΡΡΠΎΠ³ΠΎ Π΄Π»Ρ Π²ΠΎΡΠΏΡΠΈΡΡΠΈΡ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΡΠ·ΡΠΊΠ° c ΡΠ°ΡΡΠΈΡΠ΅Π½Π½ΡΠΌΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡΠΌΠΈ, ΡΠ²ΠΎΠΉΡΡΠ²Π΅Π½Π½ΡΠΌΠΈ Π΄Π»Ρ ΡΠ·ΡΠΊΠΎΠ² ΠΎΠ±ΡΠ΅Π³ΠΎ Π½Π°Π·Π½Π°ΡΠ΅Π½ΠΈΡ. Π ΡΠ·ΡΠΊΠ΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΡΡ Π°Π½Π½ΠΎΡΠ°ΡΠΈΠΈ ΡΠΈΠΏΠΎΠ², ΠΊΠ»Π°ΡΡΡ, ΡΡΠ½ΠΊΡΠΈΠΈ, Π²ΡΡΠΈΡΠ»ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ, ΡΡΠ»ΠΎΠ²ΠΈΡ ΠΈ ΡΠΈΠΊΠ»Ρ. Pkl ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡΡΡ ΠΊΠ°ΠΊ Π΄Π»Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ Π² ΡΠ°Π·Π½ΡΡ ΡΠΎΡΠΌΠ°ΡΠ°Ρ , ΡΠ°ΠΊΠΈΡ ΠΊΠ°ΠΊ JSON, YAML ΠΈ XML, ΡΠ°ΠΊ Π΄Π»Ρ ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΌΠΎΠ΄ΡΠ»Π΅ΠΉ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π·Π°Π΄Π°Π½Π½ΡΡ ΡΠΎΡΠΌΠ°ΡΠΎΠ² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΡ Π½Π° ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ ΡΠ·ΡΠΊΠ°Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
ΠΡΠΈΠ²ΡΠ·ΠΊΠΈ Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Pkl Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½Ρ Π΄Π»Ρ Java, Kotlin, Go ΠΈ Swift. ΠΡΠ΄Π΅Π»ΡΠ½ΠΎ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ ΠΌΠΎΠ΄ΡΠ»Ρ Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Ρ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΎΠΌ Spring. ΠΡΠΈΠ²ΡΠ·ΠΊΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π° ΡΠ·ΡΠΊΠ΅ Pkl ΡΡΠΎΡΠΌΠΈΡΠΎΠ²Π°ΡΡ Π³ΠΎΡΠΎΠ²ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΈ ΠΌΠΎΠ΄ΡΠ»ΠΈ Ρ ΠΊΠ»Π°ΡΡΠ°ΠΌΠΈ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠΉ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠ΅ΠΉ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. ΠΠ°ΠΊΠ΅ΡΡ Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΌΠΎΠ³ΡΡ ΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°ΡΡΡΡ Π² ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΡΡ ΠΈ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡΡΡ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ, ΡΡΠΎ Π΄ΠΎΠΏΡΡΠΊΠ°Π΅Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡΠ½ΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° Pkl ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ°Π·Π½ΡΠΌΠΈ ΠΏΡΠΎΠ΅ΠΊΡΠ°ΠΌΠΈ.
Π―Π·ΡΠΊ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Π³ΠΈΠ±ΠΊΠΈΠ΅ ΡΡΠ΅Π΄ΡΡΠ²Π° Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΡΠ»ΠΎΠ²ΠΈΠΉ ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΎΠΊ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΡΡΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠΈΡ Π²ΡΡΠ²Π»ΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΠΈΡΠΎΠ³ΠΎΠ²ΠΎΠΉ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π° ΡΡΠ°ΠΏΠ΅ Π΄ΠΎ Π΅Ρ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ Π΄ΠΎΠΏΡΡΡΠΈΠΌΡΠΉ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ («port: Int(this > 1000)» ΠΈΠ»ΠΈ «age: Int(isBetween(0, 130))»), ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΠΈΠ»ΠΈ Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΡ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈ ΡΠΎΡΠΌΠ°Ρ («zipCode: String(matches(Regex(«\\d{5}»)))»). Π ΡΠ»ΡΡΠ°Π΅ ΠΏΡΠΈΡΠ²ΠΎΠ΅Π½ΠΈΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ, Π½Π΅ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅Π³ΠΎ ΡΡΠ»ΠΎΠ²ΠΈΡ, Π²Π°Π»ΠΈΠ΄Π°ΡΠΎΡ Π²ΡΠ²Π΅Π΄Π΅Ρ ΠΎΡΠΈΠ±ΠΊΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΈ ΠΏΠΎΠΏΡΡΠΊΠ΅ ΠΏΡΠΈΡΠ²ΠΎΠΈΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ 1001 ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΠΎΠΌΡ ΠΊΠ°ΠΊ «Int(this > 1000)»).
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π½Π° ΡΠ·ΡΠΊΠ΅ Pkl ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΠΌΠΎΠ΄ΡΠ»Ρ Application.pkl Ρ ΡΠ°Π±Π»ΠΎΠ½ΠΎΠΌ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΊ Π‘Π£ΠΠ: module Application hostname: String port: UInt16 environment: Environment database: Database class Database { username: String password: String host: String port: UInt16 dbName: String } typealias Environment = «dev»|»qa»|»prod»
ΠΠ°Π»Π΅Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ Π½Π΅ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²Π΅Π½Π½ΠΎ ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΠΉ Π΄Π°Π½Π½ΡΠΉ ΠΌΠΎΠ΄ΡΠ»Ρ Π΄Π»Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΡΡΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ: amends «Application.pkl» hostname = «localhost» port = 3599 environment = «dev» database { host = «localhost» port = 5786 username = «admin» password = read(«env:DATABASE_PASSWORD») dbName = «myapp» }
Π ΡΠ°ΠΊΠΆΠ΅ Π½Π°ΠΏΠΈΡΠ°ΡΡ Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π½ΠΎΠΌΠ΅ΡΠ° ΠΏΠΎΡΡΠ° Π΄Π»Ρ ΡΠ΅ΡΡΡΡΡ ΡΠ°Π·Π½ΡΡ Π‘Π£ΠΠ: import «Application.pkl» hidden db: Application.Database = new { host = «localhost» username = «admin» password = read(«env:DATABASE_PASSWORD») dbName = «myapp» } sidecars { for (offset in List(0, 1, 2, 3)) { (db) { port = 6000 + offset } } }
ΠΡΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΡΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Π² Π΄ΡΡΠ³ΠΎΠΌ ΡΠΎΡΠΌΠ°ΡΠ΅, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, YAML: sidecars: — username: admin password: hunter2 host: localhost port: 6000 dbName: myapp — username: admin password: hunter2 host: localhost port: 6001 dbName: myapp — username: admin password: hunter2 host: localhost port: 6002 dbName: myapp — username: admin password: hunter2 host: localhost port: 6003 dbName: myapp
Π‘Ρ
Π΅ΠΌΠ° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π° ΡΠ·ΡΠΊΠ΅ Pkl ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½Π° Π² ΠΊΠ»Π°ΡΡΡ ΠΈΠ»ΠΈ ΡΡΡΡΠΊΡΡΡΡ Π΄Π»Ρ Π²ΡΡΡΠ°ΠΈΠ²Π°Π½ΠΈΡ Π² ΠΊΠΎΠ΄ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΡΠΈΠ²ΡΠ·ΠΊΡ Π΄Π»Ρ Kotlin: import kotlin.Int import kotlin.Long import kotlin.String data class Application( val hostname: String, val port: Int, val environment: Environment, val database: Database ) { data class Database( val username: String, val password: String, val host: String, val port: Int, val dbName: String ) enum class Environment( val value: String ) { DEV(«dev»), QA(«qa»), PROD(«prod»); override fun toString() = value } }
ΠΡΡΠΎΡΠ½ΠΈΠΊ: opennet.ru