Buscar

Linguagem de Programação Scala e coleções paralelas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 116 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 116 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 116 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

AUTARQUIA EDUCACIONAL DO VALE DO SÃO FRANCISCO – AEVSF
FACULDADE DE CIÊNCIAS APLICADAS E SOCIAIS DE PETROLINA – FACAPE
ADRIEL SIQUEIRA BENTO
ESTUDO E AVALIAÇÃO DA LINGUAGEM DE PROGRAMAÇÃO SCALA E SEU
USO NA PROGRAMAÇÃO PARALELA
PETROLINA – PE
2016 
2
ADRIEL SIQUEIRA BENTO
ESTUDO E AVALIAÇÃO DA LINGUAGEM DE PROGRAMAÇÃO SCALA E SEU NA
PROGRAMAÇÃO PARALELA
Trabalho obrigatório de conclusão de curso
para obtenção de grau de bacharel em Ciência
da Computação apresentado a Faculdade de
Ciências Aplicadas e Sociais de Petrolina.
Orientador: Prof. Me. Jocélio de Oliveira
Dantas Passos.
PETROLINA – PE
2016 
3
ADRIEL SIQUEIRA BENTO
ESTUDO E AVALIAÇÃO DA LINGUAGEM DE PROGRAMAÇÃO SCALA E SEU
NA PROGRAMAÇÃO PARALELA
Trabalho obrigatório de conclusão de curso
para obtenção de grau de bacharel em Ciência
da Computação apresentado a Faculdade de
Ciências Aplicadas e Sociais de Petrolina.
Orientador: Prof. Me. Jocélio de Oliveira
Dantas Passos.
Aprovada em: ___/___/______.
 
 
BANCA EXAMINADORA
________________________________________
Prof. Me. Jocélio de Oliveira Dantas Passos. (Orientador)
Faculdade de Ciências Aplicadas e Sociais de Petrolina.
_________________________________________
Prof. Me. Carlos Alberto Teixeira Batista
Faculdade de Ciências Aplicadas e Sociais de Petrolina.
_________________________________________
Prof. Esp. Thomas de Almeida Rabelo
Faculdade de Ciências Aplicadas e Sociais de Petrolina.
4
“O Temor do Senhor é o princípio do
conhecimento, mas os loucos desprezam a
sabedoria e a instrução.” – Provérbios 1:7
“Porque o Senhor dá a sabedoria, da Sua boca
vem o conhecimento e o entendimento.” –
Provérbios 2:6
5
AGRADECIMENTOS
Primeiro ao nosso Amoroso e Fiel Pai, que é Deus Eterno e Todo Poderoso, O
Criador e Arquiteto de tudo que existe e é bom. Por ter estado ao meu lado me protegendo de
vários males durante todo o curso de graduação. A Jesus Cristo, o Seu Filho e meu Salvador,
pelo Seu exemplo que me ensina e motiva a não esquecer dos outros enquanto se corre atrás
de objetivos próprios, e ao Senhor Deus Espirito Santo, que me consolou e animou nos
momentos difíceis durante toda minha vida. Minha principal e primeira fonte de sabedoria, de
conhecimento, e dos bons resultados.
Agradeço a minha Mãe Selma Bento, por seu amor terno, por suas cobranças que
me despertavam e me faziam ser mais atento. Pela prontidão em me apoiar com o que fosse
necessário tanto em conselhos como em material. Também ao meu Pai Hermes Siqueira
Cavalcante, pelo ombro amigo e preocupado que sempre me ofereceu mesmo em meio a
muito trabalho. Suas orações de Pai moviam o braço do Bom Deus em minha guia e ajuda.
Seu apoio financeiro sempre que precisei também me ajudou
Também e em especial a minha namorada Aísla Gomes Guimarães por ter estado
sempre ao meu lado a me apoiar de verdade, por muitas vezes ter se prontificado e ter
oferecido mais ajuda do que eu poderia aceitar, por ter sempre orado por mim. Seu apoio me
foi e sempre será de inestimável valor.
Agradeço muito pela paciência e acompanhamento do Prof. Me. Jocélio Dantas
Passos, pois não só no lado acadêmico mas também com suas orientações e exemplo me
ensinou a ser mais equilibrado nas várias obrigações que um Homem leva em suas costas.
Também agradeço ao meu amigo Eduardo Fernandes por sua amizade verdadeira
em frequente ajuda, seus incentivos sinceros em minha vida estudantil e de trabalho. Obrigado
a todos os meus amigos e professores pelos anos juntos, incentivo e companhia especial de
cada um de vocês.
6
RESUMO
Muito já se falara sobre o paradigma de programação funcional e suas vantagens e
desvantagens em relação ao paradigma orientado a objeto, porém a complexidade do
paradigma funcional, e grandes diferenças em relação ao paradigma orientado a objeto, foram
um entrave a sua popularidade no mercado do desenvolvimento de software. Em 2001 Martin
Odersky, co-criador do Generic java, e um dos implementadores da JVM (Máquina Virtual
Java) liderou a criação da linguagem de programação Scala, que veio a ganhar mais fama a
partir de sua versão 2.0 lançada em 2003. A linguagem Scala traz o sonho do paradigma
funcional para mais perto do mercado de desenvolvimento de software, pois ao passo que se
utiliza do paradigma funcional possibilita a integração com o paradigma orientado a objeto,
com o qual também trabalha. Juntando ambos os paradigmas sem desqualificar os
desenvolvedores acostumados com o desenvolvimento orientado a objeto ou funcional. O
presente trabalho avalia a linguagem Scala e seus principais recursos. Ao fim, ver-se-á que
Scala pode ser usada tanto na programação funcional quanto orientada a objeto.
Palavras-chave: linguagem Scala, funcional, orientado a objeto, JVM.
7
ABSTRACT
Much has been spoken about the functional programming paradigm and its advantages and
disadvantages compared to object-oriented paradigm, but the complexity of the functional
paradigm, and large differences from the object-oriented paradigm, were an obstacle to its
popularity in the market development software. In 2001 Martin Odersky, co-creator of
Generic java, and one of the implementers of the JVM (Java Virtual Machine) led the creation
of the Scala programming language, which later gained more fame from its 2.0 version
launched in 2003. The Scala brings the dream of the functional paradigm closer to the
software development market because while using the functional paradigm enables
integration with object-oriented paradigm, with which also works. Joining both paradigms
without disqualifying the developers used to develop object-oriented or functional. This study
evaluates the Scala language and its key features. In the end, it will be seen that Scala could
be used either in functional programming and object-oriented.
Key words: Scala language, functional, object-oriented, JVM.
8
LISTA DE FIGURAS
Figura 1 – Processo de compilação...........................................................................................26
Figura 2 – Processo de interpretação........................................................................................27
Figura 3 – Importação com Scala.............................................................................................30
Figura 4 – Interpretador REPL..................................................................................................37
Figura 5 – Erro de interpretação...............................................................................................37
Figura 6 – Inferência do “;”......................................................................................................37
Figura 7 – Expressões simples..................................................................................................39
Figura 8 – Values criados pelo REPL........................................................................................39
Figura 9 – Validação de values..................................................................................................40
Figura 10 – Valores imutáveis...................................................................................................41
Figura 11 – Validação call-by-value..........................................................................................42
Figura 12 – Validação call-by-name.........................................................................................43
Figura 13 – Exemplo If-else em Scala......................................................................................44
Figura 14 – Recursividade comum...........................................................................................45Figura 15 – Recursão de cauda.................................................................................................46
Figura 16 – Função anônima.....................................................................................................50
Figura 17 – Uso de somaInts, somaCubos e somaFatoriais......................................................51
Figura 18 – Pilha genérica........................................................................................................57
Figura 19 – Aplicação de simPrefixo........................................................................................58
Figura 20 – Traits implementadas.............................................................................................63
Figura 21 – Combinando abstrações.........................................................................................64
Figura 22 – Coleções: mutáveis e imutáveis.............................................................................66
Figura 23 – Operações simples.................................................................................................67
Figura 24 – Testando conjuntos (sets).......................................................................................69
Figura 25 – Testando mapas (maps)..........................................................................................71
Figura 26 – Iteração com coleções............................................................................................73
Figura 27 – Implementando geradores e filtros........................................................................75
Figura 28 – Primeira sintaxe do for...........................................................................................76
Figura 29 – Segunda sintaxe do for...........................................................................................77
Figura 30 – Seleções de campo e método.................................................................................79
Figura 31 – Flexibilidade entre coleções..................................................................................86
Figura 32 – Definições e tipos de dados...................................................................................87
Figura 33 – Combinando coleções............................................................................................92
Figura 34 – Flexibilidade da inferência....................................................................................94
Figura 35 – Inferência em tipos genéricos................................................................................95
Figura 36 – Mapeamento em paralelo.....................................................................................102
Figura 37 – Filtrando em paralelo...........................................................................................103
Figura 38 – Instanciando ParArray.........................................................................................105
Figura 39 – Exemplo de ParVector.........................................................................................106
Figura 40 – Implementando ParHashMap..............................................................................107
Figura 41 – Implementado ParHashSet..................................................................................108
9
LISTA DE QUADROS
Quadro 1 – Incrementação em C...............................................................................................18
Quadro 2 – Exemplos para o operador '+'.................................................................................19
Quadro 3 – Tipo numérico fazendo papel booleano.................................................................20
Quadro 4 – Tipo booleano.........................................................................................................20
Quadro 5 – Facilidade de escrita...............................................................................................22
Quadro 6 – Definições em Scala...............................................................................................40
Quadro 7 – Chamada de argumentos call-by-value..................................................................42
Quadro 8 – Função loop............................................................................................................43
Quadro 9 – Chamada de argumentos call-by-name..................................................................44
Quadro 10 – Validação da fatoração.........................................................................................45
Quadro 11 – Validação com recursão de cauda.........................................................................46
Quadro 12 – Funções comuns...................................................................................................48
Quadro 13 – Funções de ordem superior..................................................................................48
Quadro 14 – Função anônima mais enxuta...............................................................................50
Quadro 15 – Função currying...................................................................................................51
Quadro 16 – Sintaxe especial para currying.............................................................................52
Quadro 17 – Casamento de padrões..........................................................................................53
Quadro 18 – Casamento de padrões e classes case...................................................................55
Quadro 19 – Tipo genérico........................................................................................................56
Quadro 20 – Método genérico..................................................................................................57
Quadro 21 – Função divMod....................................................................................................59
Quadro 22 – Biblioteca Scala: Tuple2......................................................................................60
Quadro 23 – Instâncias de Tuple2.............................................................................................60
Quadro 24 – Acesso a tuplas.....................................................................................................61
Quadro 25 – Tuplas e casamento de padrões............................................................................61
Quadro 26 – Trait parcialmente implementada.........................................................................62
Quadro 27 – Operação com coleções........................................................................................65
Quadro 28 – Implementação de listas.......................................................................................68
Quadro 29 – Elementos fundamentais......................................................................................69
Quadro 30 – Formato expressões for.........................................................................................74
Quadro 31 – Implementando geradores....................................................................................75
Quadro 32 – Sintaxe com elemento incomum..........................................................................77
Quadro 33 – Keywords do Scala...............................................................................................79
Quadro 34 – Implementações de for.........................................................................................80
Quadro 35 – Implementações de currying................................................................................80
Quadro 36 – Conceitos simples................................................................................................81
Quadro 37 – Acoplamento ortogonal de conceitos...................................................................82Quadro 38 – Estrutura do if em Scala.......................................................................................83
Quadro 39 – Estrutura do if em Java.........................................................................................83
Quadro 40 – Estrutura do match Scala......................................................................................83
Quadro 41 – Estrutura do switch Java.......................................................................................84
Quadro 42 – Outra estrutura match Scala.................................................................................84
Quadro 43 – Estrutura do case em Haskell...............................................................................84
Quadro 44 – Classes como tipo de dado...................................................................................87
Quadro 45 – Keywords comuns Java e Scala............................................................................88
Quadro 46 – Keywords comuns Python e Scala........................................................................88
Quadro 47 – Comparação de sintaxe Java e Scala....................................................................89
10
Quadro 48 – Expressividade com padrões de correspondência................................................92
Quadro 49 – Lançamento de exceção.......................................................................................96
Quadro 50 – Try-catch-finally em Java.....................................................................................96
Quadro 51 – Try-catch-finally em Scala...................................................................................97
Quadro 52 – Exemplo de mnemônico com Scala.....................................................................98
Quadro 53 – Mapeando uma lista...........................................................................................101
Quadro 54 – Mapeando uma lista em paralelo.......................................................................101
Quadro 55 – Importação e instanciação de coleção paralela..................................................103
Quadro 56 – Conversão de sequencial para paralelismo........................................................104
11
LISTA DE TABELAS
Tabela 1 – Operadores aritméticos............................................................................................31
Tabela 2 – Operadores relacionais............................................................................................31
Tabela 3 – Operadores lógicos..................................................................................................32
Tabela 4 – Operadores bit a bit.................................................................................................32
Tabela 5 – Operadores de atribuição.........................................................................................33
Tabela 6 – Precedência de operadores......................................................................................35
Tabela 7 – Operações básicas....................................................................................................67
Tabela 8 – Coleções sequenciais e paralelas...........................................................................109
12
LISTA DE ABREVIATURAS E SIGLAS
VB – Visual Basic
JVM – Java Virtual Machine
CMD – Command Prompt
REPL – Read-eval-print-loop Interpreter
API – Application Programming Interface
SIP – Scala Improvement Process
JIT – Just-in-time Compiler
13
SUMÁRIO
1 INTRODUÇÃO.....................................................................................................................15
 1.1 Justificativa......................................................................................................................16
 1.2 Objetivo geral...................................................................................................................16
 1.3 Objetivos específicos.......................................................................................................16
 1.4 Metodologia.....................................................................................................................16
