Scala

De Viquipèdia
Dreceres ràpides: navegació, cerca
Aquest article tracta sobre el llenguatge de programació. Si cerqueu l teatre d'òpera, vegeu La Scala.

Scala és un llenguatge de programació modern multi-paradigma dissenyat per a expressar patrons de programació generals d'una manera concisa, elegant i segura respecte els tipus. Integra característiques de orientació a objectes i de llenguatges funcionals.

Taula de continguts

Scala és orientat a objectes [modifica]

Scala és un llenguatge pur O.O. (orientat a objectes) en el sentit que cada valor és un objecte. Els tipus i comportaments dels objectes són descrits mitjançant classes i 'trets'. L'abstracció classe s'estén mitjançant subclasses i també amb un mecanisme flexible basat en classes 'mixins' (barrejables: similars als interface de Java però amb def. de tipus, variables i implementació de mètodes) anomenades trets com a substitució neta de l' 'herència múltiple'.

Scala és funcional [modifica]

Scala també és un llenguatge funcional en el sentit que cada funció és un valor. Scala proveeix una sintaxi fàcil per a la definició de funcions anònimes, suporta funcions d'ordre superior, permet l'aniuament de funcions i suporta el currying. Les classes per cas (ang.: case classes) i el suport que inclou de reconeixement de patrons, serveix per a modelar tipus algebraics, emprats en molts llenguatges de programació funcional.

A més a més, la noció de reconeixement de patrons estén de manera natural el procés de dades XML amb l'ajuda de seqüències de patrons ignorant el que hi ha a la dreta (ang.:right-ignoring). En aquest context, les comprehensions de seqüències (iteració sobre Generadors-Filtres-Mapeig) són útils per a formular consultes. Aquestes característiques fan de Scala l'ideal per a desenvolupar aplicacions com a serveis web.

Scala té tipus estàtics [modifica]

Scala està equipat amb un sistema de tipus expressiu que assegura estàticament que les abstraccions s'utilitzin de manera coherent i segura. En particular el sistema de tipus suporta:

  • classes genèriques,
  • anotacions de variació,
  • acotacions de tipus per dalt i per baix,
  • classes internes i tipus abstractes com a membres de l'objecte,
  • tipus compostos,
  • auto referències tipificades explícitament,
  • vistes, i
  • mètodes polimòrfics.

Un mecanisme d'inferència de tipus permet que l'usuari no hagi d'anotar els tipus de manera redundant. En combinació, aquestes característiques proporcionen una base potent per a la reutilització segura de les abstraccions de programació i també per a l'extensió de programari amb tipus de dades segurs.

Scala és extensible [modifica]

El disseny de Scala reconeix el fet que, a la pràctica, el desenvolupament d'aplicacions d'un domini específic requereix extensions de llenguatge igualment específiques. Scala proporciona una combinació única de mecanismes de llenguatge que fan fàcil afegir noves construccions al llenguatge, amb suavitat , en forma de biblioteques:

  • qualsevol mètode pot ser emprat com a operador infix o postfix, i
  • els tancaments es construeixen automàticament depenent del tipus esperat.

Un ús conjunt d'ambdues característiques facilita la definició de noves instruccions sense estendre la sintaxi i sense emprar tècniques de meta-programació com ara macros.

Scala interopera amb Java i .NET [modifica]

Scala està dissenyat per a interoperar bé amb entorns populars de programació com Java 2 (JRE) i el marc .NET (CLR). En particular, la interacció amb llenguatges orientats a objectes de gran acceptació com Java i C# és força suau. Scala té el mateix model de compilació (compilació separada, càrrega dinàmica de classes) que Java i C#, permetent accedir a milers de biblioteques d'alta qualitat.

Exemple: Hola món [modifica]

Per començar:

Al Linux el podeu instal·lar pels paquets de la distribució. Altrament el compilador es pot descarregar d'aquí[1] o com endollable en un entorn IDE aquí[2]

El programa Hola món en Scala:

 // fitxer test/hola-mon.scala
 package test
 
 object Principal {
    def main(args: Array[String]) = Console.println("Hola món!")
 }

