středa 23. listopadu 2011

Kdo zaplatí státní dluh?

Když vidím současné předlužené státy jako Řecko a Itálii (nicméně Česká Republika je taky zadlužená...), musím se ptát: opravdu to muselo dojít až tak daleko? Kdo to umožnil?

Jak se státy mohly takto zadlužit?

Někdo jim to musel umožnit. Tím, že jim půjčil. V případě bankrotu přijde zkrátka. Ale proč to muselo zajít až tak daleko?

On bankrot přichází ve chvíli, kdy by dlužník měl splácet, ale nemá z čeho. Mohl by si zase půjčit, ale v takové situaci už asi nenajde věřitele. Nenajde se totiž takový věřitel, který by dostatečně věřil, že půjčené peníze dostane zpět.

To ale není něco, co by se nedalo předem odhadnout. Dlužník už nějakou dobu před bankrotem vypadá nedůvěryhodně, takže ti poslední to mohli dobře tušit. Kdyby mu nepůjčili, ušetřili by a bankrot by přišel o něco dříve (s menšími škodami). Zpětná vazba ke špatnému hospodaření nastane dříve.

Tím ale přijde zkrátka jiná část věřitelů. (Dopouštím se zde malé nepřesnosti - předpokládám, že mu pokaždé půjčil někdo jiný. Chci se vyhnout složité formulaci.) Dohromady půjde o méně peněz (bankrot nastane již při menším dluhu) a možná i o menší počet věřitelů, ale objeví se tu část půjček, které by byly zaplaceny, kdyby k bankrotu došlo později. Ale ono to vlastně už u této části půjček šlo předpovědět...

Zvýšení obezřetnosti věřitelů tedy vede k dalšímu zvýšení obezřetnosti věřitelů. Nevěřím, že to bude fungovat až do nekonečna, ale je zřejmé, že i relativně malé zvýšení obezřetnosti věřitelů na začátku může ve výsledku vést k velkému uspíšení bankrotu. To není špatně - takový rychlý bankrot bude mít relativně malé následky a brzkou zpětnou vazbu. (V informatice tomu říkáme fail fast). Jakmile by se doba od začátku zadlužování k bankrotu snížila blízko k délce volebního období (i dvě nebo tři volební období je celkem krátká doba), důsledky rozhazování politiků by bylo mnohem lépe vidět. Ti by si to rozmysleli. A pokud ne, rozmysleli by si to voliči.

Jak se měří důvěra a obezřetnost?

Důvěra může na první pohled být těžko uchopitelný pojem. Obecně asi ano, ale v případě úvěrů to tak těžké není. Věřitelé to vyjadřují z velké části dokonce číslem.

Čím méně věřím, že mi dlužník vrátí peníze zpět, tím vyšší riziko zde vidím. A to riziko musím nějak vyvážit. Kromě vymahatelnosti a záruk (například v případě nesplacení přijdete o dům) se dá zvyšovat úrok.

Kdo udělal chybu?

Ale pořád nejsme u jádra problému. Víme, že někdo státům půjčil příliš a že ten to odnese. Otázkou zůstává:

  • Kdo to byl?
  • Proč to udělal? (Když si přece následky ponese sám, nemá důvod půjčovat...)
  • Odneseme to nějak i my?
  • Přispěli jsme na to i my sami?

Na tyto otázky se pokusím odpovědět. Podle mnohých článků vypadá odpověď na první otázku celkem jednoduše - banky. (Celkem blbě se to ověřuje nebo vyvrací - vyžaduje to rozsáhlejší analýzu. Na tu se neodvážím, ale možnost, že jde o banky zní celkem rozumně. Banky mají celkem dost peněz a chtějí je někam investovat.)

Odpovědět na souvislost s námi je taky zřejmá - v bance má mnoho z nás svoje peníze a dostanou-li se banky do problémů, zaplatíme to. Otázkou tu zůstává, proč se banky takto chovají a proč je podporujeme.

(Tak mě napadá představa, kdy si dáme peníze do banky a stát nám za tyto peníze dá dárek, za který mu poděkujeme. Se slovy "darovanému koni na zuby nehleď". Nedivme se pak, že ty peníze tu nejsou. Tuto představu ale neberte úplně doslova.)