2 CRITÉRIOS DE AVALIAÇÃO.............................................................................................17
 2.1 Legibilidade.....................................................................................................................18
 2.1.1 Simplicidade Global................................................................................................18
 2.1.2 Ortogonalidade........................................................................................................19
 2.1.3 Estruturas de Controle.............................................................................................20
 2.1.4 Tipos de Estruturas de Dados..................................................................................20
 2.1.5 Projeto de Sintaxe...................................................................................................20
 2.2 Facilidade de Escrita........................................................................................................21
 2.2.1 Simplicidade e Ortogonalidade...............................................................................21
 2.2.3 Expressividade........................................................................................................22
 2.3 Confiabilidade..................................................................................................................22
 2.3.1 Tipagem da Linguagem...........................................................................................23
 2.3.2 Manipulação de Exceções.......................................................................................23
 2.3.3 Apelidos (Aliases)...................................................................................................23
 2.4 Portabilidade....................................................................................................................24
 2.5 Generalidade....................................................................................................................24
 2.6 Compilação......................................................................................................................25
 2.7 Interpretação Pura............................................................................................................27
3 LINGUAGEM SCALA.........................................................................................................28
 3.1 Histórico...........................................................................................................................28
 3.2 Características técnicas....................................................................................................29
 3.3 Operadores.......................................................................................................................30
 3.3.1 Operadores Aritméticos...........................................................................................31
 3.3.2 Operadores Relacionais...........................................................................................31
 3.3.3 Operadores Lógicos................................................................................................32
 3.3.4 Operadores Bit a Bit................................................................................................32
 3.3.5 Operadores de Atribuição........................................................................................33
 3.3.6 Precedência de Operadores.....................................................................................353.4 Ambiente de Testes..........................................................................................................36
 3.5 Expressões e Funções Simples.........................................................................................38
 3.6 Valores Imutáveis.............................................................................................................40
 3.7 Parâmetros........................................................................................................................41
 3.8 Expressão Condicional If-else..........................................................................................44
 3.9 Recursão de Cauda (Tail Recursion)................................................................................45
 3.10 Funções de Ordem Superior (High-Order Functions)...................................................47
 3.11 Funções Anônimas.........................................................................................................49
 3.12 Currying.........................................................................................................................50
 3.13 Casamento de Padrões (Pattern Matching)...................................................................52
 3.14 Classes e objetos case (Case Classes and Case Objects)..............................................54
 3.15 Tipos Genéricos e Métodos (Generic Types and Methods)...........................................56
 3.16 Tuplas (Tuples)...............................................................................................................59
 3.17 Traços (Traits)................................................................................................................61
14
 3.18 Coleções (Collections)...................................................................................................65
 3.18.1 Listas (Lists)..........................................................................................................67
 3.18.2 Conjuntos (Sets)....................................................................................................69
 3.18.3 Mapa (Map)...........................................................................................................70
 3.19 Iteradores (Iterators)......................................................................................................71
 3.20 Estruturas de controle for e suas expressões..................................................................73