alternativa

 // fitxer test/hola-mon.scala
 package test
 
 object Principal extends Application { // Application defineix main
    Console.println("Hola món!")        // la inicialització de l'objecte executa les expressions del cos.
 }
  • Compilació i execució a consola de comandes:[3]
cd objdir
scalac ../src/test/hola-mon.scala

scala test.Principal          # execució pel nom de l'objecte que conté el mètode ''main''

Hola món!
  • A l'avaluador d'expressions (bucle Read-Eval-Print)
scala

scala> println( "Hola món")
Hola món

scala>

Característiques [modifica]

Degut a ésser un llenguatge dissenyat inicialment per a la màquina virtual JVM, hereta del Java les característiques del lèxic i els tipus bàsics i les seves operacions així com una sintaxi molt similar.

Els punt-i-coma a final de línia es poden ometre (des de la versió 2).

tipus Unit [modifica]

Equival al tipus buit (void en Java) de les instruccions que no retornen res, habitualment assignacions i altres efectes laterals.

El seu únic valor és: ()       // no-op : no fer res (element neutre de les operacions)

altres tipus especials [modifica]

Vegeu ref.[4]

Any
generalització d'un tipus qualsevol
AnyVal
generalització dels tipus bàsics que es passen per valor.
AnyRef
generalització dels tipus que es passen per referència. Correspon a Java.lang.Object
ScalaObject
base per als objectes de Scala
Null
es considera subtipus de qualsevol classe o objecte, així el seu valor null pot pertànyer a totes elles.
Nothing
subtipus de tots els tipus.

restriccions en els tipus [modifica]

Els tipus poden parametritzar funcions, classes, objectes i trets. Admeten a més restriccions especials.

En el següent exemple Tipus ha d'ésser subtipus de TCotaSuperior.[5]

type Tipus <: TCotaSuperior

en el següent exemple Tipus ha d'ésser superclasse de TCotaInferior.[6]

type Tipus >: TCotaInferior

Convertibilitat

type A <% T // indica que A ha de ser convertible en T mitjançant una conversió implícita. Vegeu Scala Views[7]
trait Set[A <% Ordered[A]] ...
class EmptySet[A <% Ordered[A]] ...
class NonEmptySet[A <% Ordered[A]] ...

encaix segons el valor o el tipus [modifica]

Primer valors, després tipus

package test ;
 
object Main extends Application {
 
  val llista: List[Any] = List(true, 'c', 8:Byte, 270:Short, 300, 200000000000L, 2.5F, 3.12345678, "abc") ;
  for (elem <- llista) {
    elem match {
           case 2 | 3 => print( "dos o tres") ;
           case v :Char => printf("%c u\\%04x", v, v.toInt ) ;  // caràcter i hexadecimal
           case v :Byte => printf("és un byte: %d", v) ;
           case v :Short => printf("és un short: %d", v) ;
           case v :Int  => printf("és un int: %d 0%o x%08x", v, v, v) ;     // decimal, octal i hexad.
           case v :Long => printf("%d", v) ;
           case v :Float => printf("%.2f", v) ;
           case v :Double => printf("%.8f", v) ;
           case v :String => printf("%s", v) ;
           case v :AnyRef => print( v.toString) ;  
           case v => print( v) ;                       
    }
    println("") 
  }
}

dóna

true
c u\0063
és un byte: 8
és un short: 270
és un int: 300 0454 x0000012c
200000000000
2,50
3,12345678
abc

polimorfisme paramètric [modifica]

A més del polimorfisme per especialització dels objectes, les funcions es poden parametritzar per Tipus

 def nom_funció[VariableDeTipus](param1: VariableDeTipus, ..) = ...

exemple:

object Main extends Application {
  def imprimeix[T]( dada: T) = 
    dada match {
      case v: String => println( v) ;
      case v => println (v.toString) ;
    }
  imprimeix[Int]( 5) ;
  imprimeix[String]( "abc") ;
  imprimeix( 2) ;              // si no s'explicita el tipus es dedueix dels paràmetres actuals.
  imprimeix( "def") ;
}

