Skip to content

Commit

Permalink
feat(lambda): 🎸 lambda expression, translated
Browse files Browse the repository at this point in the history
Refers: #6
  • Loading branch information
rcmoutinho committed Sep 11, 2019
1 parent e8ced1d commit 322d571
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 117 deletions.
94 changes: 46 additions & 48 deletions book/04-lambda/sections/02-lambda-expression.asc
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,78 @@
:section-java-package: ../../../{java-package}

[[lambda-expression]]
=== Expressões Lambda (Lambda Expression)
=== Lambda Expression

.Objetivo
.Objective
--------------------------------------------------
Describe a lambda expression; refactor the code that uses an anonymous inner class to use a lambda expression; describe type inference and target typing.
-
Descrever uma expressão lambda; refatorar código que usa classes anônimas internas para usar expressões lambda; descrever a inferência de tipos e tipos esperados.
--------------------------------------------------

Expressões Lambda são parecidas com classes anônimas, porém só possuem a implementação dos métodos. Por isso, são como "métodos anônimos", que podem ser passados via variáveis.
Lambda expressions are similar to anonymous classes, but only have the implementation of the methods. Therefore, they are like "anonymous methods" that can be passed via variables.

É essencial o entendimento de funções lambda, e das variações em sua sintaxe, para compreender as próximas seções de Interfaces Funcionais Pré-Construídas e de Referências a métodos.
Understanding lambda functions, and variations in their syntax, is essential to understanding the next sections of Built-in Interfaces and Method References.

A expressão lambda possui 3 partes:
The lambda expression has 3 parts:

. Uma lista de parâmetros, separados por vírgula
* Algumas vezes possui parênteses
* Algumas vezes possui o tipo das variáveis
. O "arrow token", que sempre é escrito como `\->`
. Um corpo, que pode ou não estar entre chaves
* Pode possuir mais de uma linha
* Algumas vezes possui um `return`
* Algumas vezes possui ponto e vírgula
. A comma-separated list of parameters
* Sometimes has parentheses
* Sometimes has variable type
. The "arrow token", which is always written as `\->`
. A body, which may or may not be enclosed in braces
* Can have more than one line
* Sometimes has a `return`
* Sometimes has semicolon

Exemplos de expressões lambda:
Examples of lambda expressions:

* `i -> System.out.println(i)`
* `(Integer i) -> System.out.println(i)`
* `(Integer i) -> { System.out.println(i); }`
* `(Integer i) -> { return i + 1; }`
* `(i, j, k) -> { return i + j + k; }`
* `(i, j, k) -> System.out.println(i + j + k)`
* `() -> System.out.println("nada")`
* `() -> System.out.println("nothing")`

//-

. Expressões lambda podem ser entendidas como uma forma diferente de declarar classes anônimas.
. Lambda expressions can be understood as a different way of declaring anonymous classes.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_AnonymousClass.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_AnonymousClass.java[tag=code]
----
+
Veja que no exemplo acima é instanciada uma `Thread` com uma instância anônima de `Runnable`. Na segunda parte, é feito a mesma coisa de forma muito mais simples utilizando uma expressão lambda.
Note that in the example above a `Thread` is instantiated with an anonymous instance of `Runnable`. In the second part, the same thing is done much simpler using a lambda expression.

. Expressões lambda são sempre utilizadas para criar instâncias de interfaces funcionais, ou seja, interfaces que possuem apenas um único método abstrato.
. Lambda expressions are always used to create instances of functional interfaces, i.e., interfaces that have only a single abstract method.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_FunctionalInterface.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_FunctionalInterface.java[tag=code]
----
+
.Saída no console
.console output
[source,console]
----
executei com classe anônima
executei com expressão lambda
performed with anonymous class
performed with lambda expression
----
+
Veja que no exemplo acima o mesmo método `executeEApresenteMensagem` é invocado duas vezes. Na primeira vez é passada uma nova classe anônima. Na segunda vez é passado uma expressão lambda.
Note that in the example above the same `executeAndPresentMessage` method is invoked twice. The first time a new anonymous class is passed. The second time a lambda expression is passed.
+
Veja também que seria impossível criar uma expressão lambda caso a interface não fosse funcional, ou seja, tivesse mais de um método abstrato. O compilador não saberia identificar que o método `execute`, da interface `Executavel`, está sendo implementado dentro da expressão lambda.
Also see that it would be impossible to create a lambda expression if the interface was not functional, i.e., it had more than one abstract method. The compiler would not be able to identify that the `execute` method of the` Executable` interface is being implemented within the lambda expression.

. Existem muitos métodos já disponíveis no Java 8 que se beneficiam da sintaxe de expressões lambda, como o `forEach` de listas.
. There are many methods already available in Java 8 that benefit from lambda expression syntax, such as `forEach` lists.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_ForEach.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_ForEach.java[tag=code]
----
+
.Saída no console
.console output
[source,console]
----
1
Expand All @@ -85,93 +83,93 @@ include::{section-java-package}/lambdaexpression/LambdaExpression_ForEach.java[t
5
----
+
Veja que o novo método `forEach` executa a expressão lambda passada como parâmetro para cada item da lista, imprimindo todos no console. A expressão lambda recebe como parâmetro um número, que é o número da lista.
Note that the new `forEach` method executes the lambda expression passed as a parameter to each list item, printing them all to the console. The lambda expression takes as a parameter a number, which is the list number.
+
Neste caso, a interface funcional que está sendo implementada pela expressão lambda é chamada `Consumer`. Ela será explicada em detalhes em uma seção posterior, juntamente com outras interfaces funcionais padrões do Java 8. Nesta seção é importante apenas entender o que são as expressões lambda e como é sua sintaxe.
In this case, the functional interface being implemented by the lambda expression is called `Consumer`. It will be explained in detail in a later section, along with other standard Java 8 functional interfaces. In this section, it is essential to understand what lambda expressions are and what their syntax is like.

. Declarações de expressões lambda podem ser completas ou simplificadas.
. Declarations of lambda expressions can be complete or simplified.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_SimpleComplete.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_SimpleComplete.java[tag=code]
----
+
As duas funções lambda acima são idênticas, porém uma é mais explícita do que a outra.
The two lambda functions above are identical, but one is more explicit than the other.

. Os parênteses só podem ser omitidos caso não haja a declaração do *tipo*, e haja apenas *um único* argumento.
. Expressões lambda que NÃO possuem argumentos também precisam dos parênteses.
. Parentheses can only be omitted if there is no *type* declaration, and there is only *a single* argument.
. Lambda expressions that do NOT have arguments also need parentheses.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_Parenthesis.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_Parenthesis.java[tag=code]
----

. É obrigatória a utilização de chaves, ponto e vírgula e `return` (caso a função retorne algum valor) em expressões lambda com mais de uma linha.
. The use of curly brackets, semicolons and `return` (if the function returns any value) is required in lambda expressions with more than one line.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_Block.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_Block.java[tag=code]
----

. Ao tornar explícito o tipo de um dos argumentos, é obrigatório informar de todos.
. When making the type of one of the arguments explicit, it is mandatory to inform all of them.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_VarType.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_VarType.java[tag=code]
----

. Não é permitido declarar variáveis com o mesmo nome dentro da expressão lambda.
. It is not allowed to declare variables with the same name within the lambda expression.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_Shadowing.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_Shadowing.java[tag=code]
----

. É permitido acessar variáveis externas dentro da expressão lambda, mas somente variáveis finais ou variáveis que não são alteradas.
. It is allowed to access external variables within the lambda expression, but only final variables or variables that do not change.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_AccessExternalVar.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_AccessExternalVar.java[tag=code]
----
+
Perceba que o compilador identifica que a variável `x3` é alterada no final do método, e por isso, não permite que ela seja utilizada na expressão lambda.
Note that the compiler identifies that the `x3` variable is changed at the end of the method, and therefore does not allow it to be used in the lambda expression.

. Em situações de ambiguidade, o compilador tenta descobrir o tipo da expressão lambda utilizando o contexto.
. In ambiguous situations, the compiler tries to find out the type of lambda expression using the context.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_TypeInference.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_TypeInference.java[tag=code]
----
+
No exemplo anterior, apenas o método `run` da interface funcional `Application` retorna uma `String`, enquanto o método `execute` da interface funcional `Executavel` não retorna nada (`void`). Isso é diferença suficiente para o compilador saber qual método chamar cada vez que `rode` é invocado.
+
Na primeira chamada ao método `rode`, como a expressão lambda passada retorna uma `String`, o compilador entende que essa expressão lambda é uma implementação da interface `Application`, pois o método `run` também retorna uma `String`.
In the previous example, only the `run` method of the `Application` functional interface returns a `String`, while the `execute` method of the `Executable` functional interface returns nothing (`void`). This is enough difference for the compiler to know which method to call each time `doThis` is invoked.
+
Na segunda chamada ao método `rode`, como a expressão lambda não retorna nada (apenas imprime a `String` `"executando"`), o compilador entende que essa expressão lambda é uma implementação da interface `Executavel`, pois o método `execute` também não retorna nada.
On the first call to the `doThis` method, since the passed lambda expression returns a `String`, the compiler understands that this lambda expression is an implementation of the `Application` interface, as the `run` method also returns a `String`.
+
On the second call to the `doThis` method, since the lambda expression returns nothing (just prints the `String` `"executing"`), the compiler understands that this lambda expression is an implementation of the `Executable` interface, because the `execute` also returns nothing.

. Se não for possível descobrir o tipo da expressão lambda, ocorre erro de compilação.
. If the type of the lambda expression cannot be found, a compilation error occurs.
+
[source,java,indent=0]
.{java-package}/lambdaexpression/LambdaExpression_Ambiguity.java
----
include::{section-java-package}/lambdaexpression/LambdaExpression_Ambiguity.java[tag=code]
----
+
No exemplo anterior, como as duas interfaces funcionais possuem métodos com retorno `void`, o compilador não sabe qual das duas está sendo instanciada na expressão lambda, e ocorre erro de compilação. A expressão lambda, nesse exemplo, poderia ser tanto do tipo `Piloto` quanto `Corredor`, e não há como o compilador descobrir qual o desenvolvedor de fato quis utilizar.
In the previous example, because both functional interfaces have a `void` method, the compiler does not know which one is being instantiated in the lambda expression, and a compilation error occurs. The lambda expression in this example could be either `Pilot` or `Runner`, and there is no way for the compiler to find out which developer actually wanted to use it.

.Referências
.References
****
* Implementing Functional Interfaces with Lambdas
+
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 55). Wiley. Edição do Kindle.
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 55). Wiley. Kindle Edition.
* Using Variables in Lambdas
+
Expand All @@ -181,4 +179,4 @@ Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8
* https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Lambda Expressions.] The Java™ Tutorials.
****
****
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ public static void main(String[] args) {
Double x2 = 2.0;
Double x3 = 2.0;

// COMPILA - variável externa 'x1' é final e pode ser utilizada na expressão lambda
UnaryOperator<Double> elevarAoX1 = (Double y) -> Math.pow(y, x1);
// COMPILES - external variable 'x1' is final and can be used in lambda expression
UnaryOperator<Double> raiseToX1 = (Double y) -> Math.pow(y, x1);

// COMPILA - variável externa 'x2' não é final, mas nunca é alterada, então pode ser utilizada dentro da expressão lambda
UnaryOperator<Double> elevarAoX2 = (Double y) -> Math.pow(y, x2);
// COMPILES - external variable 'x2' is not final, but never changed, so it can be used inside the lambda expression
UnaryOperator<Double> raiseToX2 = (Double y) -> Math.pow(y, x2);

// NÃO COMPILA - variável externa 'x3' é alterada dentro desse método, então não pode ser utilizada dentro da expressão lambda
UnaryOperator<Double> elevarAoX3 = (Double y) -> Math.pow(y, x3);
// NOT COMPILING - external variable 'x3' is changed within this method, so it cannot be used within the lambda expression
UnaryOperator<Double> raiseToX3 = (Double y) -> Math.pow(y, x3);

x3 = 3.0; // alteração da variável x3 não permite que ela seja utilizada em expressões lambda
x3 = 3.0; // changing variable 'x3' does not allow it to be used in lambda expressions
}
// end::code[]
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ public class LambdaExpression_Ambiguity {

// tag::code[]
@FunctionalInterface
interface Corredor {
void corra();
interface Runner {
void run();
}

@FunctionalInterface
interface Piloto {
void corra();
interface Pilot {
void run();
}

static class Executor {
void execute(Corredor corredor) {
corredor.corra();
void execute(Runner runner) {
runner.run();
}

String execute(Piloto piloto) {
piloto.corra();
return "correndo";
String execute(Pilot pilot) {
pilot.run();
return "running";
}
}

public static void main(String[] args) {
Executor executor = new Executor();
// NÃO COMPILA - não é possível determinar o tipo da expressão lambda abaixo
// NOT COMPILING - cannot determine type of lambda expression below
executor.execute(() -> System.out.println("execute"));
}
// end::code[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ public class LambdaExpression_AnonymousClass {

public static void main(String[] args) {
// tag::code[]
// com classe anônima
// with anonymous class
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Executando.");
System.out.println("Executing.");
}
}).run();

// com expressão lambda
new Thread(() -> System.out.println("Executando.")).run();
// with lambda expression
new Thread(() -> System.out.println("Executing.")).run();
// end::code[]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ public class LambdaExpression_Block {

public static void main(String[] args) {
// tag::code[]
UnaryOperator<Double> elevarAoQuadrado = (Double x) -> {
UnaryOperator<Double> square = (Double x) -> {
double pow = Math.pow(x, 2);
return pow;
};

Consumer<Double> imprime = (Double x) -> {
Consumer<Double> print = (Double x) -> {
double pow = Math.pow(x, 2);
System.out.println(pow);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ public class LambdaExpression_ForEach {

public static void main(String[] args) {
// tag::code[]
List<Integer> lista = Arrays.asList(1, 2, 3, 4, 5);
lista.forEach((numero) -> { System.out.println(numero); });
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.forEach((number) -> { System.out.println(number); });
// end::code[]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ public class LambdaExpression_FunctionalInterface {

// tag::code[]
@FunctionalInterface
interface Executavel { // interface funcional
String execute(); // método funcional
interface Executable { // functional interface
String execute(); // functional method
}

private static void executeEApresenteMensagem(Executavel executavel) {
String mensagem = executavel.execute();
System.out.println(mensagem);
private static void executeAndPresentMessage(Executable executable) {
String message = executable.execute();
System.out.println(message);
}

public static void main(String[] args) {

// com classe anônima
executeEApresenteMensagem(new Executavel() {
// with anonymous class
executeAndPresentMessage(new Executable() {
@Override
public String execute() {
return "executei com classe anônima";
return "performed with anonymous class";
}
});

// com expressão lambda
executeEApresenteMensagem(() -> { return "executei com expressão lambda"; });
// with lambda expression
executeAndPresentMessage(() -> { return "performed with lambda expression"; });
}
// end::code[]
}
Loading

0 comments on commit 322d571

Please sign in to comment.