4 AVALIAÇÃO DA LINGUAGEM.........................................................................................78
 4.1 Legibilidade.....................................................................................................................78
 4.1.1 Simplicidade Global................................................................................................78
 4.1.2 Ortogonalidade........................................................................................................81
 4.1.3 Estruturas de Controle.............................................................................................82
 4.1.4 Tipos e estruturas de dados.....................................................................................85
 4.1.5 Projeto de Sintaxe...................................................................................................88
 4.2 Facilidade de Escrita........................................................................................................90
 4.2.1 Simplicidade e Ortogonalidade...............................................................................90
 4.2.2 Suporte a abstração.................................................................................................91
 4.2.3 Expressividade........................................................................................................91
 4.3 Confiabilidade..................................................................................................................93
 4.3.1 Tipagem da linguagem............................................................................................93
 4.3.2 Manipulação de Exceções.......................................................................................95
 4.3.3 Apelidos (Aliases)...................................................................................................97
 4.4 Portabilidade e Generalidade...........................................................................................98
 4.5 Implementação da Linguagem.........................................................................................99
 4.6 Conclusão da Avaliação.................................................................................................100
5 PROGRAMAÇÃO COM COLEÇÕES PARALELAS.......................................................100
 5.1 Simplicidade na paralelização........................................................................................101
 5.2 Exemplos de implementação.........................................................................................102
 5.3 Criando uma coleção paralela........................................................................................103
 5.4 Alguns tipos de coleções paralelas (mutáveis e imutáveis)...........................................104
 5.4.1 ParArray (Matriz Paralela)....................................................................................104
 5.4.2 ParVector (Vetor Paralelo)....................................................................................105
 5.4.3 Mutable ParHashMap (Mapa Hash Paralelo mutável).........................................106
 5.4.4 Mutable ParHashSet (Conjunto Hash Paralelo mutável)......................................107
 5.5 Conversão de coleções – Métodos par e seq..................................................................108
6 CONCLUSÃO E TRABALHOS FUTUROS......................................................................109
7 REFERÊNCIAS...................................................................................................................111
15
1 INTRODUÇÃO
Em Ciência da computação um paradigma de programação refere-se há um
modelo, padrão ou estilo de programação suportado por linguagens de programação que
agrupam certas características comuns (SÁ; SILVA, 2006). Como exemplos de paradigmas de
programação tem-se o Funcional e o Orientado a Objeto (SÁ; SILVA, 2006).
O paradigma orientado a objeto visa dar a uma linguagem de programação o
poder de simular o mundo real de forma abstrata, eficiente e eficaz. “Muitas linguagens de
programação desenvolvidas a princípio em o paradigma imperativo hoje suportam a
orientação a objeto” (SEBESTA, 2010).
“Por sua vez, a programação funcional está se tornando cada vez mais popular por
oferecer métodos atrativos de explorar o paralelismo em arquiteturas multicore e em
computação nas nuvens” (ODERSKY, 2014). No senso mais restrito a programação funcional
significa programar sem fazer uso de variáveis mutáveis, atribuições, loops, e outras
estruturas de controle da programação imperativa. Enquanto em um senso mais amplo
significa um foco em funções, pois aqui, elas podem atuar como valores que são produzidos,
consumidos e compostos. “Tudo isto porém, se torna fácil de fazer em uma linguagem de
programação funcional” (ODERSKY, 2012). 
Levando em consideração estas características apresentadas, Scala (Linguagem de
Programação Escalável) integra facilmente a programação orientada a objetos à funcional. Ela
é projetada para expressar os padrões de programação comuns delesde forma concisa,
elegante e tipada (segurança de tipos) (TYPESAFE, 2015), e ao mesmo tempo, Scala é
compatível com Java (ODERSKY, 2014). Funciona com a mesma máquina virtual.
Bibliotecas e frameworks Java podem ser usados em código Scala tal como estão, isto é, sem
código ou declarações adicionais (ODERSKY, 2014).
Scala também facilita a programação paralela de código, permitindo que um
computador com arquitetura multicore (ou um conjunto de computadores conectados) divida
o código e processe várias partes dele ao mesmo tempo (SCHEPKE, 2009) (SOBRAL, 2016).
16
1.1 Justificativa
A pouca existência de material traduzido, de comunidades de desenvolvimento
Scala (em comparação a outras linguagens de programação) e alto nível de complexidade.
Com vista nisso o presente trabalho familiarizará o interessado com a linguagem Scala e
algumas das principais características dela. Dessa forma será mais fácil decidir empenhar-se
ou não em se aprofundar nela, posto a presente falta de material traduzido.
1.2 Objetivo geral
Avaliar a linguagem Scala com base nos critérios obtidos da literatura acadêmica,
apresentando algumas de suas características principais e uma de suas capacidades para a
programação paralela.
1.3 Objetivos específicos
 Pesquisar critérios de avaliação na literatura acadêmica.
 Avaliar a linguagem Scala a partir de tais critérios.
 Apresentar as coleções paralelas da linguagem para a programação paralela.
1.4 Metodologia
 Pesquisar em trabalhos e leituras científicas critérios de avaliação adequados 
para a linguagem Scala.
 Estudar características dentre as principais da linguagem, de maneira que uma 
facilite a compreensão da outra, até que, por fim, convenha apresentar as 
coleções paralelas.
 Utilizar exemplos de código para avaliar a linguagem Scala a partir dos 
17
critérios levantados.
 Apresentar através de exemplos de código como a programação paralela é 
implementada pela linguagem.
Os próximos capitulos estarão dispostos da seguinte forma: (2) Critérios de
Avaliação: levatamento de critérios de avaliação para a referida linguagem de programação;
(3) Apresentação da linguagem e suas caracteristicas notaveis; (4) Avaliação da linguagem
Scala: resultado da avaliação com base nos critérios levantados; (5) Estudo das coleções
paralelas da biblioteca padrão da linguagem para a programação paralela; (6) Conclusão e
Trabalhos Futuros.
2 CRITÉRIOS DE AVALIAÇÃO
“Usam-se critérios de avaliação em linguagens de programação para descobrir
como os recursos de uma linguagem estão influenciando no processo de desenvolvimento e
manutenção de softwares feitos com esta linguagem” (SEBESTA, 2010). Não é sempre
possível fazer com que dois desenvolvedores de software experientes concordem a respeito do
mesmo critério em uma determinada linguagem. Mas ainda assim os critérios têm seu valor
(SEBESTA, 2010).
Os critérios escolhidos para a avaliação foram os abordados pelo autor e professor
Robert W. Sebesta em seu livro “Conceitos de Linguagens de Programação” (SEBESTA,
2010), com exceção do critério de custo, que não foi incluído no trabalho para reduzir o
tamanho do mesmo, os demais critérios são: Simplicidade Global, Ortogonalidade, Estruturas
de Controle, Tipos de Estruturas de Dados, Projeto de Sintaxe, Simplicidade e
Ortogonalidade, Suporte a Abstração, Expressividade, Tipagem, Manipulação de Exceções,
Uso Seguro de Apelidos, Portabilidade e Generalidade. O critério de implementação, que foi
utilizado no trabalho de conclusão de curso do aluno Francisco Adelanio Soares da Silva
(2014) na FACAPE (Faculdade de Ciências Sociais e Aplicadas de Petrolina), é utilizado para
enriquecer a avaliação da linguagem Scala.
18
Uma nota importante sobre critérios de avaliação: os critérios de projetos de
linguagens apresentados a seguir tem diferentes pesos quando vistos de diferentes
perspectivas. Projetistas de linguagens são propensos a enfatizar a elegância e a habilidade de
atrair um grande número de usuários. Já os implementadores de linguagens estão preocupados
principalmente com a dificuldade de implementar as construções e recursos da linguagem. Os
usuários desenvolvedores por sua vez, estão preocupados primeiramente com a facilidade de
escrita e depois com a legibilidade, enquanto analistas tem como anelo a legibilidade do
código antes de sua facilidade de escrita. “Todas essas características geralmente entram em
conflito” (SEBESTA, 2010).
2.1 Legibilidade
Quão facilmente um programa pode ser lido e entendido. O valor da legibilidade
em um código é sentido quando se faz necessária alguma manutenção no software, fato que
acontece constantemente no mercado de desenvolvimento de software. O Critério de
legibilidade agrega os subcritérios de: 
2.1.1 Simplicidade Global
Para ser simples e ter melhor aprendizado, uma linguagem precisa ter uma
quantidade pequena de construções básicas. Precisa também possuir poucas maneiras para
realizar uma mesma operação, como por exemplo, incrementar um contador. Observe o
quadro 1.
Quadro 1 – Incrementação em C.
contador = contador + 1 
contador += 1 
contador++ 
++contador 
Fonte: SEBESTA, 2010.
Outro problema em potencial é a sobrecarga de operadores, ou seja, um único
19
símbolo (seja um operador de comparação, de atribuição, ou outro similar) possuir vários
significados no código. Pode até parecer útil, mas o é apenas na fase de desenvolvimento, pois
no momento em que alguém, que não seja o desenvolvedor, ler o código, sentirá dificuldades
em relação a legibilidade do código.
2.1.2 Ortogonalidade
Ortogonalidade diz respeito a capacidade da linguagem de programação permitir
ao desenvolvedor combinar seus conceitos básicos sem que isto produza efeitos anômalos
(efeitos anormais) (MATTOS, 2015). A ortogonalidade está fortemente relacionada a
legibilidade e simplicidade do código.
Linguagens de programação ortogonais são interessantes porque o programador
pode prever, com segurança, o comportamento de uma determinada combinação de
conceitos. Isso pode ser feito sem que se tenha de implementar teste para a
averiguação do uso combinado de dois ou mais conceitos, ou mesmo buscar na
especificação da linguagem de programação se existe alguma restrição àquela
combinação.
A falta de ortogonalidade diminui o aprendizado da linguagem de programação e
pode estimular a ocorrência de erros de programação. (MATTOS, 2015)
Como outro exemplo de ortogonalidade, imagina-se um projeto de linguagem
onde o operador '+' possa ser usado tanto em operações de tipos numéricos como em
concatenações. Isto traz simplicidade, facilita o trabalho do desenvolvedor, como mostra o
exemplo do quadro 2.
Quadro 2 – Exemplos para o operador '+'.
a+b // Onde a e b são valores inteiros
78.056 + 23 + “F”
“Samuel se encontra na ” + “Padaria.”
Fonte: Autor.
Porém há momentos em que isto não convém, por exemplo, caso a = “Samuel se
encontra na ” e b = “Padaria.” o leitor do código não saberia que se tratam de strings
(supondo que não houvesse nenhuma anotação na linha do código) a não ser que ele fosse
estudar mais a fundo o código. O excesso de ortogonalidade pode levar a situações tais.
20
2.1.3 Estruturas de Controle
A existência de instruções para controle de fluxo que já estejam bem conhecidas
em outras linguagens de mesmo paradigma(s).
2.1.4 Tipos de Estruturas de Dados
Facilidades para definir tipos e estruturas de dados. Como exemplo suponha que,
devido a falta do tipo booleano em uma linguagem,o tipo numérico precise ser atribuído a
uma variável que deve armazenar uma informação booleana, observe o quadro 3.
Quadro 3 – Tipo numérico fazendo papel booleano.
timeOut = 1 
Fonte: SEBESTA, 2010.
O significado dessa sentença não estará claro para alguém (não sendo o
desenvolvedor) conseguir entender a primeira vista. Por outro lado o exemplo no quadro 4 é
uma sentença perfeitamente clara.
Quadro 4 – Tipo booleano.
timeOut = true 
Fonte: SEBESTA, 2010.
2.1.5 Projeto de Sintaxe
A sintaxe dos elementos de uma linguagem vai influenciar e muito na legibilidade
do programa. De forma geral, para uma boa sintaxe, os identificadores devem possuir um
tamanho moderado, nem muito comprido (pois pode implicar em erros de digitação), nem
muito curto (prejudica a legibilidade). A linguagem também não deve permiti o uso de suas
palavras reservadas como identificadores de variáveis, por isto atrapalhar a legibilidade do
21
código tanto pelos desenvolvedores e analistas como pelo compilador e/ou interpretador. As
palavras reservadas de uma linguagem devem ter suas formas bem definidas e de modo a
sugerir claramente o que elas fazem.
2.2 Facilidade de Escrita
Mede o quão facilmente uma linguagem pode ser usada pelo desenvolvedor para
criar um software para alguma aplicação. A maioria das características de linguagem que
afetam a legibilidade também afetam a facilidade de escrita justamente pelo desenvolvedor
constantemente ter que reler o código anteriormente já feito.
Para avaliar a facilidade de escrita é importante levar em consideração o problema
alvo para qual aquela linguagem de programação foi desenvolvida. Como exemplo disto
Robert W. Sebesta (2010, p. 33) cita:
… as facilidades de escrita do Visual BASIC (VB) e do C são drasticamente
diferentes para criar um programa com uma interface gráfica com o usuário, para o
qual VB é ideal. Suas facilidades de escrita também são bastante diferentes para a
escrita de programas de sistema, como um sistema operacional, para os quais a
linguagem C foi projetada.
2.2.1 Simplicidade e Ortogonalidade
Os critérios de simplicidade e ortogonalidade precisam aqui ser combinados e
equilibrados. “Poucos construtores, um pequeno número de primitivas, um pequeno conjunto
de regras para combiná-los” (BOECHAT, 2016). Segundo Robert W. Sebesta (2010, p. 33)
… muita ortogonalidade pode prejudicar a facilidade de escrita. Erros em programas
podem passar despercebidos quando praticamente quaisquer combinações de
primitivas são legais. Isso pode levar a certos absurdos no código que não podem ser
descobertos pelo compilador.
22
2.2.2 Suporte a Abstração
Abstração é a capacidade de definir e de usar estruturas ou operações complexas
de maneira que permita ignorar muitos dos detalhes. O grau de abstração permitido por uma
linguagem de programação e a facilidade que o desenvolvedor tem de expressar o que deseja
nela são importantes para sua facilidade de escrita. O uso de módulos prontos para
determinado algoritmo que precisa ser usado várias vezes no programa também é considerado
uma forma de abstração (abstração de processo).
2.2.3 Expressividade
Em geral para uma linguagem ter boa expressividade ela deve permitir que o
desenvolvedor especifique códigos de uma forma conveniente, e não deselegante, diminuindo
assim o número de linhas de código. Devem possuir construções que aumentem a sua
facilidade de escrita, tais como as presentes no quadro 5.
Quadro 5 – Facilidade de escrita.
• count++ é mais conveniente do que count = count + 1
• a inclusão do for em muitas linguagens modernas
Fonte: SEBESTA, 2010.
A maioria das linguagens de alto nível apresentam melhor expressividade se
comparadas com linguagens de baixo nível, pois são desenvolvidas visando, principalmente,
facilitar o trabalho do desenvolvedor de software.
2.3 Confiabilidade
Vale ressaltar aqui que a legibilidade do código afeta a confiabilidade de um
programa, tanto na escrita quanto na manutenção (SEBESTA, 2010). O critério de
confiabilidade diz respeito ao programa escrito com a linguagem de programação. Um
software pronto é dito confiável se ele estiver de acordo com todas as suas especificações em
23
todas as condições. Para uma melhor confiabilidade, também faz-se necessário que a
linguagem de programação escolhida lide bem com os seguintes subtópicos.
2.3.1 Tipagem da Linguagem
Os tipos de dados definidos na implementação de um código precisam ser testados
para descobrir se houve erros de tipo (SEBESTA, 2010). Como a verificação de tipos em
tempo de execução é cara, a verificação em tempo de compilação é mais desejável, sem falar
que quanto mais cedo os erros no programa forem encontrados e corrigidos menor será o
custo com reparos necessários (SEBESTA, 2010).
Exemplo e prova disto aconteceu em 4 de junho de 1996, onde em menos de um
minuto após seu lançamento o foguete francês Ariane 501 (projeto da Agência Espacial
Europeia) se autodestruiu (ARIANE… 1996). Após as investigações feitas por uma comissão
presidida pelo matemático francês Jacques Louis Lions, do Colégio de França, foi indicado
um erro numérico (overflow) no software de controle onde um programa que convertia um
valor em ponto flutuante para um inteiro de 16 bits recebeu como entrada um valor que estava
fora da faixa permitida e isto causou um shut-down nos computadores principal e reserva ao
mesmo tempo, resultando a terrível falha no lançamento.
2.3.2 Manipulação de Exceções
É a capacidade de perceber, interceptar e tratar erros em tempo de execução
oferecida por uma linguagem de programação. Como exemplos de linguagens que fazem o
tratamento de exceções temos Ada, C++ e Java. Mas tais facilidades são praticamente
inexistentes em muitas linguagens amplamente usadas, como C e Fortran.
2.3.3 Apelidos (Aliases)
Apelidos (aliases) são referências a endereços da memória principal;
24
mnemônicos, ponteiros, variáveis, objetos, constantes são alguns exemplos de apelidos. O uso
de apelidos pode ser algo perigoso em uma linguagem de programação, isto ocorre quando é
possível ter um ou mais nomes para acessar a mesma célula de memória, por exemplo, dois
ponteiros configurados para apontarem para o espaço de memória de uma mesma variável.
A maioria das linguagens de programação permitem algum tipo de apelido. Na
linguagem C os apelidos são implementados através de ponteiros, em Java através de objetos.
Em algumas linguagens apelidos são usados para resolver deficiências nos recursos de
abstração de dados; outras restringem o uso de apelidos para aumentar sua confiabilidade.
Alguns tipos de uso de apelidos podem ser proibidos pelo projeto de uma linguagem
(SEBESTA, 2010).
2.4 Portabilidade
Facilidade com a qual os programas podem ser movidos de uma implementação
para outra (SEBESTA, 2010). Ou seja, quão facilmente o mesmo código, escrito em uma
determinada linguagem de programação, pode ser executado em vários sistemas operacionais
e plataformas de hardware.
Depende muito do grau de padronização da linguagem, pois quanto mais
padronizada for a linguagem mais fácil será mover um programa de uma implementação para
outra. Por sua vez a padronização de uma linguagem é um processo difícil e consome muito
tempo (SEBESTA, 2010).
2.5 Generalidade
Possibilidade de uso da linguagem em uma gama de aplicações. Por exemplo,
aplicações desktop, web, mobile, tablets, sistemas embarcados, sistemas distribuídos e outros
mais. Um exemplo comum de linguagem com bastante generalidade é o Java.
25
2.6 Compilação
A compilaçãoé uma das formas usadas para adequar a uma determinada máquina
os códigos de software escritos em uma linguagem diferente da sua (linguagem de máquina).
Os programas que podem ser completamente, e de uma vez por todas, traduzidos em
linguagens de máquina (isto é, instruções de máquina), onde estas por sua vez possam ser
executadas diretamente pelo processador, possuem sua implementação baseada em
compilação.
As implementações baseadas em compilação contam com a vantagem de ter uma
execução de programas muito rápida uma vez que o processo de tradução estiver completo
(SEBESTA, 2010). “A maioria das implementações de produção das linguagens, como, C,
COBOL, Ada, é feita por meio de compiladores” (SEBESTA, 2010).
As principais fazes do processo de compilação são as seguintes:
• Análise léxica: agrupa os caracteres do código em identificadores, palavras
chaves, operadores e símbolos de pontuação. Essas informações são inseridas em uma
Tabela de Símbolos;
• Análise sintática: obtém as unidades léxicas e constrói a estrutura hierárquica
sintática do programa. Também inserindo e associando as informações conseguidas às
informações na Tabela de Símbolos;
• Código intermediário e análise semântica: reproduz o programa em uma
linguagem de nível intermediário entre o programa-fonte e a saída final do
compilador. A análise semântica verifica erros difíceis de serem observados na análise
sintática;
• Gerador de código: traduz a geração do código intermediário em um
programa equivalente à linguagem de máquina;
26
• Tabela de símbolos: serve como uma base de dados para o processo de
compilação, esses dados são escritos pelos analisadores léxico e sintático e são lidos
pelo analisador semântico e pelo gerador de código.
Figura 1 – Processo de compilação.
 
Fonte: SEBESTA, 2010.
27
2.7 Interpretação Pura
O método de Interpretação (da linguagem do código fonte para a linguagem de
máquina) é outra forma de adequar o código a uma determinada máquina local. Na
interpretação pura os programas implementados com uma linguagem de alto nível são
traduzidos linha após linha por um outro programa chamado interpretador (onde este já não
precisa ser traduzido para funcionar). O interpretador simula uma máquina física que recebe e
executa essas linhas (sentenças) de código, porém aqui, ao contrário do que normalmente
ocorre em uma máquina real onde as sentenças precisam estar em linguagem de máquina para
serem executadas, as sentenças se encontram em alto nível. Essa simulação de máquina física
é conhecida como Maquina Virtual (daquela linguagem de alto nível).
A interpretação pura tem a vantagem de permitir uma fácil implementação de
muitas operações de depuração em código fonte, pois todas as mensagens de erro em tempo
de execução podem referenciar unidades de código fonte (SEBESTA, 2010). Porém o método
de interpretação pura também traz serias desvantagens como: a lentidão no tempo de
execução, que chega a ser entre 10 e 100 vezes mais do que em sistemas compilados; a
quantidade de espaço requerido a memória principal, pois tanto a tabela de símbolos como o
código fonte tem de ser armazenados na memória; e o fato de todas as vezes em que o
programa for usado, se faz necessária uma nova interpretação.
Figura 2 – Processo de interpretação.
Fonte: SEBESTA, 2010.
28
3 LINGUAGEM SCALA
Scala é uma linguagem de programação que integra os recursos de linguagens
orientadas a objetos e funcionais (ODERSKY, 2011). Ela foi desenhada para expressar
padrões comuns de programação de forma concisa, elegante e tipada (TYPESAFE, 2015).
“Permite aos desenvolvedores serem mais produtivos, enquanto retem plena
interoperabilidade com Java e aproveitando o hardware multicore moderno” (TYPESAFE,
2015).
Muitas organizações conhecidas utilizam (ou já utilizaram) Scala, como por
exemplo: Sony, IBM, Twitter, Foursquare, Novell, LinkedIn, Siemens, Xerox, Edf, UBS
(ODERSKY, 2011). Scala pode rodar em qualquer máquina com uma JVM (Máquina Virtual
Java) instalada (da versão 1.6 às mais recentes), conforme será visto na avaliação da
linguagem. Sua distribuição estável mais recente se encontra na versão 2.11.7 e pode ser
baixada na página oficial da linguagem Scala (ÉCOLE POLYTECHNIQUE FÉDÉRALE DE
LAUSANNE, 2015).
3.1 Histórico
Scala foi desenvolvida em 2001 por Martin Odersky (ex-integrante do java
Generics) no Laboratório de Métodos de Programação localizado na EPFL (Escola
Politécnica Federal de Lausana), Suíça. Sua versão 1.0 foi lançada em novembro de 2003
(ÉCOLE POLYTECHNIQUE FÉDÉRALE DE LAUSANNE, 2015; FURTADO e PERIN e
HEBEDA, 2012). Foi liberada publicamente na plataforma Java em janeiro de 2004, e na
plataforma .NET em junho do mesmo ano. Tendo uma segunda versão da linguagem liberada
em março de 2006 (FURTADO e PERIN e HEBEDA, 2012). 
Na verdade, Scala tem sido um esforço coletivo de muitas pessoas. O design e a
implementação da versão 1.0 foi concluída por Philippe Altherr, Vincent Cremet, Gilles
Dubochet, Burak Emir, Stéphane Micheloud, Nikolay Mihaylov, Michel Schinz, Erik
29
Stenman, Matthias Zenger, e, o autor, Martin Odersky (ÉCOLE POLYTECHNIQUE
FÉDÉRALE DE LAUSANNE, 2015).
Iulian Dragos, Gilles Dubochet, Philipp Haller, Sean McDirmid, Lex Spoon, e
Geoffrey Washburn se juntaram ao esforço para desenvolver a segunda versão da
linguagem e ferramentas. Gilad Bracha, Craig Chambers, Erik Ernst, Matthias
Felleisen, Shriram Krishnamurti, Gary Leavens, Sebastian Maneth, Erik Meijer,
Klaus Ostermann, Didier Rémy, Mads Torgersen, e Philip Wadler moldaram o
projeto da linguagem através de discussões e comentários animados e inspiradores…
(ÉCOLE POLYTECHNIQUE FÉDÉRALE DE LAUSANNE, 2015). 
Os contribuintes para a lista de discussão Scala também deram um feedback útil
que ajudou a melhorar a linguagem e suas ferramentas (ÉCOLE POLYTECHNIQUE
FÉDÉRALE DE LAUSANNE, 2015).
Em 17 de Janeiro de 2011 o Time Scala ganhou uma bolsa de pesquisa de 5 anos no
valor de 2,3 milhões de Euros do European Research Council (Conselho Europeu de
Pesquisa). E em maio do mesmo ano, Odersky e alguns colaboradores fundaram a
Typesafe, uma empresa para dar suporte comercial, treinamento e serviços para
Scala (FURTADO e PERIN e HEBEDA, 2012).
3.2 Características técnicas
Scala é uma linguagem orientada a objeto e funcional, compatível com Java
(ODERSKY, 2006). Um componente Scala pode acessar todos os métodos e campos de um
componente Java, pode criar instâncias de classes Java, pode herdar de classes Java,
implementar interfaces Java, e pode ser instanciado e chamado a partir de um componente
Java (ODERSKY, 2006).
Observe um exemplo de interoperabilidade entre Java e Scala implementado na
figura 3. Percebe-se que as declarações de importação de Scala são semelhantes às
equivalentes em Java. Em Scala várias classes podem ser importadas do mesmo pacote ao
envolvê-las com colchetes, por exemplo a instrução import java.util.{Date,
Locale}. Quando se está importando tudo dentro de um pacote ou classe específica Scala
utiliza o caractere underline “_” em vez de asteriscos “*”, isto pode ser visto na declaração de
30
importação import java.text.DateFormat._, que torna o método
getDateInstace e o campo LONG (ambos estáticos) diretamente disponíveis na
implementação.
Dentro do método main é criada uma instância da classe Date (pertencente ao
Java), val agora = new Date, que por padrão contém a data atual. No passo seguinte é
escolhidoum formato de data com o método estático getDateInstance, neste caso o
formato de data escolhido foi o utilizado na França. E, a declaração
println(formatoData.format(agora)) imprime a data armazenada em agora
com o formato de data escolhido.
Figura 3 – Importação com Scala.
Fonte: SCHINZ; HALLER, 2015.
3.3 Operadores
Um operador é um símbolo que fala ao compilador para efetuar manipulações
matemáticas ou lógicas específicas (TUTORIALSPOINT, 2015). Scala é rica em operadores
internos e fornece os seguintes tipos de operadores:
31
3.3.1 Operadores Aritméticos
Supondo que variável A =10 e variável B = 20, observe na tabela 1 a apresentação
dos operadores aritméticos da linguagem Scala e seu emprego com as variáveis A e B.
Tabela 1 – Operadores aritméticos.
OPERADOR DESCRIÇÃO EXEMPLO
+ Adiciona dois operandos A + B dará 30
- Subtrai o segundo operando
do primeiro
A – B dará -10
* Multiplica os dois operandos A * B dará 200
/ Divide dividendo pelo divisor B / A dará 2
% Operador modular e resto de
uma divisão de inteiros
B % A dará 0
Fonte: TUTORIALSPOINT, 2014.
3.3.2 Operadores Relacionais
Supondo que variável A =10 e variável B = 20, observe a tabela 2 a apresentação
dos operadores relacionais da linguagem Scala e seu emprego com as variáveis A e B.
Tabela 2 – Operadores relacionais.
OPERADOR DESCRIÇÃO EXEMPLO
== Checa se os valores dos dois
operandos são iguais
A == B não é verdadeiro
!= Checa se os valores de dois
operando não são iguais
A != B é verdadeiro
> Checa se o valor do operando
a esquerda é maior que o da
direita
A > B não é verdadeiro
< Checa se o valor do operando
a esquerda é menor que o da
direita
A < B é verdadeiro
32
>= Checa se o valor do operando
a esquerda é maior ou igual
ao da direita
A >= B não é verdadeiro
<= Checa se o valor a esquerda é
menor ou igual ao da direita
A <= B é verdadeiro
Fonte: TUTORIALSPOINT, 2014.
3.3.3 Operadores Lógicos
Supondo que variável A =1 e variável B = 0, observe a tabela 3 a apresentação dos
operadores lógicos da linguagem Scala e seu emprego com as variáveis A e B.
Tabela 3 – Operadores lógicos.
OPERADOR DESCRIÇÃO EXEMPLO
&& Operador lógico and. (A && B) é falso
|| Operador lógico ou. (A || B) é verdadeiro
! Operador lógico not. !(A && B) é verdadeiro
Fonte: TUTORIALSPOINT, 2014.
3.3.4 Operadores Bit a Bit
Operadores bit a bit funcionam em bits e executam operações bit a bit. Propondo
que A = 60 e B = 13, observe na tabela 4 operações binárias com as variáveis A e B.
Tabela 4 – Operadores bit a bit.
OPERADOR DESCRIÇÃO EXEMPLO
& Operador binário and que
multiplica os bits
correspondentes entre A e B
(A & B) dará 0000 1100 que é
o mesmo que 12 em formato
inteiro.
| Operador binário or que cópia
o maior bit correspondente
onde os operando não forem
(A | B) dará 0011 1101 que é
o mesmo que 61 em formato
inteiro.
33
ambos nulos
^ Operador binário xor que
atribui 1 onde os operando
não forem iguais.
(A ^ B) dará 0011 0001 que é
o mesmo que 49 em formato
inteiro.
~ Operador binário unário de
negação.
(~A) dará 1100 0011 que é o
mesmo que -61
<< Operador binário left shift
que de acordo com o valor
especificado “move” os bits
da direita para esquerda,
preenchendo com 0 (zero) as
posições agora abertas
A << 2 dará 1111 0000 que é
o mesmo que 240 em formato
inteiro
>> Operador binário right shift
que de acordo com o valor
especificado “move” os bits
da esquerda para direita.
A >> 2 dará 1111 que
equivale a 15 em formato
inteiro.
>>> Operador binário shift right
zero que de acordo com o
valor especificado “move” os
bits da esquerda para direita,
preenchendo com 0 (zero) as
posições agora abertas.
A >>> 2 dará 0000 1111 que
equivale também a 15 em
formato inteiro.
Fonte: TUTORIALSPOINT, 2014.
3.3.5 Operadores de Atribuição
Operadores de atribuição e suas equivalências são demonstrados na tabela 5.
Tabela 5 – Operadores de atribuição.
OPERADOR DESCRIÇÃO EXEMPLO
= Operador de atribuição
simples. Atribui valores de
C = A + B atribuirá o valor
resultado de A + B para C.
34
operandos do lado direito
para o operando no lado
esquerdo do operador.
+= Operador para adicionar e
atribuir. Ele soma o operando
direito e operando esquerdo
ao operador, atribuindo o
resultado ao operando
esquerdo.
C += A é equivalente a C
= C + A.
-= Operador para subtrair e
atribuir. Ele subtrai o
operando direito do operando
esquerdo ao operador,
atribuindo o resultado ao
operando esquerdo.
C -= A é equivalente a C
= C – A.
*= Operador para multiplicar e
atribuir. Ele multiplica o
operando direito com o
operando esquerdo ao
operador, atribuindo o
resultado ao operando
esquerdo.
C *= A é equivalente a
C = C * A.
/= Operador para dividir e
atribuir. Ele divide o
operando esquerdo pelo
operando direito ao operador,
atribuindo o resultado ao
operando esquerdo.
C /= A é equivalente a C
= C / A.
%= Operador para modular e
atribuir. Ele captura o resto da
divisão entre os operandos
esquerdo e direito do
C %= A é equivalente a C
= C % A.
35
operador, atribuindo o
resultado ao esquerdo.
<<= Left shift e operador de
atribuição.
C <<= 2 é o mesmo que C
= C << 2.
>>= Right shift e operador de
atribuição.
C >>= 2 é o mesmo que C
= C >> 2.
&= AND Bit a bit e operador de
atribuição.
C &= 2 é o mesmo que
C = C & 2.
^= XOR bit a bit e operador de
atribuição.
C ^= 2 é o mesmo que C
= C ^ 2.
|= OR bit a bit inclusivo e
operador de atribuição;
C |= 2 é o mesmo que C
= C | 2.
Fonte: TUTORIALSPOINT, 2014.
3.3.6 Precedência de Operadores
A precedência de operadores determinará grupos de termos em uma mesma
expressão. Isto afeta o modo como as expressões são validadas, pois alguns operadores terão
maior precedência que outros. Por exemplo, tomemos a expressão x = 7 + 3 * 2; aqui a
x é atribuído o valor 13 e não 20, pois o operador “*” tem maior precedência que “+”, então
o primeiro a ser calculado aqui é 3 * 2 e somente então soma o valor com 7. Na tabela 6 a
seguir, os operadores com maior precedência aparecem nas primeiras posições.
Tabela 6 – Precedência de operadores.
CATEGORIA OPERADOR ASSOCIATIVIDADE
Postfix ( ) [ ] Esquerda para direita
Unário ! ~ Direita para esquerda
Multiplicativo * / % Esquerda para direita
Aditivo + - Esquerda para direita
Shift (deslocação) >> >>> << Esquerda para direita
Relacional > >= < <= Esquerda para direita
Igualdade == != Esquerda para direita
36
AND bit a bit & Esquerda para direita
XOR bit a bit ^ Esquerda para direita
OR bit a bit | Esquerda para direita
AND lógico && Esquerda para direita
OR lógico || Esquerda para direita
Atribuição = += -= *= /= %= >>=
<<= &= ^=
Direita para esquerda
Virgula , Esquerda para direita
Fonte: TUTORIALSPOINT, 2014.
3.4 Ambiente de Testes
Os testes para avaliação da linguagem Scala na versão 2.11.5 deram-se em
computador particular usando o sistema operacional Windows 7 Professional Edition
(MICROSOFT, 2015), mas Scala é compatível com qualquer plataforma que possua uma
JVM entre a versão 1.6 e alguma versão 8 instalada. 
O ambiente escolhido para as demonstrações foi o Diretório de Gerenciamento de
Comandos (CMD) do Windows junto com um interpretador Scala chamado REPL (Read –
Eval – Print – Loop, isto é,Leia – Valide – Imprima – Faça de novo), um recurso muito
interessante para os iniciantes se familiarizarem com a sintaxe da linguagem e mesmo para os
veteranos executarem testes de APIs. APIs são conjuntos de rotinas e padrões estabelecidos
por um software para a utilização das suas funcionalidades por aplicativos que não pretendem
envolver-se em detalhes da implementação do software, mas apenas usar seus serviços.
Em alguns momentos será necessário a utilização da ScalaIDE para Eclipse
(TYPESAFE, 2015) para a realização de demonstrações mais complexas e completas. Por
fim, após as devidas configurações para criar uma variável de ambiente Scala, pode-se
executar o REPL pelo terminal digitando “scala” conforme mostra a figura 4.
37
Figura 4 – Interpretador REPL.
Fonte: Autor.
Na figura 5 vê-se um erro de interpretação devido ao comando println
(imprimir informação na tela) ter sido digitado com a sintaxe incorreta “printlm”.
Figura 5 – Erro de interpretação.
Fonte: Autor.
Em Scala um ponto e vírgula “;” sempre indica o fim de uma expressão, porém,
não é obrigatório para isto. Ao mesmo tempo, e a depender da situação em que for usada, uma
nova linha (Enter) também pode indicar o fim de uma expressão. Tem-se como exemplo o que
acontece na figura 6.
Figura 6 – Inferência do “;”.
Fonte: Autor.
38
Mas para que o código aqui possa funcionar da maneira esperada as seguintes
condições precisam ser atendidas:
1. A linha em questão NÃO deve terminar com alguma palavra (como um período
ou um operador infixo) que não seja o legal (correto, permitido) para o fim de
uma expressão. Exemplo: def Exemplo_2(x: Int) = x *
2. A próxima linha NÃO deve começar com uma palavra incorreta para o início
de uma nova expressão. Exemplo: 
def Exemplo_2(x: Int) = (x
+ y)
3. Código tem de estar fora de parênteses “()” ou colchetes “[]”, caso contrário
precisará utilizar ponto e vírgula “;”.
Vale mencionar também que Scala é uma linguagem case sensitive, ou seja, caixas
maiúsculas e minúsculas são tratadas de forma diferente pela linguagem, por exemplo,
Exemplo_1 é algo diferente de exemplo_1.
3.5 Expressões e Funções Simples
Observe alguns exemplos de expressões simples na figura 7. Não há nenhuma
atribuição de valor aqui, mas em situações assim o interpretador REPL automaticamente cria
values (espaços de memória alocados que funcionam como constantes), por exemplo, res0,
res1, res2, etc … para alocar o resultado de cálculos e expressões.
39
Figura 7 – Expressões simples.
Fonte: Autor.
Scala possui inferência de tipos, ou seja, não é obrigatório sempre declarar o tipo
de dados, ainda que isso seja recomendado para uma boa documentação, mas de fato Scala foi
desenvolvida para em muitas situações descobrir o tipo de dados que está sendo atribuído, Isto
vale para values, variáveis e funções. Caso necessite, o desenvolvedor pode usar as values
criadas pelo interpretador, conforme mostra a figura 8.
Figura 8 – Values criados pelo REPL.
Fonte: Autor.
Funções em Scala são chamadas de Definições. Definições são semelhantes a
métodos em Java, e são declaradas usando a palavra reservada def, que deve ser seguida
respectivamente do nome da função, seus parâmetros (se houverem), seu tipo de retorno
(optativo por causa da inferência de tipos do Scala), e por fim, seu corpo após o sinal “=”, tal
como é apresentada no quadro 6.
40
Quadro 6 – Definições em Scala.
def nomeFuncao(parametro: Tipo de dado): Tipo de dado =
expressão
Fonte: Autor.
Scala oferece a possibilidade de criação de values, como mostra a value vCubo
na figura 9. Values são indicadas pela palavra reservada val.
Figura 9 – Validação de values.
Fonte: Autor.
Uma função (def) é validada substituindo no código o seu nome pelo seu corpo
não resolvido, isto é não reduzido a algum valor (tal como ele está escrito em sua definição).
Alternativamente, uma value (val) é validada substituindo o seu nome no código pelo seu
corpo já resolvido, isto é, já reduzido a um resultado. Quando então a value for utilizada no
código imediatamente ela será substituída pelo seu valor já pré-computado, não precisando ser
validada novamente. A função, por sua vez, precisará sempre ser resolvida (reduzida) todas as
vezes que for utilizada pelo código. 
3.6 Valores Imutáveis
As values, apresentadas no tópico anterior, são consideradas valores imutáveis,
semelhantes a constantes Java definidas pela palavra reservada final, como por exemplo:
final String nome = “Adriel”. Observe no exemplo da figura seguinte que ao ser
atribuído outro valor a value nome ocorre um erro no interpretador. 
41
Figura 10 – Valores imutáveis.
Fonte: Autor.
Portanto, ao declarar-se um valor imutável (val), é preciso que já em sua
declaração lhe seja atribuído algum valor, pois não será permitido alterar ou atribuir mais
nada a val durante o resto do código. Observa-se no código o método principal (main) e o
tipo desse método (Unit, logo a direita dos parâmetros). Unit é semelhante ao void do
Java, e é ele quem indica que o método principal não retorna nada. Scala também trabalha
com valores mutáveis, ou seja, variáveis, através da palavra reservada var (semelhantes a
atributos em outras linguagens de programação).
3.7 Parâmetros
Sobre toda função parametrizada o compilador/interpretador do Scala possui duas
formas diferentes de chamar argumentos recebidos ao corpo da função: call-by-value e call-
by-name. Caso nada seja especificado pelo desenvolvedor, a forma call-by-value é adotada
como padrão pelo compilador/interpretador, e exatamente isto (call-by-value adotada como
padrão) acontece no código da figura 11, onde as funções quadrado e
somaDeQuadrados são criadas de forma normal.
42
Figura 11 – Validação call-by-value.
Fonte: Autor.
Observe no quadro 7 como a função somaDeQuadrados(3, 5+7) da figura
11 foi validada pelo interpretador. A passagem de parâmetros por call-by-value segue os
seguintes passos:
1. Cada argumento passado a função, da esquerda para a direita, é resolvido (reduzido a
um resultado) por meio de um modelo de substituição de sentenças.
2. Feito isto, a chamada da função (no código) é substituída pelo seu corpo já com os
argumentos resolvidos.
Quadro 7 – Chamada de argumentos call-by-value.
SomaDeQuadrados(3, 5+7) //Argumento ainda não foi resolvido
somaDeQuadrados(3, 12) //Argumento resolvido
quadrado(3) + quadrado(12) //Corpo com argumentos resolvidos
3 * 3 + quadrado(12)
9 + quadrado(12)
9 + 12 * 12
9 + 144
153
 Fonte: Autor.
Porém há situações em que o interpretador não consegue validar uma expressão
em um número finito de passos com call-by-value. Por exemplo, observe a função teste no
quadro 8 e note que o argumento loop está sendo passado a função por meio de teste(1,
loop). Contudo loop não é utilizado em nada no corpo de teste. E ali, justamente pelo
43
interpretador querer resolver loop, será impedido de chegar a um resultado em um número
finito de passos.
Tem-se então a função teste2 utilizando o modelo de validação call-by-name,
que possibilita aplicar ao corpo da função os argumentos ainda não reduzidos, e, somente os
que ele utilizará (os necessários). Se o tipo do parâmetro de uma função for escrito
começando com o símbolo =>, Scala usará call-by-name para validar aquele parâmetro.
Quadro 8 – Função loop.
def loop: Int = loop
//Validação com call-by-value
def teste(x: Int, y: Int): Int = x
teste(1, loop)
//Validação com call-by-name
def teste2(x: Int, y: => Int): Int = x
teste2(1, loop)
Fonte: Autor.
Observe como o exemplo da figura 11 é reescrito na figura 12 com a utilizaçãode
call-by-name em dado momento.
Figura 12 – Validação call-by-name.
Fonte: Autor.
Ambas estratégias convergem ao mesmo resultado, diferenciando apenas o
número de passos dados. Observe no quadro 9 a função somaDeQuadrados(3, 5+7)
sendo validada, agora com call-by-name.
44
Quadro 9 – Chamada de argumentos call-by-name.
somaDeQuadrados(3, 5+7)
quadrado(3) + quadrado(5+7)
3 * 3 + quadrado(5+7)
9 + quadrado(5+7)
9 + (5+7) * (5+7)
9 + 12 * (5+7)
9 + 12 * 12
9 + 144
153
Fonte: Autor.
Call-by-value possui a vantagem de evitar repetidas resoluções dos argumentos. Já
Call-by-name possui a vantagem de evitar resolver argumentos nos casos em que um
determinado parâmetro não está sendo usado em nada pelo corpo da função (quadro 8). Call-
by-value é usualmente mais eficiente que call-by-name, mas, call-by-value pode entrar em
loop onde call-by-name poderia concluir seu dever.
3.8 Expressão Condicional If-else
O If-else do Scala permite uma escolha entre duas expressões alternativas. Sua
sintaxe é como o if-else do Java. Mas onde if-else do Java é utilizado apenas como uma
alternativa de declarações simples, Scala pode usar a mesma sintaxe para escolher entre duas
expressões. Observe o exemplo de If-else em Scala na figura 13.
Figura 13 – Exemplo If-else em Scala.
Fonte: Autor.
Expressões If do Scala também podem resultar em um valor, semelhantemente
ao operador ternário do java (ODERSKY e SPOON e VENNERS, 2008). 
45
3.9 Recursão de Cauda (Tail Recursion)
Funções recursivas são definições que em algum lugar do seu corpo chamam a si
mesmas. Observe a função da figura 14 (fatoracao) e sua validação no quadro 10. Na
figura 14, pelo modo como a recursão é ali implementada obtêm-se cadeias mais longas e
mais longas de operandos, sendo necessário alocar cada vez mais espaço de memória, até que
enfim, os operandos sejam multiplicados na última parte da sequência de validação 5 * (4
* (3 * (2* (1 * 1)))).
Figura 14 – Recursividade comum.
Fonte: Autor.
Quadro 10 – Validação da fatoração.
fatoracao(5)
 if(5 == 0) 1 else 5 * fatoracao(5 – 1)
 5 * fatoracao(5 – 1)
 5 * fatoracao(4)
 … 5 * (4 * fatoracao(3))
 … 5 * (4 * (3 * fatoracao(2)))
 … 5 * (4 * (3 * (2* fatoracao(1))))
 … 5 * (4 * (3 * (2* (1 * fatoracao(0)))))
 … 5 * (4 * (3 * (2* (1 * 1))))
 … 120
Fonte: Autor.
Scala possibilita o uso de recursões de cauda (Tail Recursion) que é uma forma
mais dinâmica e interativa de serem feitas recursões, possibilitando que elas sejam executadas
em um espaço de memória constante.
46
Veja na figura 15 a mesma função, agora, fazendo uso de recursão de cauda. A
recursão fatoracao(n-1, result*n) está sendo a última ação realizada no if-else, e
sem mais nenhuma operação ligada a ela. O fato de não ter mais nenhuma operação ligada a
ela, por exemplo, … n * fatoracao, faz com que nenhum novo espaço de pilha, isto é de
memória, seja necessário, e aqui os sucessivos argumentos gerados pela recursão
fatoracao(n-1, result*n) apenas ficarão substituindo os atuais. Por isso o nome
“recursão de cauda”, pois não deixa um rastro de valores armazenados para realizar o calculo
somente no último momento. Por fim, em Scala toda função recursiva (de cauda ou não)
precisa declarar explicitamente seu tipo de retorno, por exemplo, o tipo de retorno da função
fatoracao é Int.
Figura 15 – Recursão de cauda.
Fonte: Autor.
Observe a forma como a função com recursão de cauda é validada. Quadro 11.
Quadro 11 – Validação com recursão de cauda.
fatoracao(5, 1)
 if(5 == 1) 1 else fatoracao(5–1, 1*5)
 if(4 == 1) 5 else fatoracao(4–1, 5*4)
 if(3 == 1) 20 else fatoracao(3–1, 20*3)
 if(2 == 1) 60 else fatoracao(2–1, 60*2)
 if(1 == 1) 120
 120
Fonte: Autor.
47
Em princípio, as recursões de cauda sempre podem reusar o quadro de pilha
(reusar o mesmo espaço de memória) da função que a chama. No entanto, alguns ambientes
run-time (como o JVM 7) não têm as primitivas para fazer reúso eficiente do quadro de pilha
para recursões de cauda. Uma implementação Scala feita com qualidade é, portanto, requerida
para reutilizar o quadro de pilha de uma função recursiva de cauda. Não se deve contar com
esse recurso em toda implementação. 
3.10 Funções de Ordem Superior (High-Order Functions)
Uma função em Scala é considerada uma espécie de “valor de primeira classe”.
Como qualquer outro valor, funções podem ser passadas como argumentos ou devolvidas
como resultado. Funções cujos parâmetros recebam outras funções como argumentos, e/ou,
devolvam funções como resultado, são chamadas de Funções de Ordem Superior
(ODERSKY, 2014). Elas fornecem um mecanismo flexível para a composição de programas e
são um traço forte na linguagem Scala.
Observe os exemplos dos quadros 12 e 13 seguintes. Neles foram implementadas
funções que calculam a soma de valores inteiros, cubos e fatoriais dentro de algum intervalo.
O quadro 12 faz isto se utilizando de funções comuns enquanto o quadro 13 se utiliza de
funções de ordem superior.
48
Quadro 12 – Funções comuns.
//SOMA DE INTEIROS
def somaInts(a: Int, b: Int): Int =
if (a > b) 0 else a + somaInts(a + 1, b)
//SOMA DE CUBOS
def cubo(x: Int): Int = x * x * x
def somaCubos(a: Int, b: Int): Int =
if (a > b) 0 else cubo(a) + somaCubos(a + 1, b)
//SOMA DE FATORIAIS
def fatorial(n: Int, result: Int): Int = 
if (n == 0) result else fatorial(n-1, result*n)
def somaFatoriais(a: Int, b: Int): Int =
if (a > b) 0 else fatorial(a, 1) + somaFatoriais(a + 1, b)
Fonte: Autor.
Uma observação importante para a compreensão do quadro 13 seguinte: o
parâmetro f: Int => Int da função soma indica que para aquele parâmetro o argumento
precisa ser uma função, Int => Int indica que esta função pode ser qualquer uma que
receba um inteiro como argumento e retorne um inteiro como resultado. As funções
somaInts, somaCubos, e somaFatoriais estão retornando como resultado as funções
soma(id, a, b), soma(cubo, a, b) e soma(fatorial, a, b).
Quadro 13 – Funções de ordem superior.
def id(x: Int): Int = x
def cubo(x: Int): Int = x * x * x
def fatorial(x: Int): Int = if (x == 0) 1 else 
 x * fatorial(x - 1)
def soma(f: Int => Int, a: Int, b: Int): Int =
if (a > b) 0 else f(a) + soma(f, a + 1, b)
def somaInts(a: Int, b: Int) = soma(id, a, b)
def somaCubos(a: Int, b: Int) = soma(cubo, a, b)
def somaFatoriais(a: Int, b: Int) = soma(fatorial, a, b)
Fonte: Autor.
49
Ao comparar o quadro 12 com o quadro 13 destacam-se duas diferenças entre as
duas implementações do mesmo problema.
1. Com o uso de funções de ordem superior a dependência que as funções têm uma das
outras é maior.
2. O número de funções no quadro 13 para resolver o problema foi maior, contudo, no
geral as funções ficaram mais simples do que as implementadas no quadro 12.
As funções anônimas (tópico seguinte) tem influência positiva sobre os dois
aspectos citados acima.
3.11 Funções Anônimas
O uso de funções como parâmetros tende a criar muitas funções pequenas
(ODERSKY, 2014). Ao invés do desenvolvedor criar várias e pequenas funções com suas
assinaturas (nome da função, parâmetros e tipo de retorno) para servirem de argumentos a
funções de ordem superior, Scala lhe possibilita formulá-las de forma mais rápida e curta com
o uso de Funções Anônimas (Anonymous Function).
Uma função anônima é uma função que é definida sem dar-lhe um nome, ao
mesmo tempo que o compilador/interpretador a trata da mesma forma que uma função
qualquer. Como exemplo, na figura 16, considere a função anônima logo abaixo da função
cubo, esta função anônima realiza o mesmo que a função cubo. Em funções anônimas a
parte

Outros materiais

Materiais relacionados

Perguntas relacionadas

Perguntas Recentes