k47.cz  — každý den dokud se vám to nezačne líbit
foto Praha výběr povídky kultura
twitter FB RSS

Ceylon Project

7. 6. 2011 — k47 (CC by) (♪)

Red Hat dva roky po­tajmu vy­ví­jel vlastní pro­gra­mo­vací jazyk Ceylon, který byl stejně ne­ná­padně ozná­men Gainem Kingem na nějaké asij­ské kon­fe­renci. Nikdo z Red Hatu ne­če­kal velké ohlasy, šlo jenom o malé ozná­mení. Ale věci na­braly ne­če­kaný spád a o Cey­lonu se v po­slední době píše všude možně. A to i přesto, že máme k dis­po­zici jenom dvo­jici slajdů z kon­fe­rence. Nemáme kom­pi­lá­tor, žádné info o při­pra­vo­vané vlastní SDK, nic.


Jde o další pokus udělat Javu, která se stává dneš­ním CO­BO­Lem, správně, tak jak by byl dnes na­vr­ho­ván jazyk pro busi­ness com­pu­ting.

Ceylon v sobě nese ně­ko­lik velice za­jí­ma­vých nápadů, ale má jeden ob­rov­ský pro­blém: Scalu. Na­pros­tou vět­šinu z toho, co Ceylon někdy v bu­doucnu na­bídne, už teď Scala ob­sa­huje a ještě mnohem víc. Scala je jako asymptota, jejímž směrem se snahy pro­jektu Ceylon z větší čísti ubí­rají. Ceylon se poučil z ne­do­statků Javy a po­su­nul se o jeden krok dál, může tak vy­ře­šit sou­časné pro­blémy, ale stejně jako v pří­padě Javy za ně­ko­lik let na­ra­zíme na další pro­blémy, které budou mí stejné řešení: Scalu (resp. ně­ja­kou její bu­doucí verzi) jako velice fle­xi­bilní a or­to­go­nální jazyk.

A teď moje ne­sou­vislé po­známky k Cey­lonu:

Za­jí­ma­vou myš­len­kou je na­hra­zení vět­šiny klí­čo­vých slov ano­ta­cemi, které na rozdíl od Javy nejsou uvo­zeny za­vi­ná­čem, takže vy­pa­dají jako sku­tečná klí­čová slova. Ale na druhou stranu je po­divné, proč byla zažitá po­jme­no­vání za­mě­něna za zcela jiná. Jmenná ška­tu­lata jsou ná­sle­du­jící:

Proč se zříkat za­ži­tých ter­mínů a za­vá­dět jiná, když to nemá žádný patrný přínos. Ale na druhou stranu, jde jenom o ano­tace, takže mohou být kdy­koli změ­něny (a to snad i sa­mot­ným pro­gra­má­to­rem) bez toho aby se musela měnit gra­ma­tika jazyka.


Pře­tě­žo­vání ope­rá­torů: ope­rá­tor v Cey­lonu je alias pro před­de­fi­ni­o­va­nou metodu na před­de­fi­no­va­ném roz­hraní. + je alias pro Numeric.plus(), > pro Comparable.largerThan() Jde o něco bez­peč­nější způsob než kla­sicé pře­tě­žo­vání ope­rá­torů, pro­tože si zkrátka nemůžu vy­tvo­řit vlastní ope­rá­tor +, který by měl jiný význam než sčí­tání nebo >, který by ne­po­rov­ná­val. Na druhou stranu se ztrácí spousta fle­xi­bi­lity. Není možné de­fi­no­vat ex­pre­sivní DSL jako např. parser com­bi­na­tors ze Scaly:

def obj: Parser[Map[String, Any]] = "{" ~> repsep(member, ",") <~ "}" ^^ (Map() ++ _)
def arr: Parser[List[Any]]        = "[" ~> repsep(value, ",") <~ "]"

Scala navíc pro­blém pře­tě­žo­vání ope­rá­torů vy­ře­šila velice ša­la­moun­sky – mezi oběma pojmy není žádný rozdíl, ope­rá­tor je jejom jinak za­psaná metoda, což je ještě o něco pruž­nější pří­stup, ale plyne z něj pe­ten­ci­ální riziko, že se kód může stát ne­pře­hled­ným, když si lidi začnou de­fi­no­vat vlastní ASCII art ope­rá­tory.


Ceylon zcela ig­no­ruje pat­tern matching jednu ze sil­ných vlast­ností Scaly.


Type unions & in­ter­secti­ons – stejný kon­cept jako juncti­ons z Perlu 6.

A & B & C – průnik typů – musí im­ple­men­to­vat roz­hraní A a zá­ro­veň B a zá­ro­veň C A | B | C – sjed­no­cení typů – od­po­vídá typu A nebo B nebo C

Zvlášť průnik není možné nijak jed­no­duše emu­lo­vat. Ale otázka zní, jestli je tolik po­třeba, když máme k dis­po­zici dě­dič­nost, struk­tu­rální typy, typ Either nebo tenhle klenot vy­u­ží­va­jící Curry-Howard iso­mor­fis­mus.


Spousta roz­hod­nutí jde správ­ným směrem. Např: žádný over­lo­a­ding, žádný null. Otázka zní, jak to ovlivní in­te­ro­pe­ra­bi­litu s Javou. Martin Ode­r­sky se v ně­ja­kým roz­ho­voru zmínil, že v pří­padě Scaly také uva­žo­vali o po­dobně zá­sad­ních změ­nách – na­hra­dit null typem Option[T] a v pří­padě over­la­dingu se vydat na druhou stranu a zavést plně dy­na­mický mul­tiple dispatch, ale právě proto, aby byli schopni hladné spo­lu­práce s Javou se roz­hodli nebýt tak ra­di­kální. In­te­ro­pe­ra­bi­lita s ně­ja­kou již exis­tu­jící plat­for­mou je zá­sadní pro adopci nového jazyka. Všechno je mnohem jed­no­dušší, když můžeme bez­pro­blé­mově vy­u­ží­vat již exis­tu­jící knihovny od času T = 0.

Dále je za­jí­mavá zmínka, že Ceylon je za­mě­řen na JVM, ale může být poz­ději por­to­ván i na jiné plat­formy. Lo­gický další krok .NET. Scala má po­dob­nou fi­lo­so­fii a kromě hlavní JVM verze exis­tuje i její .NET pro­těj­šek. Že by se tady rý­so­vala nová ge­ne­race vý­kon­ných (myš­leno ne­skrip­to­va­cích) jazyků vro­zeně agnos­tic­kých k po­u­ži­tému vir­tu­ál­nímu stroji?

Vlast­nost ze které jsem hodně nad­šený je type re­i­fi­cation a to do­konce i na JVM, které po­u­žívá type era­sure. Jak to vlastně im­ple­men­to­vat, když pro do­da­tečné typové in­for­mace není pod­pora v by­te­kódu? Napadá mě jediné řešení: kom­pi­lá­tor pro každý typový pa­ra­metr doplní jeden hod­no­tový atri­but, který bude ucho­vá­vat kon­krétní třídu ge­ne­ric­kého typu.

Kom­pi­lá­tor ná­sle­du­jící třídu (v syn­taxi Scaly)

class A[B](a: B)

trans­for­muje na ná­sle­du­jící:

class A[B](a: B) {
  val B: Class[B]
}

A všechna volání

new A(x)

pře­píše na

new A(x) {
  val B = x.getClass // getClass musí zase vrátit reifikovaný typ
}

Bude to mít dva dů­sledky:

  1. ge­ne­rické ob­jekty budou o ně­ko­lik extra re­fe­rencí větší
  2. spo­lu­práce s kla­sic­kými ja­vov­skými ob­jekty, které pod­leh­nou type era­sure může být pro­ble­ma­tická.

Re­i­fi­kace typů může být uži­tečná i když pro ní není pod­pora na nižší úrovni. Ve Scale v bych si ji do­ká­zal před­sta­vit na vy­žá­dání, po­dobně jako spe­ci­a­li­zaci ge­ne­ric­kých tříd:

@reify
class List[+A]

Ceylon se zkrátka snaží jenom vy­ře­šit ně­které kon­krétní ne­do­statky v návrhu Javy, ale není dost fle­xi­bilní, aby umož­ňo­val zá­sadní roz­ší­ření vlast­ních mož­ností skrz knihovny.


Další čtení:

píše k47 & hosté, ascii@k47.cz