Scala é uma linguagem de programação funcional que trata funções como valores de primeira classe e também possui métodos, com semelhanças e diferenças entre eles. Tanto funções quanto métodos são blocos de código reutilizáveis usados para centralizar lógicas repetidas e, assim, permitir chamadas que executam tarefas específicas. Eles também facilitam a depuração e a manutenção do código.
Porém, funções são objetos inicializados em variáveis, enquanto métodos começam com a palavra-chave 'def', seguida do nome do método, lista de parâmetros e corpo do método com o valor de retorno.
Declaração e definição de métodos
A sintaxe para declarar e definir métodos em Scala é a seguinte:
A chamada é feita passando os argumentos para 'method_name', que é o nome do método correspondente que você deseja executar.
Método com argumentos nomeados
Métodos com argumentos nomeados permitem associar explicitamente cada argumento ao parâmetro correspondente durante a chamada. Veja abaixo um exemplo de passagem de argumentos, com a declaração/definição da função e a chamada em ação:
object calculateResult {deffunSub(x:Int, y:Int): Int ={
var diff:Int =0
diff = x - y
//return value
return diff
}defmain(args: Array[String]){// Function call
println("Difference of the value is: "+ funSub(8,6));
println("Difference of the value is "+ funSub(y=6,x=8));}}Tecnologia
O programa acima gera a saída: Difference of the value is: 2 Difference of the value is: 2
No exemplo, temos o objeto 'calculateResult' e, dentro dele, o método 'funSub' com os parâmetros x e y, ambos do tipo 'Int'. O tipo de retorno do método também é 'Int'. Em seguida, há uma atribuição para o valor de retorno. As chaves indicam o início do corpo do método, onde a variável 'diff' é inicializada com 0. A chamada 'funSub(8,6)' feita em 'main' associa 8 a 'x' e 6 a 'y'; a subtração é realizada, o valor de 'diff' é retornado e impresso. Da mesma forma, 'funSub(x=8,y=6)' associa 8 a 'x' e 6 a 'y' via nomes (a ordem não importa); a operação é a mesma e o resultado é impresso.
Valores padrão de parâmetros
Você pode definir valores padrão para parâmetros de métodos, inicializando-os na assinatura. Assim, é possível omitir argumentos na chamada.
object calculateResult {deffunSub(x:Int=9, y:Int=6): Int ={
var diff:Int =0
diff = x - y
//return value
return diff
}defmain(args: Array[String]){// Function call
print("The final value is: "+ funSub());}}Tecnologia
O programa acima gera a saída: The final value is: 3
No código, o objeto 'calculateResult' contém o método 'funSub' com parâmetros x e y, ambos do tipo 'Int', e tipo de retorno 'Int'. A atribuição final indica o valor retornado. O corpo do método inicia com as chaves, e 'diff' é inicializada em 0. Em 'main', a chamada 'funSub()' usa os valores padrão x = 9 e y = 6; a operação é realizada, 'diff' é retornado e impresso.
Argumentos de comprimento variável
Argumentos de comprimento variável permitem passar uma quantidade qualquer de valores, conforme desejado pelo usuário/cliente. O último parâmetro do método é declarado usando '*' para indicar repetição.
object variableArgument {defmain(args: Array[String]){
printAll("Scala","is","great")}defprintAll(strings: String*){
var i : Int =0;for( value <- strings ){
println(value);
i = i +1;}}}Tecnologia
O programa acima gera a saída: Scala is great
Note que o objeto 'variableArgument' define o método 'printAll' com o argumento de comprimento variável 'String*'. Na chamada do método, é possível passar uma lista de strings. A lista recebida é percorrida e seus valores são impressos na função principal.
Função recursiva
Recursão é uma técnica comum em programação funcional: o problema é resolvido ao dividi-lo repetidamente em subproblemas menores, semelhantes ao original. Resolvem-se os menores e suas soluções são combinadas para chegar ao resultado final. Por isso, é conhecido como abordagem de dividir e conquistar (ou diminuir e conquistar), deixando o código mais limpo e elegante. Ao escrever uma função recursiva, dois pontos são essenciais:
Caso base: pode haver mais de um caso base; se não for bem definido, a recursão pode se tornar infinita. O caso base precisa ter uma solução direta, sem recursão.
Caso recursivo: onde as chamadas recursivas são feitas. O ponto-chave é que, a cada chamada, o problema diminui de tamanho, dividindo-se em subproblemas até chegar ao caso base. Ao final, as soluções são combinadas para resolver o problema principal (abordagem divide and conquer).
O fatorial de um número qualquer é n! e pode ser expresso assim:
n! = n.(n-1).(n-2)...3.2.1
Também podemos escrever (n-1).(n-2)...3.2.1 como (n-1)!. Logo, o fatorial de n é n.(n-1)!
Veja abaixo a solução recursiva do problema.
object factorialDemo {defmain(args: Array[String]){for(i <-1 to 5)
println("Factorial of "+ i +": = "+ factorial(i))}deffactorial(n: Int): Int ={if(n <=1)return1elsereturn n * factorial(n -1)}}Tecnologia
O programa acima gera a saída: Factorial of 1: = 1 Factorial of 2: = 2 Factorial of 3: = 6 Factorial of 4: = 24 Factorial of 5: = 120
Temos o objeto 'factorialDemo' com a função 'main' que executa um loop de 1 a 5 e chama 'factorial' a cada iteração. A função recursiva faz chamadas sucessivas até atingir o caso base (n menor ou igual a 1), quando então retorna o resultado, que é impresso.
Função anônima
Funções anônimas são definições leves de função sem nome, conhecidas em Scala como function literals.
Na primeira sintaxe, a expressão após "=>" é avaliada para um valor específico, enquanto a lista de variáveis antes de "=>" é usada para avaliar a expressão.
Na segunda, usamos placeholders: cada sublinhado aceita um valor como um curinga apenas uma vez, e então o operador é aplicado entre eles.
Veja um exemplo de função anônima:
object anonymousDemo
{defmain(args: Array[String]){
var function1 =(var1:Int, var2:Int)=> var1 + var2
var function2 =(_:Int)+(_:Int)// function call
println(function1(5,5))
println(function2(7,3))}}Tecnologia
Initializing Scala interpreter ...
Spark Web UI available at http://DESKTOP-03TH7J0:4040
SparkContext available as'sc'(version =2.4.3, master = local[*], app id = local-1566986265958)
SparkSession available as'spark'<console>:10: error: unbound placeholder parameter
var function2 ={_:Int}+{_:Int}^<console>:10: error: unbound placeholder parameter
var function2 ={_:Int}+{_:Int}^Tecnologia
O programa acima gera a saída: 10 10
No objeto 'anonymousDemo', a função 'main' define duas funções anônimas. Elas têm sintaxes diferentes, mas produzem o mesmo resultado. 'function1' usa parâmetros nomeados ao ser chamada (passamos 5 e 5), resultando em 10. 'function2' usa placeholders, recebe 7 e 3, aceita quaisquer inteiros válidos, soma e imprime o resultado.
Conclusão
Parabéns! Você concluiu a leitura deste tutorial.
Há muitos tópicos avançados em Scala, como higher-order functions, funções aninhadas, currying, entre outros.
Descubra como escrever funções em Python reutilizáveis e eficientes. Domine parâmetros, instruções de retorno e temas avançados como funções lambda. Organize melhor seu código com main() e outras boas práticas.
Aprenda sobre as funções lambda do Python, para que servem e quando usá-las. Inclui exemplos práticos e melhores práticas para uma implementação eficaz.
Quer se aprofundar em Scala? Faça o curso Introduction to Scala da DataCamp.
Scala é uma linguagem de programação funcional que trata funções como valores de primeira classe e também possui métodos, com semelhanças e diferenças entre eles. Tanto funções quanto métodos são blocos de código reutilizáveis usados para centralizar lógicas repetidas e, assim, permitir chamadas que executam tarefas específicas. Eles também facilitam a depuração e a manutenção do código.
Porém, funções são objetos inicializados em variáveis, enquanto métodos começam com a palavra-chave 'def', seguida do nome do método, lista de parâmetros e corpo do método com o valor de retorno.
Declaração e definição de métodos
A sintaxe para declarar e definir métodos em Scala é a seguinte:
Um método em Scala é composto pelas partes abaixo:
Chamada de método
A sintaxe para chamar um método em Scala é:
A chamada é feita passando os argumentos para 'method_name', que é o nome do método correspondente que você deseja executar.
Método com argumentos nomeados
Métodos com argumentos nomeados permitem associar explicitamente cada argumento ao parâmetro correspondente durante a chamada. Veja abaixo um exemplo de passagem de argumentos, com a declaração/definição da função e a chamada em ação:
O programa acima gera a saída:
Difference of the value is: 2
Difference of the value is: 2
No exemplo, temos o objeto 'calculateResult' e, dentro dele, o método 'funSub' com os parâmetros x e y, ambos do tipo 'Int'. O tipo de retorno do método também é 'Int'. Em seguida, há uma atribuição para o valor de retorno. As chaves indicam o início do corpo do método, onde a variável 'diff' é inicializada com 0. A chamada 'funSub(8,6)' feita em 'main' associa 8 a 'x' e 6 a 'y'; a subtração é realizada, o valor de 'diff' é retornado e impresso. Da mesma forma, 'funSub(x=8,y=6)' associa 8 a 'x' e 6 a 'y' via nomes (a ordem não importa); a operação é a mesma e o resultado é impresso.
Valores padrão de parâmetros
Você pode definir valores padrão para parâmetros de métodos, inicializando-os na assinatura. Assim, é possível omitir argumentos na chamada.
O programa acima gera a saída:
The final value is: 3
No código, o objeto 'calculateResult' contém o método 'funSub' com parâmetros x e y, ambos do tipo 'Int', e tipo de retorno 'Int'. A atribuição final indica o valor retornado. O corpo do método inicia com as chaves, e 'diff' é inicializada em 0. Em 'main', a chamada 'funSub()' usa os valores padrão x = 9 e y = 6; a operação é realizada, 'diff' é retornado e impresso.
Argumentos de comprimento variável
Argumentos de comprimento variável permitem passar uma quantidade qualquer de valores, conforme desejado pelo usuário/cliente. O último parâmetro do método é declarado usando '*' para indicar repetição.
O programa acima gera a saída:
Scala
is
great
Note que o objeto 'variableArgument' define o método 'printAll' com o argumento de comprimento variável 'String*'. Na chamada do método, é possível passar uma lista de strings. A lista recebida é percorrida e seus valores são impressos na função principal.
Função recursiva
Recursão é uma técnica comum em programação funcional: o problema é resolvido ao dividi-lo repetidamente em subproblemas menores, semelhantes ao original. Resolvem-se os menores e suas soluções são combinadas para chegar ao resultado final. Por isso, é conhecido como abordagem de dividir e conquistar (ou diminuir e conquistar), deixando o código mais limpo e elegante. Ao escrever uma função recursiva, dois pontos são essenciais:
O fatorial de um número qualquer é n! e pode ser expresso assim:
Também podemos escrever (n-1).(n-2)...3.2.1 como (n-1)!. Logo, o fatorial de n é n.(n-1)!
Veja abaixo a solução recursiva do problema.
O programa acima gera a saída:
Factorial of 1: = 1
Factorial of 2: = 2
Factorial of 3: = 6
Factorial of 4: = 24
Factorial of 5: = 120
Temos o objeto 'factorialDemo' com a função 'main' que executa um loop de 1 a 5 e chama 'factorial' a cada iteração. A função recursiva faz chamadas sucessivas até atingir o caso base (n menor ou igual a 1), quando então retorna o resultado, que é impresso.
Função anônima
Funções anônimas são definições leves de função sem nome, conhecidas em Scala como function literals.
Sintaxe com exemplos de função anônima:
Sintaxe:
Exemplo:
OU
Sintaxe:
Exemplo:
Na primeira sintaxe, a expressão após "=>" é avaliada para um valor específico, enquanto a lista de variáveis antes de "=>" é usada para avaliar a expressão.
Na segunda, usamos placeholders: cada sublinhado aceita um valor como um curinga apenas uma vez, e então o operador é aplicado entre eles.
Veja um exemplo de função anônima:
O programa acima gera a saída:
10
10
No objeto 'anonymousDemo', a função 'main' define duas funções anônimas. Elas têm sintaxes diferentes, mas produzem o mesmo resultado. 'function1' usa parâmetros nomeados ao ser chamada (passamos 5 e 5), resultando em 10. 'function2' usa placeholders, recebe 7 e 3, aceita quaisquer inteiros válidos, soma e imprime o resultado.
Conclusão
Parabéns! Você concluiu a leitura deste tutorial.
Há muitos tópicos avançados em Scala, como higher-order functions, funções aninhadas, currying, entre outros.
Referências:
TOUR OF SCALA BASICS
Scala | Functions – Basics
Scala - Functions
Anonymous Functions in Scala
Confira o curso Introduction to Scala da DataCamp.