diff --git a/_es/tour/basics.md b/_es/tour/basics.md index bd86428a9b..80977f061b 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -6,4 +6,319 @@ discourse: false partof: scala-tour language: es + +num: 2 +next-page: unified-types +previous-page: tour-of-scala --- + +En esta página, practicaremos conceptos básicos de Scala. + +## Probando Scala en el navegador + +Puedes ejecutar Scala en tu navegador con ScalaFiddle. + +1. Ve a [https://scalafiddle.io](https://scalafiddle.io). +2. Escribe `println("Hello, world!")` en el panel a la izquierda. +3. Presiona el botón "Run". En el panel de la derecha aparecerá el resultado. + +Así, de manera fácil y sin preparación, puedes probar fragmentos de código Scala. + +Muchos ejemplos de código en esta documentación están integrados con ScalaFiddle, y así puedes probarlos directamente solo con pulsar el botón "Run". + +## Expresiones + +Las expresiones son sentencias computables. + +```tut +1 + 1 +``` + +Se puede ver el resultado de evaluar expresiones usando `println`. + +{% scalafiddle %} +```tut +println(1) // 1 +println(1 + 1) // 2 +println("Hello!") // Hello! +println("Hello," + " world!") // Hello, world! +``` +{% endscalafiddle %} + +## Valores + +Se puede dar un nombre al resultado de una expresión usando la palabra reservada `val`. + +```tut +val x = 1 + 1 +println(x) // 2 +``` + +Los resultados con nombre, como `x` en el ejemplo, son llamados valores. Referenciar un valor no lo vuelve a computar. + +Los valores no pueden ser reasignados. + +```tut:fail +x = 3 // This does not compile. +``` + +Scala es capaz de inferir el tipo de un valor. Aun así, también se puede indicar el tipo usando una anotación: + +```tut +val x: Int = 1 + 1 +``` + +Nótese que la anotación del tipo `Int` sigue al identificador `x` de la variable, separado por dos puntos `:`. + +## Variables + +Una variable es como un valor, excepto que a una variable se le puede re-asignar un valor después de declararla. Una variable se declara con la palabra reservada `var`. + +```tut +var x = 1 + 1 +x = 3 // This compiles because "x" is declared with the "var" keyword. +println(x * x) // 9 +``` + +Como con los valores, si se quiere se puede especificar el tipo de una variable mutable: + +```tut +var x: Int = 1 + 1 +``` + +## Bloques + +Se pueden combinar expresiones rodeándolas con `{}` . A esto le llamamos un bloque. + +El resultado de la última expresión del bloque es también el resultado total del bloque. + +```tut +println({ + val x = 1 + 1 + x + 1 +}) // 3 +``` + +## Funciones + +Una función es una expresión que acepta parámetros. + +Una función se puede declarar anónima, sin nombre. Por ejemplo, ésta es una función que acepta un número entero `x`, y devuelve el resultado de incrementarlo: + +```tut +(x: Int) => x + 1 +``` + +La lista de parámetros de la función está a la izquierda de la flecha `=>`, y a su derecha está el cuerpo de la función. + +También podemos asignarle un nombre a la función. + +{% scalafiddle %} +```tut +val addOne = (x: Int) => x + 1 +println(addOne(1)) // 2 +``` +{% endscalafiddle %} + +Las funciones pueden tomar varios parámetros. + +{% scalafiddle %} +```tut +val add = (x: Int, y: Int) => x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +O ninguno. + +```tut +val getTheAnswer = () => 42 +println(getTheAnswer()) // 42 +``` + +## Métodos + +Los métodos se parecen y comportan casi como a las funciones, pero se diferencian en dos aspectos clave: + +Un método se define con la palabra reservada `def`, seguida por el nombre del método, la lista de parámetros, el tipo de valores que el método devuelve, y el cuerpo del método. + +{% scalafiddle %} +```tut +def add(x: Int, y: Int): Int = x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +Observe que el tipo de retorno se declara _después_ de la lista de parámetros, y separado con dos puntos, p.ej. `: Int`. + +Un método puede tener varias listas de parámetros. + +{% scalafiddle %} +```tut +def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier +println(addThenMultiply(1, 2)(3)) // 9 +``` +{% endscalafiddle %} + +O ninguna lista de parámetros. + +```tut +def name: String = System.getProperty("user.name") +println("Hello, " + name + "!") +``` + +Hay otras diferencias, pero para simplificar, podemos pensar que son similares a las funciones. + +Los métodos también pueden tener expresiones de varias lineas. + +```tut +def getSquareString(input: Double): String = { + val square = input * input + square.toString +} +``` + +La ultima expresión en el cuerpo del método es el valor de retorno del mismo. +(Scala tiene una palabra reservada `return`, pero se usa raramente y no se aconseja usarla) + +## Clases + +Una clase se define con la palabra reservada `class`, seguida del nombre, y la lista de parámetros del constructor. + +```tut +class Greeter(prefix: String, suffix: String) { + def greet(name: String): Unit = + println(prefix + name + suffix) +} +``` + +El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que en Scala toda expresión debe devolver un valor. Por ello, se usa un tipo `Unit` que tiene con un solo valor que se escribe `()` y no lleva información. + +Se puede crear una instancia de una clase con la palabra reservada *new*. + +```tut +val greeter = new Greeter("Hello, ", "!") +greeter.greet("Scala developer") // Hello, Scala developer! +``` + +Las clases se tratan en profundidad [más adelante](classes.html). + +## Case Classes + +Hay un tipo especial de clases en Scala, las llamadas "case" classes. Por defecto, las instancias de una case class son inmutables, y se comparan con otras solo por los valores que contienen en cada campo. +Una case class se define con las palabras reservadas `case class`: + +```tut +case class Point(x: Int, y: Int) +``` + +Se puede crear una instancia de una `case class`, sin usar la palabra reservada `new`. + +```tut +val point = Point(1, 2) +val anotherPoint = Point(1, 2) +val yetAnotherPoint = Point(2, 2) +``` + +Y son comparadas por valor. + +```tut +if (point == anotherPoint) { + println(point + " and " + anotherPoint + " are the same.") +} else { + println(point + " and " + anotherPoint + " are different.") +} // Point(1,2) and Point(1,2) are the same. + +if (point == yetAnotherPoint) { + println(point + " and " + yetAnotherPoint + " are the same.") +} else { + println(point + " and " + yetAnotherPoint + " are different.") +} // Point(1,2) and Point(2,2) are different. +``` + +Hay mucho más sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Se tratan con más detalle [mas adelante](case-classes.html). + +## Objetos + +Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como _singleton_ de sus propias clases. + +Un objeto se define usando la palabra reservada `object`. + +```tut +object IdFactory { + private var counter = 0 + def create(): Int = { + counter += 1 + counter + } +} +``` + +Para acceder al objeto, lo referencias por su nombre. + +```tut +val newId: Int = IdFactory.create() +println(newId) // 1 +val newerId: Int = IdFactory.create() +println(newerId) // 2 +``` + +Cubriremos los objetos en profundidad [más adelante](singleton-objects.html). + +## Traits + +Los traits son tipos que contienen campos y métodos. Se pueden combinar múltiples traits. + +Un trait se define usando la palabra reservada `trait`. + +```tut +trait Greeter { + def greet(name: String): Unit +} +``` + +Un `trait` también puede definir un método, o un valor, con una implementación por defecto. + +{% scalafiddle %} +```tut +trait Greeter { + def greet(name: String): Unit = + println("Hello, " + name + "!") +} +``` + +Un `trait` también puede extender otros traits, usando la palabra clave `extends`. Asimismo, en un `trait` se puede redefinir la implementación de un método heredado, usando la palabra reservada `override`. + +```tut +class DefaultGreeter extends Greeter + +class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { + override def greet(name: String): Unit = { + println(prefix + name + postfix) + } +} + +val greeter = new DefaultGreeter() +greeter.greet("Scala developer") // Hello, Scala developer! + +val customGreeter = new CustomizableGreeter("How are you, ", "?") +customGreeter.greet("Scala developer") // How are you, Scala developer? +``` +{% endscalafiddle %} + +Aquí, `DefaultGreeter` extiende un solo trait, pero puede extender múltiples traits. + +Los `traits` se tratan con detalle [en otra página](traits.html). + +## Método principal (Main Method) + +El método principal (main) es el punto donde comienza la ejecución de un programa en Scala. La máquina virtual de java (_Java Virtual Machine_ or JVM) requiere, para ejecutar un código Scala, que éste tenga un método principal llamado `main` cuyo único parámetro sea un arrray de Strings. + +Usando un objeto, puedes definir el método principal de la siguiente forma: + +```tut +object Main { + def main(args: Array[String]): Unit = + println("Hello, Scala developer!") +} +``` diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index b776a87a6b..117e52b90b 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -27,7 +27,7 @@ This table shows the first Scala release in each series that works with each JVM We recommend using Java 8 for *compiling* Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to *run* your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9. The Scala compiler does usually need updates to run properly on newer versions of the JVM, so make sure to use the appropriate JVM when compiling your code. -We try to provide experimental support for running the Scala compiler on LTS versions of Java ("Long Term Support"; see http://www.oracle.com/technetwork/java/eol-135779.html), and to the extent possible will include the current LTS Java version in our CI matrix and the community build. We will not, a priori, consider non-LTS Java versions. Compiler bugs related to Java versions other than the supported one (Java 8), will be scheduled with lower priority, and will not be considered release blockers. Lightbend does offer commercial support for faster resolution of issues like this. +We try to provide experimental support for running the Scala compiler on LTS versions of Java ("Long Term Support"; see ), and to the extent possible will include the current LTS Java version in our CI matrix and the community build. We will not, a priori, consider non-LTS Java versions. Compiler bugs related to Java versions other than the supported one (Java 8), will be scheduled with lower priority, and will not be considered release blockers. Lightbend does offer commercial support for faster resolution of issues like this. Scala code compiled on Java 8 should run without problems in later JVMs, and we will give higher priority to bugs that break this property. For example, in the 2.13.x series we intend to provide support for JPMS module access checks, to allow ensuring your code won't incur `LinkageErrors` due to module access violations. diff --git a/_pl/tour/case-classes.md b/_pl/tour/case-classes.md index 48c6683418..bc67870201 100644 --- a/_pl/tour/case-classes.md +++ b/_pl/tour/case-classes.md @@ -6,128 +6,70 @@ discourse: false partof: scala-tour -num: 10 +num: 11 language: pl next-page: pattern-matching previous-page: multiple-parameter-lists --- -Scala wspiera mechanizm _klas przypadków_. Klasy przypadków są zwykłymi klasami z dodatkowymi założeniami: +Scala wspiera mechanizm _klas przypadków_ (ang. case class). +Są one zwykłymi klasami z dodatkowymi założeniami, przez które przejdziemy. +Klasy przypadków idealnie nadają się do modelowania niezmiennych (niemutowalnych) danych. +W dalszych rozdziałach przyjrzymy się jak przydają się w [dopasowywaniu wzorców (ang. pattern matching)](pattern-matching.html). -* Domyślnie niemutowalne -* Można je dekomponować poprzez [dopasowanie wzorca](pattern-matching.html) -* Porównywane poprzez podobieństwo strukturalne zamiast przez referencje -* Zwięzła składnia tworzenia obiektów i operacji na nich +## Definiowanie klas przypadków -Poniższy przykład obrazuje hierarchię typów powiadomień, która składa się z abstrakcyjnej klasy `Notification` oraz trzech konkretnych rodzajów zaimplementowanych jako klasy przypadków `Email`, `SMS` i `VoiceRecording`: +Minimalna definicja klasy przypadku wymaga słów kluczowych `case class`, identyfikatora oraz listy parametrów (może być pusta): ```tut -abstract class Notification -case class Email(sourceEmail: String, title: String, body: String) extends Notification -case class SMS(sourceNumber: String, message: String) extends Notification -case class VoiceRecording(contactName: String, link: String) extends Notification -``` - -Tworzenie obiektu jest bardzo proste: (Zwróć uwagę na to, że słowo `new` nie jest wymagane) +case class Book(isbn: String) -```tut -val emailFromJohn = Email("john.doe@mail.com", "Greetings From John!", "Hello World!") +val frankenstein = Book("978-0486282114") ``` -Parametry konstruktora klasy przypadków są traktowane jako publiczne wartości i można się do nich odwoływać bezpośrednio: +Zauważ, że słowo kluczowe `new` nie było konieczne do stworzenia instancji klasy przypadku `Book`. +Jest tak, ponieważ klasy przypadków posiadają domyślnie zdefiniowaną metodę `apply`, która zajmuje się tworzeniem obiektu klasy. -```tut -val title = emailFromJohn.title -println(title) // wypisuje "Greetings From John!" -``` +W przypadku, kiedy tworzymy klasę przypadku zawierającą parametry, są one publiczne i stałe (`val`). -W klasach przypadków nie można modyfikować wartości pól. (Z wyjątkiem sytuacji kiedy dodasz `var` przed nazwą pola) - -```tut:fail -emailFromJohn.title = "Goodbye From John!" // Jest to błąd kompilacji, gdyż pola klasy przypadku są domyślnie niezmienne ``` +case class Message(sender: String, recipient: String, body: String) +val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?") -Zamiast tego możesz utworzyć kopię używając metody `copy`: - -```tut -val editedEmail = emailFromJohn.copy(title = "I am learning Scala!", body = "It's so cool!") - -println(emailFromJohn) // wypisuje "Email(john.doe@mail.com,Greetings From John!,Hello World!)" -println(editedEmail) // wypisuje "Email(john.doe@mail.com,I am learning Scala,It's so cool!)" +println(message1.sender) // wypisze guillaume@quebec.ca +message1.sender = "travis@washington.us" // ten wiersz nie skompiluje się ``` -Dla każdej klasy przypadku kompilator Scali wygeneruje metodę `equals` implementującą strukturalne porównanie obiektów oraz metodę `toString`. Przykład: +Nie można ponownie przydzielić wartości do `message1.sender`, ponieważ jest to `val` (stała). +Alternatywnie, w klasach przypadków można też używać `var`, jednak stanowczo tego odradzamy. -```tut -val firstSms = SMS("12345", "Hello!") -val secondSms = SMS("12345", "Hello!") - -if (firstSms == secondSms) { - println("They are equal!") -} +## Porównywanie -println("SMS is: " + firstSms) -``` +Klasy przypadków są porównywane według ich struktury, a nie przez referencje: -Wypisze: +```tut +case class Message(sender: String, recipient: String, body: String) -``` -They are equal! -SMS is: SMS(12345, Hello!) +val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val messagesAreTheSame = message2 == message3 // true ``` -Jednym z najważniejszych zastosowań klas przypadków (skąd też się wzięła ich nazwa) jest **dopasowanie wzorca**. Poniższy przykład pokazuje działanie funkcji, która zwraca różne komunikaty w zależności od rodzaju powiadomienia: +Mimo, że `message1` oraz `message2` odnoszą się do innych obiektów, to ich wartości są identyczne. -```tut -def showNotification(notification: Notification): String = { - notification match { - case Email(email, title, _) => - "You got an email from " + email + " with title: " + title - case SMS(number, message) => - "You got an SMS from " + number + "! Message: " + message - case VoiceRecording(name, link) => - "you received a Voice Recording from " + name + "! Click the link to hear it: " + link - } -} - -val someSms = SMS("12345", "Are you there?") -val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123") - -println(showNotification(someSms)) // Wypisuje "You got an SMS from 12345! Message: Are you there?" -println(showNotification(someVoiceRecording)) // Wypisuje "you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123" -``` +## Kopiowanie -Poniżej bardziej skomplikowany przykład używający `if` w celu określenia dodatkowych warunków dopasowania: +Możliwe jest stworzenie płytkiej kopii (ang. shallow copy) instancji klasy przypadku używając metody `copy`. +Opcjonalnie można zmienić jeszcze wybrane parametry konstruktora. ```tut -def showNotificationSpecial(notification: Notification, specialEmail: String, specialNumber: String): String = { - notification match { - case Email(email, _, _) if email == specialEmail => - "You got an email from special someone!" - case SMS(number, _) if number == specialNumber => - "You got an SMS from special someone!" - case other => - showNotification(other) // nic szczególnego, wywołaj domyślną metodę showNotification - } -} - -val SPECIAL_NUMBER = "55555" -val SPECIAL_EMAIL = "jane@mail.com" -val someSms = SMS("12345", "Are you there?") -val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123") -val specialEmail = Email("jane@mail.com", "Drinks tonight?", "I'm free after 5!") -val specialSms = SMS("55555", "I'm here! Where are you?") - -println(showNotificationSpecial(someSms, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an SMS from 12345! Message: Are you there?" -println(showNotificationSpecial(someVoiceRecording, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123" -println(showNotificationSpecial(specialEmail, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an email from special someone!" -println(showNotificationSpecial(specialSms, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an SMS from special someone!" +case class Message(sender: String, recipient: String, body: String) +val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg") +val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr") +message5.sender // travis@washington.us +message5.recipient // claire@bourgogne.fr +message5.body // "Me zo o komz gant ma amezeg" ``` -Programując w Scali zachęca się, abyś jak najszerzej używał klas przypadków do modelowania danych, jako że kod, który je wykorzystuje, jest bardziej ekspresywny i łatwiejszy do utrzymania: - -* Obiekty niemutowalne uwalniają cię od potrzeby śledzenia zmian stanu -* Porównanie przez wartość pozwala na porównywanie instancji tak, jakby były prymitywnymi wartościami -* Dopasowanie wzorca znacząco upraszcza logikę rozgałęzień, co prowadzi do mniejszej ilości błędów i czytelniejszego kodu - +Odbiorca wiadomości 4 `message4.recipient` jest użyty jako nadawca wiadomości 5 `message5.sender`, ciało wiadomości 5 zostało skopiowane bez zmian z wiadomości 4. diff --git a/_sips/sip-submission.md b/_sips/sip-submission.md index b40800b5d0..c30a4ae96c 100644 --- a/_sips/sip-submission.md +++ b/_sips/sip-submission.md @@ -190,8 +190,9 @@ Committee members should be either individuals responsible for a specific part of the Scala codebase, committers or contributors of the Scala compiler. Exceptionally, members may also be important representatives of the community with a high technical knowledge to understand the implications of every proposal -and participate into the discussions. The members are elected by the Process -Lead based on their expertise and implication in the community. +and participate into the discussions. New members are elected by existing +members of the SIP Committee, based on their expertise and involvement in the +community. The current committee members are: diff --git a/_tour/case-classes.md b/_tour/case-classes.md index 607e449d0e..ee02b7406d 100644 --- a/_tour/case-classes.md +++ b/_tour/case-classes.md @@ -37,7 +37,7 @@ You can't reassign `message1.sender` because it is a `val` (i.e. immutable). It ## Comparison Case classes are compared by structure and not by reference: -``` +```tut case class Message(sender: String, recipient: String, body: String) val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") @@ -48,7 +48,7 @@ Even though `message2` and `message3` refer to different objects, the value of e ## Copying You can create a (shallow) copy of an instance of a case class simply by using the `copy` method. You can optionally change the constructor arguments. -``` +```tut case class Message(sender: String, recipient: String, body: String) val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg") val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr")