Clone ou baixe o projeto da lista,
importe ele no IntelliJ, e implemente as funções
correspondentes a cada questão do exercício. Depois envie um novo Lista3.zip
com
as modificações até 30/10/2017,
usando esse link.
Implemente os padrões de recursão em listas que usamos em Scala: map
, filter
,
foldRight
, foldLeft
e flatMap
como funções de fun para trabalhar com listas
construídas com as funções abaixo:
fun Cons(h, t)
fun (v, c)
(c)(h, t)
end
end
fun Vazia()
fun (v, c)
(v)()
end
end
fun tamanho(l)
(l)(fun () 0 end, fun (h, t) 1 + tamanho(t) end)
end
fun map(f, l)
-- implementação de map
end
fun filter(p, l)
-- implementação de filter
end
fun foldLeft(z, op, l)
-- implementação de foldLeft
end
fun foldRight(z, op, l)
-- implementação de foldRight
end
fun flatMap(f, l)
-- implementação de flatMap
end
Implemente as funções no arquivo listas.sc
.
Embora possamos usar recursão para fazer laços, em uma linguagem imperativa o mais
natural é ter uma expressão específica para isso. Vamos acrescentar um laço while
a fun, com a sintaxe while EXP do EXP end
. O parser de fun já foi modificado
para aceitar essa expressão e gerar um nó While
com a estrutura abaixo:
case class While(econd: Exp, corpo: Exp) extends Exp
Acrescente casos a eval
, fvs
e subst
para While
.
Um tipo bem comum de efeito colateral é a entrada e saída, onde uma linguagem de programação pode ler valores de algum dispositivo de entrada e escrever valores para algum dispositivo de saída.
Podemos incorporar entrada e saída a fun modificando o tipo Acao[T]
para receber
e produzir “dispositivos” de entrada e saída:
type Acao[T] = (Stream[Valor], List[String], Mem) => (Either[T, Erro], Stream[Valor], List[String], Mem)
A entrada é um Stream
de valores. Uma stream é uma lista potencialmente infinita: dada uma stream s
lemos
o próximo elemento dela com s.head
, e obtemos uma stream sem esse próximo elemento com s.tail
. A saída
é a lista de strings impressas.
Podemos acrescentar duas ações primitivas, uma para ler um valor da entrada e outra para imprimir uma string na saída:
def levalor: Acao[Valor] = ???
def imprime(s: Valor): Acao[Valor] = ???
Implemente a mudança no tipo Acao[T]
, mudando as primitivas existentes para levar em
conta entrada/saída (em especial a bind
), depois implemente as novas primitivas.
Preste atenção na linearidade da entrada/saída.
Para usar essas primitivas precisamos de novas expressões em fun. O parser de fun
já foi modificado para aceitar as expressões read
e print '(' [EXP {',' EXP}] ')'
,
que correspondem aos casos abaixo:
case class Read() extends Exp
case class Print(args: List[Exp]) extends Exp
Implemente os casos de Read
e Print
nas funções fvs
, subst
, e eval
. A
expressão Read
avalia para o próximo valor na entrada (consumindo esse valor),
enquanto Print
avalia sua lista de argumentos da esquerda pra direita e os
imprime como uma string, separados por tabs.
Última Atualização: 2017-11-28 17:18