Co bere bankám a lidem obezřetnost?

Ale banky přece nemají zájem zkrachovat a lidé nemají zájem přijít o své peníze! Bankéři by se měli chovat nanejvýš opatrně, aby banky byly solventní, to je přece v jejich zájmu, ne?

Možná ne tak docela. Tady do toho vstupuje ještě stát se svými psanými a nepsanými zárukami. O čem je řeč?

První věc je, že většina bankovních vkladů je státem pojištěná. V takovémto případě se lidé nebudou až tolik zajímat o to, jak banka hospodaří. Banky budou motivovány k riziku, protože riskantní investice typicky vynášejí více. Pokud risk vyjde, zisk dostanou především bankéři. (Dobře, podělí se o něj v úrocích, haha.) Ve chvíli, kdy risk nevyjde (v případě dluhopisů to asi nebude hned), zaplatí to všichni z daní. Pokud by to platili jen klienti té banky, pak by to platili jen ti, kdo uvěřili jejím slibům. Lidé by byli motivováni si vybírat dobře hospodařící banky, které neriskují příliš.

Druhá věc je ještě horší - problémová banka může být zachráněna se vším všudy. Bankéřům, kteří riskovali, zůstává práce a mohou riskovat za peníze jiných dál. (Ovšem ve chvíli, kdy se risk vyplatí, shrábnou zisk sami.) Pokud si dobře pamatuji, dělo se to v USA s argumentem, že jsou too big to fail. (Tak je podepřeme a časem necháme udělat ještě větší fail...). A hlavně se to zřejmě plánuje v EU - jak jinak mám pochopit rekapitalizaci bank?

Celkem dobře to shrnuje pojmenování soukromý zisk a veřejné ztráty. To není zrovna podle kapitalismu, kde je soukromý nejen zisk, ale i ztráty.

Ručí stát sám za sebe?

Pokud by stát prodával dluhopisy pouze svým bankám (a ty by je dál neprodávaly a nesjednávaly by si k nim pojištění jinde), pak by stát svoji případnou platební neschopnost jistil svým pojištěním vkladů. Bylo by jasné, že státní pojištění vkladů bude v případě jeho bankrotu pouze iluzí, protože by stejně neměl z čeho to pojištění platit. Ono je to trošku (ale ne o moc) složitější.

Velmi křehký systém

Státy totiž dluží dost v zahraničí. Zbankrotuje-li Řecko, nejen řecké banky se mohou dostat do potíží. A pokud některá z nich zkrachuje a je státem pojištěná, může do problémů dostat stát. Pokud ten zbankrotuje, může dostat do problémů další banky... Je tu vidět, jak se všichni vzájemně opírají o všechny. (Řecko zřejmě nebude až takový problém. Ledaže by byl použit 'Euroval' a s Řeckem padla i Itálie... Tady se přiznám, že neznám dostatečně dobře aktuální stav, nicméně doufám, že 'Euroval' bude zahrabán.)

Mimochodem, toto domino už někdo popisoval. Je prostě jasné, že ony záruky nemohou fungovat donekonečna.

Abych to upřesnil, v extrémním případě by stát mohl zatlačit na centrální banku, která by vytiskla libovolné množství peněz a za ně nakoupila třeba státní dluhopisy. To je ale vpodstatě jen jiná forma daní - inflace. Velká inflace je možná i horší alternativa k bankrotu. Lehce odlišná je situace v zemích eurozóny, které by musely pro inflaci ovlivňovat ECB. Na druhou stranu si myslím, že je tady ještě větší motivace se na to spoléhat. Ale to by bylo na samostatný článek.

Přidat státní zásah? Ne, odebrat!

Možná si někteří říkají, že je potřeba na banky státem lépe dohlédnout. Je skutečně možné, že takové snahy nastanou. Ale co by se tím vyřešilo? Kdo z úředníků má skutečnou motivaci správně rozhodnout za jiné? Nebude zde mít větší sílu úplatek nebo (v tomto případě) tlak od politiků, kteří chtějí rozhazovat a kupovat si voliče z cizích daní?

Nejspíš bude. A komu takový státní dozor prospěje?

V této souvislosti jsem si vzpomněl na snahu politiků zavést novou daň a udělat pro jejich dluhopisy výjimku. Myslíte si, že by to zde dopadlo jinak?