classes "per cas" per implementar tipus "suma" algebraics [modifica]

El que en altres lleng. funcionals es descriu com a unió de tipus discriminats per etiquetes anomenades constructors, aquí es parteix de la classe que identifica el tipus i se'n deriven classes per cada cas de la unió discriminada, amb el constructor per nom i paràmetres corresponents als components del cas.


abstract class Arbre[T]
// ''val'' al paràmetre el fa consultable externament (és membre de la classe) 
case class Fulla[T]( val dada: T) extends Arbre[T] 
case class Branca[T]( val dada: T, val esquerra: Arbre[T], val dreta: Arbre[T]) extends Arbre[T]
 
object Main extends Application { 
 
  def imprimeixArbre[T]( arbre: Arbre[T]):Unit = 
    arbre match {
            case Fulla( d) => println ("fulla: " ++ d.toString)
            case Branca( d, esq, dreta) => { imprimeixArbre( esq) ;
                                             println("branca: " ++ d.toString) ;
                                             imprimeixArbre( dreta) ;
                                           }
    }
  val arbre1 = new Fulla( 1) ;   // si s'omet el paràmetre de tipus ''[T]'', es pren el del literal.   
  val arbre2 = new Branca[Int]( 2, arbre1, arbre1) ;
  imprimeixArbre( arbre2) ;
}

Equivalència en ML Estàndard:

datatype 't Arbre = Fulla of 't | Branca of ('t * 't Arbre * 't Arbre)

Equivalència en Haskell:

data Arbre t = Fulla t | Branca t (Arbre t) (Arbre t)

Vegeu exemple #Encaixos de patrons.

Llistes [modifica]

object Main extends Application {
  val llista = List( 1, 2, 3) ;
  def descriuLlista[T]( llista: List[T]) = 
    llista match {
             case Nil => println ("llista buida") ;
 
             case ll @ _::_ =>       // as-pattern (variable @ patró): unifica variable i terme encaixat
                          println ("llista no buida: " + ll.toString) ;
    }
  descriuLlista( llista )
}

Llistes per comprensió [modifica]

La clàusula for admet una primera part amb generadors i filtres (clàusula if), i una segona part de mapeig que pot ésser o bé un bloc imperatiu d'efectes laterals, o bé una clàusula yield amb una expressió o bloc que retorna una llista resultant de l'aplicació del bloc a la llista del generador.

// retorna la llista dels dobles dels parells de l'interval

for (i <- Iterator.range( des_de, topall_exclòs) if i % 2 == 0) yield 2 * i

Variables [modifica]

El tipus de les declaracions es pot ometre si es dedueix de la seva inicialització de manera inequívoca, altrament el compilador avisarà.

val nom_var :tipus = ..     // amb val: variable assignable un sol cop
var nom_var :tipus = ..     // amb var: variable assignable més d'un cop

Operadors [modifica]

Els operadors són mètodes definits amb símbols.

class Q {
          def ##(that:Q) = this != that
        }

La precedència la determina el primer dels símbols. (Vegeu apartat 'Infix operators' al manual de ref. del llenguatge).

(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)

L'associativitat la determina el darrer símbol, que si és ':' llavors és associatiu per la dreta, altrament associatiu per l'esquerra.

Tuples [modifica]

Definides les classes Tuple2, Tuple3, .., Tuple22.
Pair equival a Tuple2, Triple a Tuple3
object Main extends Application {
 
  val parell = new Pair( 10, "abc") ;
 
  val parell2 = Pair( 10, "abc") ; // alternativa amb el mètode ''fàbrica d'instàncies'' 
                                   // (ang: ''factory method'') a l'objecte Pair.
 
  val Pair(primer, segon) = parell ;  // encaix de la tupla
 
  println( primer) ;
  println( segon) ;
}

Classes i mòduls Object [modifica]

En Scala se separen les parts dinàmica i estàtica de les classes del Java en class i object (mòdul no instanciable que conté els membres estàtics), com a l'OCaml.

Extensibilitat. Els mòduls object tenen un tractament unificat amb les classes respecte a l'extensibilitat com si fossin classes d'una sola instància (singleton) que els permet implementar interfaces i estendre'ls amb altres object i traits com a l'exemple amb l' object Application.

Grafia. Els identificadors dels mòduls object comencen per majúscula segons el llibre d'estil.

La inicialització dels mòduls object i també de les classes, es produeix seqüencialment processant definicions i instruccions executables, com a l'ML Estàndard i l'OCaml.

// ''Application'' és l' ''object'' d'engegada que conté el mètode ''main''
 
object ProvaFiltratge extends Application {
 
  def filtrar(xs: List[Int], llindar: Int) = {
 
    def processa( ys: List[Int]): List[Int] =    // funció a l'interior d'una altra funció
      if (ys.isEmpty) ys
      else if (ys.head >= llindar) ys.head :: processa( ys.tail)
      else processa( ys.tail)
 
    processa( xs)
  }
  println( filtrar( List(1, 9, 2, 8, 3, 7, 4), 5))
}

En importar una classe de Java, l'identificador designa la classe equivalent en Scala amb els mètodes dinàmics, així com l' Object que conté els mètodes, variables i constants estàtics.

import java.lang.{Color}
val vermell = new Color( 0xFF, 0, 0) ;                    // constructor de la ''classe''
val componentRoigDelBlanc = Color.getRed( Color.WHITE) ;  // membres estàtics de l' ''Object''
override
els mètodes que es redefineixen han de dur el qualificatiu override per distingir-los dels que es volen nous, per evitar que si algú afegeix un mètode amb el mateix nom i signatura a alguna de les superclasses o trets que s'hereten el comportament esdevingui diferent del que se n'espera.

Trets: variables, operacions i tipus, incorporables a classes i mòduls object [modifica]

Assimilables als interface del Java, però amb el potencial d'una classe abstracta.

Els trets poden contenir definició de tipus, variables i mètodes, i també implementacions dels mètodes, però no són instanciables per si mateixos, ni poden tenir paràmetres de valor.

import java.awt.{Color} ;
 
trait Acoloriment {
        var color:Color ; 
        def pinta( nouColor: Color): Unit = { color = nouColor}
        def imprimeixColor: Unit = { print( "color: ") ; println( color) } 
}
 
trait Cloneable extends java.lang.Cloneable {
  override def clone(): Cloneable = { super.clone(); this }
}
 
trait Resetable {
  def reset: Unit
}
 
def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
  val cloned = obj.clone()
  obj.reset
  cloned
}

herència múltiple [modifica]

L'herència múltiple es basa en la incorporació de trets.

import java.awt.{Color} ;
 
class Punt(xInicial:Int) {
        var x: Double = xInicial.toDouble ;
        def desplaça( dx: Double): Unit = { x = x + dx}
        def imprimeixPosició: Unit = { print( "posició: ") ; println( x) } 
}
 
trait Acoloriment {
        var color: Color ; 
        def pinta( nouColor: Color): Unit = { color = nouColor}
        def imprimeixColor: Unit = { print( "color: ") ; println( color) } 
}
 
class PuntAcolorit( xInicial:Int, colorInicial: Color) extends Punt( xInicial) with Acoloriment {
 
        var color = colorInicial ;
 
        def desplaçaIPinta( dx: Double, nouColor: Color) = { 
 
          super.desplaça(dx) ;
          super.pinta(nouColor) ;
        }
}
 
object Main extends Application {
 
  val punt = new PuntAcolorit( 0, Color.WHITE) {   // extensió en instanciar
                                      // només aquesta instància incorpora l'extensió
 
          def desplaçaRàpid( dx: Double) = { 
                  x = x + 10.0 * dx
          }
  }
  punt.desplaçaIPinta(2, Color.BLUE) ;
  punt.desplaçaRàpid( 3.5)
  punt.imprimeixPosició ;
  punt.imprimeixColor ;
}

dóna el resultat:

posició: 37.0
color: java.awt.Color[r=0,g=0,b=255]

funcions anònimes com a expressió [modifica]

exemple:

(x: Int, y:Int) => x + y         // el tipus del resultat és deduït per inferència en aquest cas

En l'exemple següent el compilador dedueix els tipus dels paràmetres de la funció sobre la qual s'aplica.

object Main extends Application {
  val llista = List(1,2,3,4) ;  // pels literals infereix tipus List[Int]
 
  // aplica la funció a un acumulador i cada valor de la llista
  // els tipus dels paràmetres els dedueix de l'aplicació parcial (funció ometent paràmetres) precedent.
  //     tipus de llista.foldleft( 0) : (Int * Int) => Int
 
  val result = llista.foldLeft( 0) { (x,y) => x+y } ; 
 
  Console.print("resultat: ") ;
  Console.println( result);
}

dóna l'esperat

resultat: 10

funcions d'ordre superior [modifica]

Amb funcions als paràmetres o al resultat.

// en aquest cas, funció que pren una funció d'argument i en retorna una altra
 
def sum(f: Int => Int): (Int, Int) => Int = {
 
  def sumF(a: Int, b: Int): Int =             // suma f(x), x <- [a..b]
    if (a > b) 0 else f(a) + sumF(a + 1, b)
 
  &sumF
}
 
def sumaDobles = &sum( x => 2 * x)
def sumaQuadrats = &sum( x => x * x)

Assercions [modifica]

Vegeu Assercions[8] i Opció de compilació -enableassertions[3]

assert( predicat [,missatge]) 
especifica un predicat que cal provar i dispara l'excepció java.lang.AssertionError: assertion failed: missatge
assume( axioma [,missatge]) 
especifica un axioma. Dispara l'excepció java.lang.AssertionError: assumption failed: missatge
require( predicat [,missatge]) 
com assert però blasma la funció que el crida,[8] llançant l'excepció IllegalArgumentException: requirement failed
error( missatge)

XML al codi [modifica]

Vegeu [9]

object Main extends Application {
  val idioma = "ca" ;
  val títol = "El meu títol" ;
  val xml_títol = <title> {títol} </title> ;    // entre claus '{' <expr> '}' substitució d'expressions.
  val xml_capsalera = <head> {xml_títol} </head>
 
  // substitució a l'atribut, hi afegeix les cometes.
  val xml_pàgina = <html lang={idioma}>  
                     {xml_capsalera} 
                     <body> Aquesta pàgina porta el títol {títol} </body>
                   </html> ;
  val capsal_xml ="<?xml version='1.0' encoding='UTF-8' ?>\n" ;
  val doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " +
           " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" ;
  println( capsal_xml + doctype + xml_pàgina) ;
}

Genèrics mitjançant mòduls implícits (implicit object) [modifica]

Classes genèriques (parametritzades en tipus) per agrupar funcions. Les implementacions d'aquestes classes per a tipus concrets, constitueixen mòduls de instància única (singleton) que es passaran de manera implícita (implicit object).

La obtenció de la instància adequada al tipus de la crida és automàtica, mitjançant un paràmetre implícit (absent en la crida) del tipus del genèric. Permeten diversificar el tipus retornat per una funció.

A l'exemple el paràmetre (implicit m: Monoid[A]), m obtindrà el valor de la instància específica del genèric Monoid[A] per al tipus de A emprat en la crida a la funció def suma[A](xs: List[A])(implicit m: Monoid[A]).

    abstract class SemiGroup[A] {
      def add(x: A, y: A): A
    }
 
    abstract class Monoid[A] extends SemiGroup[A] {
      def unit: A
    }
    object ImplicitTest extends Application {
 
      // mòdul instància de Monoid per al tipus String
 
      implicit object StringMonoid extends Monoid[String] {
        def add(x: String, y: String): String = x concat y
        def unit: String = ""
      }
 
      // mòdul instància de Monoid per al tipus Int
 
      implicit object IntMonoid extends Monoid[Int] {
        def add(x: Int, y: Int): Int = x + y
        def unit: Int = 0
      }
 
      // param. implícit selecciona instància segons param. de tipus
      // entre els ''implícit object''s visibles en l'àmbit.
 
      def suma[A](xs: List[A])(implicit m: Monoid[A]): A =
        if (xs.isEmpty) m.unit
        else m.add(xs.head, suma(xs.tail))
 
      println(suma(List(1, 2, 3)))
      println(suma(List("a", "b", "c")))
    }