Ne, tudy cesta opravdu nevede. Záruky za banky musí zmizet, třeba i postupně. Pak občané budou mít motivaci si banky hlídat (nebo na ně a jejich mizivé úroky kašlat, taky cesta - trh to taky ovlivní) a banky budou mít motivaci k méně riskantním investicím.

Je nutná změna ve všech státech?

Když jsem nakousl ono propletení mezi státy, nastává otázka, zda by nám mělo stačit zrušení záruk v České Republice, nebo jestli je musí zrušit i okolní státy, aby to mělo účinek. Na první pohled to bez spolupráce ostatních států nemá pro nás smysl. Náš stát se bude moci dál zadlužovat.

Ale naše banky by to nepodporovaly a my bychom to riziko nenesli. A ostatní státy by měly motivaci se k nám přidat. A pokud by nám "jen" znevýhodnily půjčky nějakou regulací, pro nás by to v důsledku bylo jen více či méně obdoba téhož. Nebylo by to sice ideální (řídili by to politici, ne trh), ale byla by to taky možnost.

Jaký má smysl běžný účet?

Tak svůj smysl určitě má - na placení přes internet apod. se určitě hodí. Ale nepřijde mi vhodné na něj dávat všechny svoje úspory. Co z toho? Úročení je obvykle směšné a riziko zbytečně vysoké. Že to rozložíte na více bank? Fajn, ale v případě problémů např. se státními dluhopisy na tom banky budou podobně a může jich padnout více prakticky zároveň.

Něco jiného jsou spořicí účty, termínované vklady, podílové fondy a podobně. To už může stát za zvážení. O úročení se již dá mluvit. Dá se už přemýšlet o tom, jestli je větší riziko, nebo výnos. To si moc netroufám odhadovat a obecně to asi nelze říct.

pondělí 5. září 2011

Dědičnost u case classes

Case classes jsou ve Scale jednoduchým nástrojem, který slouží zhruba ke stejnému účalu jako struktury v Cčku nebo entitní třídy v Javě - seskupují data, která patří k sobě. Vše je velmi jednoduché, než se sem vloží dědičnost. Pak je potřeba trochu přemýšlet, protože se situace trochu komplikuje. Ale jen trochu...


Budu postupovat po malých krocích, takže článek vypadá dlouze. Přidaný nebo změněný kód se snažím zvýrazňovat.


Terminologická odbočka

  • field - datový atribut třídy, který by měl být podle zásad zapouzdření pokud možno private. Napíšete-li v Javě ve třídě třeba private String foo = null;, vytvořili jste field.
  • vlastnost (vlastnost třídy) - data, která mají vztah ke třídě a která lze zjistit zavoláním getteru a případně nastavit zavoláním setteru. Data lze číst z fieldu (a případně zapisovat do něj), ale obecně to není nutné.

Co nám case classes nabízejí?

Když už víme, kdy zvažovat jejich použití, přejděme k tomu, co od nich dostaneme.

  • Metody pro porovnávání - equals a hashCode. Díky tomu nebudou instance té třídy ve výchozím stavu porovnávány podle identity, ale podle ekvivalence jejich členů.
  • Parametry třídy jsou defaultně veřejně viditelné, takže nemusíte psát val. (Generují se fieldy a gettery k nim.)
  • Metodu toString pro převod na čitelný řetězec.
  • Metodu apply ("statickou" metodu) pro konstrukci objektu bez klíčového slova new.
  • Metodu unapply ("statickou" metodu) pro pattern matching

Podle článku o case classes z FAQ by to mělo být již vše.

Úkol

Určeme si nějaký úkol s dědičností. Navrhuji použít elipsu a kružnici (jako její speciální případ). Každý tvar bude mít i barvu. (Možná budu za tu barvu kritizován, ale zkuste navrhnout příklad, který je co nejjednodušší, nejnázornější a nemá znaky něčeho umělého...)

Nápad s case classes

Možná vás jako první napadne toto:

package com.v6ak.example.geometry

case class Shape(color: String)

case class Ellipse(color: String, a: Int, b: Int) extends Shape(color)

case class Circle(color: String, r: Int) extends Ellipse(color, r, r)

Zkuste si to. Kompilátor řve? No dobře, tudy cesta asi nevede.

Problém

Kompilátor nám vlastně řval, že se snažíme znovu přidávat vlastnost (vlastně jen getter), která již existuje díky rodiči. A je plně implementovaná. (Onen getter není v rodiči abstraktní.) Což o to, přidáním override val k vlastnosti color bychom kompilátor umlčeli. (On by stále řval, že se to tak dělat nemá, ale bylo by to jen varování.)

U Shape jsme definovali i to, jak se barva získává. V Javě by tomu totiž odpovídal privátní field s getterem. Možná si myslíte, že budou následovat nějaké "kecy o zapouzdření". To ne, u kružnice a elipsy máme zajímavější situaci. Elipsa má hlavní a vedlejší poloosu a ve speciálním případě (pokud si jsou obě poloosy rovny) jde o kružnici. U kružnice ale máme tři vlastnosti, které nesou tu stejnou hodnotu - jednou jako hlavní poloosu, podruhé jako vedlejší poloosu a potřetí jako poloměr. Jedna hodnota by tedy byla v jedné instanci kružnice uložena třikrát! To vypadá už trošku divně, ne? No ano, ale když jsme si takto implementovali elipsu, tak to jinak nepůjde. Elipsa prostě je implementovaná tak, že má dva fieldy a k nim dva gettery pro hlavní a vedlejší poloosu. A kružnice k nim takto přidává třetí. Fieldy odebírat prostě nejdou. A i kdyby to šlo, byla by to celkem úzká vazba na implementaci v rodičovi.

Varianta s abstraktními třídami

Můžeme to ale řešit jinak:

  • Každá case class bude finální.
  • Všichni předci case classes budou abstraktní. (Pro úplnost: třídu AnyRef teď vynechávám.)
  • Díky tomu se nám nestane, že by jedna case class dědila z druhé. Třídy si tedy nebudou lézt do zelí (fieldů).

První verze

Tato verze je záměrně velmi podobná verzi plné case classes a přízpůsobil jsem tomu i styl odsazování.

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

No, už to vypadá lépe a kompilátor to vezme. Kružnice má jen jeden field pro poloměr, ne tři stejné. Ale co elipsa? Jak vytvořím elipsu? Asi to chce ještě něco trošku přidat.

Přidáváme konkrétní elipsu

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

Teď již není problém vytvořit konkrétní elipsu. Používá se ale "škaredé" GeneralEllipse, které "ční" ven. Třídu radši skryjeme a vytvoříme jí továrnu.

Skrýváme GeneralEllipse

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = GeneralEllipse(color, a, b)

}

Už je to celkem použitelné, ale pořád se dá vylepšovat. Ellipse nemá pattern matching.

Doplňujeme pattern matching

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = GeneralEllipse(color, a, b)
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

Toto si už zaslouží menší komentář. Jednodušší verze by nebyla odolná null hodnotám:

def unapply(e: Ellipse) = Some((e.color, e.a, e.b)) // vrací přímo uspořádanou trojici, ale selže u null hodnot

Proto pomocí Option(e) konvertujeme na Option, což je vpodstatě kolekce o nejvýše jednom prvku. Pro null dostáváme prázdnou kolekci (tj. None), pro jinou hodnotu dostáváme kolekci o právě jednom prvku (tj. Some(e)). A nakonec pomocí metody map konvertujeme případný obsah na uspořádanou trojici. Pro null tedy dostáváme None, protože to není elipsa, pro ostatní dostáváme rozloženou elipsu na uspořádanou trojici prvků, že kterých byla vytvořena. Narozdíl od GeneralEllipse toto funguje i pro kružnice.

K čemu to unapply využijeme?

Zde trošku odbočím. Možná si říkáte, k čemu je tu to podivínské unapply. Díky němu totiž můžete psát toto:

shape match {
 case Circle(c, r) => "kružnice o poloměru "+r
 case Ellipse(c, a, b) => "elipsa (...)"
 case _ => "neznámé"
}

Možná to nepotřebujete, pak to můžete vynechat.

Vylaďujeme detaily (někdy podstatné)

Každá kružnice je Circle

Pokud nyní vytvoříme Ellipse("yellow", 5, 5), dostaneme tím něco jiného než Circle("yellow", 5). Sice se to bude chovat podobně, ale podle == si rovny nebudou. (Metoda/"operátor" == porovnává podle metody equals a řeší null hodnoty.) Navíc Ellipse(5, 5) nebude instancí třídy Circle. Proto trošku upravíme továrnu:

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = if(a == b){
  Circle(color, a)
 }else{
  GeneralEllipse(color, a, b)
 }
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

Stylystická: Použijeme match místo podmínek

Toto je otázka spíše stylu, ale přijde mi hezčí použít match než if. Fungovat by to mělo naprosto stejně.

package com.v6ak.example.geometry

abstract class Shape{def color: String}

abstract class Ellipse extends Shape {def a: Int; def b: Int}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = a match {
  case `b` => Circle(color, a)
  case _ => GeneralEllipse(color, a, b)
 }
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

Uzavíráme okruh tříd

Můžeme chtít, aby nám Shape neimplementoval někdo jiný. První možnost je dát jeho konstruktoru viditelnost jen pro balíček, ve kterém je:

abstract class Shape private[geometry]() {def color: String}

Máme tu ale možnost vše mít v jednom souboru a použít modifikátor sealed. Díky tomu nebude možné dělat potomky Shape v jiném souboru a navíc dostaneme u pattern matchingu varování při nevhodném použití. Modifikátor dostanou všechny veřejné abstraktní třídy.

package com.v6ak.example.geometry

abstract sealed class Shape{def color: String}

abstract sealed class Ellipse extends Shape {def a: Int; def b: Int}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = a match {
  case `b` => Circle(color, a)
  case _ => GeneralEllipse(color, a, b)
 }
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

Vylepšujeme toString u elips

Pokud nechceme při převodu elipsy na řetězec dostávat GeneralEllipse(...), uvedeme, co chceme místo toho:

package com.v6ak.example.geometry

abstract sealed class Shape{def color: String}

abstract sealed class Ellipse extends Shape {
 def a: Int
 def b: Int
}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse{
 override def productPrefix = "Ellipse"
}

final case class Circle(color: String, r: Int) extends Ellipse {def a=r; def b=r}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = a match {
  case `b` => Circle(color, a)
  case _ => GeneralEllipse(color, a, b)
 }
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

A nakonec trosku whitespace

Při prvních úpravách jsem pro pocit podobnosti použil trošku nekonvenční pravidla pro odsazování apod., tak to teď napravím.

package com.v6ak.example.geometry

abstract sealed class Shape{
 def color: String
}

abstract sealed class Ellipse extends Shape {
 def a: Int
 def b: Int
}

private[geometry] final case class GeneralEllipse(color: String, a: Int, b: Int) extends Ellipse{
 override def productPrefix = "Ellipse"
}

final case class Circle(color: String, r: Int) extends Ellipse {
 def a=r
 def b=r
}

object Ellipse {

 def apply(color: String, a: Int, b: Int) = a match {
  case `b` => Circle(color, a)
  case _ => GeneralEllipse(color, a, b)
 }
 
 def unapply(e: Ellipse) = Option(e).map(e => (e.color, e.a, e.b))

}

Vyzkoušíme si

Nedělali jsme unit testy, ale aspoň si napíšeme jednoduchý kód, který demonstruje funkčnost:

package com.v6ak.example.geometry

object Demo extends Application{ // use App instead of Application in Scala <= 2.9
 val a = Circle("yellow", 5)
 val b = Ellipse("yellow", 5, 5)
 val c = Ellipse("yellow", 4, 5)
 println(a + " is equal to " + b + ": " + (a == b) + " (should be true)")
 println(a + " is equal to " + c + ": " + (a == c) + " (should be false)")
}

Nyní můžeme uložit poslední verzi tříd třeba do classes.scala a tuto ukázku do demo.scala, zkompilovat příkazem fsc *.scala a spustit příkazem scala com.v6ak.example.geometry.Demo. Měli bychom dostat toto:

Circle(yellow,5) is equal to Circle(yellow,5): true (should be true)
Circle(yellow,5) is equal to Ellipse(yellow,4,5): false (should be false)

Konečnou verzi zdrojáků spolu s demem si můžete stáhnout z Githubu,