Parametrització de tipus amb cota superior [modifica]

Admetre tipus més especialitzats que un tipus determinat.

trait Similar {
  def isSimilar(x: Any): Boolean
}
 
case class MyInt(x: Int) extends Similar {
  def isSimilar(m: Any): Boolean =
    m.isInstanceOf[MyInt] &&
    m.asInstanceOf[MyInt].x == x
}
 
object UpperBoundTest extends Application {
 
  def findSimilar[T <: Similar](e: T, xs: List[T]): Boolean =
    if (xs.isEmpty) false
    else if (e.isSimilar(xs.head)) true
    else findSimilar[T](e, xs.tail)
 
  val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3))
 
  println(findSimilar[MyInt](MyInt(4), list))
  println(findSimilar[MyInt](MyInt(2), list))
}

La API de Scala [modifica]

Scala té una llarga biblioteca per facilitar la feina amb varietat de col·leccions immutables i mudables així com tractament de XML i altres que trobareu aquí.[10]

L'especificació oficial del llenguatge és aquí.[11]

Els elements predefinits són a l' object Predef[12]

Entorns de desenvolupament [modifica]

La millor manera de treballar amb Scala és descarregant d'aquí[2] l'endollable per a l'Eclipse (o altres entorns de desenvolupament Java) que ja incorpora el compilador i les biblioteques de les quals, clicant, se'n pot examinar el codi font.

Scala a l'Eclipse [modifica]

A l'Eclipse[13], un cop incorporat l'endollable al menú Help->Install new software podrem crear un "Projecte Scala" que incorporarà automàticament les biblioteques de Scala al projecte si ho fem amb el menú de context de la barra lateral esquerre a l'opció "New -> Project -> Scala Wizards -> Scala Project" del menú de context de la barra lateral de projectes.

Scala segueix la mateixa estructura de mòduls (package) que el Java. Tantmateix podem posar diversos objects, classes i traits al mateix fitxer de codi font.

És habitual crear primer sobre el directori src, abreviació de source (codi font), un Package amb nom on crear els fonts, si volem facilitar l'estructuració modular o la inter-operabilitat amb paquets d'altres projectes.

Després podrem triar, al menú de context del package, els assistents (ang:wizards) de generació d'esquelets Scala Application, Scala Object, Scala Class o Scala Trait

Execució: per cada projecte cal crear una configuració d'engegada que podrem desar, especificant projecte, nom de l'objecte que conté el mètode main i possibles paràmetres de l'aplicació. Clicant el menú de context del projecte, opcions "RunAs -> Run configurations -> especificar la configuració o seleccionar-la -> botó Run"

Exemples [modifica]

Encaixos de patrons [modifica]

package test              // fitxer: test/LaMevaApp.scala
 
abstract class Llista ;
 
trait Imprimible {                          // en Java seria un ''interface''
                                            // admet definició de tipus i implementació de mètodes.
 
  def imprimeix: Unit ;                     // tipus Unit: equival al ''void'' de Java i C
} 
 
trait Igualable {
  def igual_que( aquell: Any): Boolean ;
  def desigual_que( aquell:Any): Boolean = ! igual_que( aquell) ;  // amb implementació inclosa
}
 
// herència múltiple basada en ''mixins'' (cat: barrejables): traits
 
class LlistaImprimible extends Llista with Imprimible with Igualable {     
 
  def imprimeix: Unit = this match {        // ''this'' es refereix a la instància
 
    case LlistaCons( cap, cua) => {         // patró LlistaCons
 
      cap match {                           // encaix segons el tipus
        case v:Int => printf("%d", v) ;
        case v:Float => printf("%.2f", v) ; 
        case _ => () ;                      // valor () de tipus Unit equival a ''no-op'' (no fer res)
      }
 
      print( " ") ;
 
      cua.imprimeix ;
      }
    case LlistaNil () => println ("Fi")     // patró LlistaNil
    }
 
  def igual_que( aquell:Any): Boolean = 
          // refinament amb guarda: comprova la subclasse (''isInstanceOf'')
          //   i, si té èxit, en caracteritza el tipus (''asInstanceOf'')
 
          aquell.isInstanceOf[LlistaImprimible] &&
              aquell.asInstanceOf[LlistaImprimible] match {
 
                      case LlistaNil () => this match {
                                                  case LlistaNil () => true
                                                  case _ => false
                                                  }
                      case LlistaCons (aquell_cap, aquella_cua) => this match {
                                                  case LlistaCons (aquest_cap, aquesta_cua) =>
                                                         aquest_cap == aquell_cap &&
                                                             aquesta_cua.igual_que( aquella_cua) ;
 
                                                  case _ => false
                                                  }   
                      }
 
}
 
// definició dels patrons
// 
// en lleng. SML seria:   
//    datatype 'tip_elem Llista = LlistaNil | LlistaCons of ('tip_elem * 'tip_elem Llista)
//
// en lleng. Haskell seria:  
//    data Llista tip_elem = LlistaNil | LlistaCons tip_elem (Llista tip_elem)
//    class Imprimible a where
//      imprimeix :: a -> Unit
//    instance Imprimible (Llista tip_elem) where ... (implementació)
 
case class LlistaNil() extends LlistaImprimible ; 
case class LlistaCons[Tip_elem](cap: Tip_elem, cua: LlistaImprimible ) extends LlistaImprimible ; 
 
 
object LaMevaApp extends Application {
 
  override def main(args : Array[String]) : Unit = {
 
    val llista1 = new LlistaNil() ;                           // val: assignable un sol cop
    val llista2 = new LlistaCons[AnyVal](1, llista1) ;        // AnyVal: qualsevol valor escalar (String exclòs)
                                                              // AnyRef: qualsevol per referència (inclou String)
    var llista = new LlistaCons[AnyVal](2.5F, llista2) ;      // var: assignable més d'un cop
 
 
    for (val v <- Iterator.range(4,9)) {       // de 4 a 9 exclòs el darrer
      llista = new LlistaCons[AnyVal]( v, llista)
    }
 
    llista.imprimeix ;
  }
}
# compilació a l'Eclipse: clicar al menú de context RunAs -> Run configurations 
#  -> doble-clic a Scala application -> New Configuration 
#  -> Ajustar el nom de l'objecte d'engegada (el que deriva de Application o conté el mètode main) 
#  -> prémer botó Run
 
# compilació en consola de comandes
cd objdir
scalac ../src/test/LaMevaApp.scala

# execució i resultat (cal cridar el nom de l'objecte que conté el mètode main o que deriva l'objecte Application).
scala test.LaMevaApp

8 7 6 5 4 2.50 1 Fi

Exemples a LiteratePrograms.org [modifica]

Referències [modifica]

  1. Scala - descàrregues(anglès)
  2. 2,0 2,1 Endollables Scala a diversos entorns de desenv. (anglès)
  3. 3,0 3,1 Scala - Opcions d'execució(anglès)
  4. Tipus unificats(anglès)
  5. Cota superior en els tipus(anglès)
  6. Cota inferior en els tipus(anglès)
  7. A tour of Scala: Views
  8. 8,0 8,1 Assercions(anglès)
  9. Scala Tour - XML(anglès)
  10. La API de Scala (anglès)
  11. Manuals del llenguatge(anglès)
  12. Objecte Predef(anglès) tipus i funcions predefinits. Predefinits en format nou
  13. Eclipse (Entorn de desenvolupament)(anglès)
  14. Camí més curt segons alg. de Dijkstra en Scala (anglès) amb exemple Barcelona - Lausanne
  15. Ordenació per comptatge(anglès)
  16. Ordenació per QuickSort(anglès)
  17. Ordenació per inserció(anglès)
  18. Sèrie de Fibonaci(anglès)

Enllaços externs [modifica]

Guies:

Exemples:

Recursos:

Articles: