diff options
Diffstat (limited to 'pt-pt')
-rw-r--r-- | pt-pt/bf-pt.html.markdown (renamed from pt-pt/brainfuck-pt.html.markdown) | 1 | ||||
-rw-r--r-- | pt-pt/git-pt.html.markdown | 2 | ||||
-rw-r--r-- | pt-pt/scala-pt.html.markdown | 651 | ||||
-rw-r--r-- | pt-pt/swift-pt.html.markdown | 609 |
4 files changed, 1262 insertions, 1 deletions
diff --git a/pt-pt/brainfuck-pt.html.markdown b/pt-pt/bf-pt.html.markdown index da4c787f..13c22387 100644 --- a/pt-pt/brainfuck-pt.html.markdown +++ b/pt-pt/bf-pt.html.markdown @@ -1,5 +1,6 @@ --- language: brainfuck +filename: brainfuck-pt.bf contributors: - ["Prajit Ramachandran", "http://prajitr.github.io/"] - ["Mathias Bynens", "http://mathiasbynens.be/"] diff --git a/pt-pt/git-pt.html.markdown b/pt-pt/git-pt.html.markdown index a85c9704..bd0f0fc5 100644 --- a/pt-pt/git-pt.html.markdown +++ b/pt-pt/git-pt.html.markdown @@ -2,7 +2,7 @@ category: tool tool: git lang: pt-pt -filename: LearnGit.txt +filename: LearnGit-pt.txt contributors: - ["Jake Prather", "http://github.com/JakeHP"] translators: diff --git a/pt-pt/scala-pt.html.markdown b/pt-pt/scala-pt.html.markdown new file mode 100644 index 00000000..a4c1c02b --- /dev/null +++ b/pt-pt/scala-pt.html.markdown @@ -0,0 +1,651 @@ +--- +language: Scala +filename: learnscala-pt.scala +contributors: + - ["George Petrov", "http://github.com/petrovg"] + - ["Dominic Bou-Samra", "http://dbousamra.github.com"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Ha-Duong Nguyen", "http://reference-error.org"] +translators: + - ["João Costa", "http://joaocosta.eu"] +lang: pt-pt +--- + +Scala - a linguagem escalável + +```scala + +/* + Prepare tudo: + + 1) Faça Download do Scala - http://www.scala-lang.org/downloads + 2) Faça unzip/untar para onde preferir e coloque o subdirectório `bin` na + variável de ambiente `PATH` + 3) Inicie a REPL de Scala correndo o comando `scala`. Deve aparecer: + + scala> + + Isto é chamado de REPL (Read-Eval-Print Loop / Lê-Avalia-Imprime Repete). + Pode escrever qualquer expressão de Scala e o resultado será imprimido. + Vamos mostrar ficheiros de Scala mais à frente neste tutorial mas, para já, + vamos começar com os básicos. + +*/ + + +///////////////////////////////////////////////// +// 1. Basicos +///////////////////////////////////////////////// + +// Uma linha de comentários é marcada com duas barras + +/* + Comentários de multiplas linhas, como se pode ver neste exemplo, são assim. +*/ + +// Imprimir, forçando uma nova linha no final +println("Hello world!") +println(10) + +// Imprimir, sem forçar uma nova linha no final +print("Hello world") + +// Valores são declarados com var ou val. +// As declarações val são imutáveis, enquanto que vars são mutáveis. +// A immutabilidade é uma propriedade geralmente vantajosa. +val x = 10 // x é agora 10 +x = 20 // erro: reatribuição de um val +var y = 10 +y = 20 // y é agora 12 + +/* + Scala é uma linguagem estaticamente tipada, no entanto, nas declarações acima + não especificamos um tipo. Isto é devido a uma funcionalidade chamada + inferência de tipos. Na maior parte dos casos, o compilador de scala consegue + inferir qual o tipo de uma variável, pelo que não o temos de o declarar sempre. + Podemos declarar o tipo de uma variável da seguinte forma: +*/ +val z: Int = 10 +val a: Double = 1.0 + +// Note a conversão automática de Int para Double: o resultado é 10.0, não 10 +val b: Double = 10 + +// Valores booleanos +true +false + +// Operações booleanas +!true // false +!false // true +true == false // false +10 > 5 // true + +// A matemática funciona da maneira habitual +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 +6 / 4 // 1 +6.0 / 4 // 1.5 + + +// Avaliar expressões na REPL dá o tipo e valor do resultado + +1 + 7 + +/* A linha acima resulta em: + + scala> 1 + 7 + res29: Int = 8 + + Isto significa que o resultado de avaliar 1 + 7 é um objecto do tipo Int com + o valor 8. + + Note que "res29" é um nome de uma variavel gerado sequencialmente para + armazenar os resultados das expressões que escreveu, por isso o resultado + pode ser ligeiramente diferente. +*/ + +"Strings em scala são rodeadas por aspas" +'a' // Um caracter de Scala +// 'Strings entre plicas não existem' <= Isto causa um erro + +// Strings tem os métodos de Java habituais definidos +"olá mundo".length +"olá mundo".substring(2, 6) +"olá mundo".replace("á", "é") + +// Para além disso, também possuem métodos de Scala. +// Ver: scala.collection.immutable.StringOps +"olá mundo".take(5) +"olá mundo".drop(5) + +// Interpolação de Strings: repare no prefixo "s" +val n = 45 +s"Temos $n maçãs" // => "Temos 45 maçãs" + +// Expressões dentro de Strings interpoladas também são possíveis +val a = Array(11, 9, 6) +s"A minha segunda filha tem ${a(0) - a(2)} anos." // => "A minha segunda filha tem 5 anos." +s"Temos o dobro de ${n / 2.0} em maçãs." // => "Temos o dobro de 22.5 em maçãs." +s"Potência de 2: ${math.pow(2, 2)}" // => "Potência de 2: 4" + +// Strings interpoladas são formatadas com o prefixo "f" +f"Potência de 5: ${math.pow(5, 2)}%1.0f" // "Potência de 5: 25" +f"Raíz quadrada 122: ${math.sqrt(122)}%1.4f" // "Raíz quadrada de 122: 11.0454" + +// Strings prefixadas com "raw" ignoram caracteres especiais +raw"Nova linha: \n. Retorno: \r." // => "Nova Linha: \n. Retorno: \r." + +// Alguns caracteres tem de ser "escapados", e.g. uma aspa dentro de uma string: +"Esperaram fora do \"Rose and Crown\"" // => "Esperaram fora do "Rose and Crown"" + +// Strings rodeadas por três aspas podem-se estender por varias linhas e conter aspas +val html = """<form id="daform"> + <p>Carrega aqui, Zé</p> + <input type="submit"> + </form>""" + + +///////////////////////////////////////////////// +// 2. Funções +///////////////////////////////////////////////// + +// Funções são definidas como: +// +// def nomeDaFuncao(args...): TipoDeRetorno = { corpo... } +// +// Se vem de linugagens mais tradicionais, repare na omissão da palavra +// return keyword. Em Scala, a ultima expressão de um bloco é o seu +// valor de retorno +def somaQuadrados(x: Int, y: Int): Int = { + val x2 = x * x + val y2 = y * y + x2 + y2 +} + +// As { } podem ser omitidas se o corpo da função for apenas uma expressão: +def somaQuadradosCurto(x: Int, y: Int): Int = x * x + y * y + +// A sintaxe para chamar funções deve ser familiar: +somaQuadrados(3, 4) // => 25 + +// Na maior parte dos casos (sendo funções recursivas a principal excepção), o +// tipo de retorno da função pode ser omitido, sendo que a inferencia de tipos +// é aplicada aos valores de retorno +def quadrado(x: Int) = x * x // O compilador infere o tipo de retorno Int + +// Funções podem ter parâmetros por omissão: +def somaComOmissão(x: Int, y: Int = 5) = x + y +somaComOmissão(1, 2) // => 3 +somaComOmissão(1) // => 6 + + +// Funções anónimas são definidas da seguinte forma: +(x: Int) => x * x + +// Ao contrário de defs, o tipo de input de funções anónimas pode ser omitido +// se o contexto o tornar óbvio. Note que o tipo "Int => Int" representa uma +// funão que recebe Int e retorna Int. +val quadrado: Int => Int = x => x * x + +// Funcões anónimas são chamadas como funções normais: +quadrado(10) // => 100 + +// Se cada argumento de uma função anónima for usado apenas uma vez, existe +// uma forma ainda mais curta de os definir. Estas funções anónumas são +// extremamente comuns, como será visto na secção sobre estruturas de dados. +val somaUm: Int => Int = _ + 1 +val somaEstranha: (Int, Int) => Int = (_ * 2 + _ * 3) + +somaUm(5) // => 6 +somaEstranha(2, 4) // => 16 + + +// O código return existe em Scala, mas apenas retorna do def mais interior +// que o rodeia. +// AVISO: Usar return em Scala deve ser evitado, pois facilmente leva a erros. +// Não tem qualquer efeito em funções anónimas, por exemplo: +def foo(x: Int): Int = { + val funcAnon: Int => Int = { z => + if (z > 5) + return z // Esta linha faz com que z seja o retorno de foo! + else + z + 2 // Esta linha define o retorno de funcAnon + } + funcAnon(x) // Esta linha define o valor de retorno de foo +} + + +///////////////////////////////////////////////// +// 3. Controlo de fluxo +///////////////////////////////////////////////// + +1 to 5 +val r = 1 to 5 +r.foreach(println) + +r foreach println +// NB: Scala é bastante brando no que toca a pontos e parentisis - estude as +// regras separadamente. Isto permite escrever APIs e DSLs bastante legiveis + +(5 to 1 by -1) foreach (println) + +// Ciclos while +var i = 0 +while (i < 10) { println("i " + i); i += 1 } + +while (i < 10) { println("i " + i); i += 1 } // Sim, outra vez. O que aconteceu? Porquê? + +i // Mostra o valor de i. Note que o while é um ciclo no sentido clássico - + // executa sequencialmente enquanto muda uma variável. Ciclos while são + // rápidos, por vezes até mais que ciclos de Java, mas combinadores e + // compreensões (usados anteriormente) são mais fáceis de entender e + // paralelizar + +// Um ciclo do while +i = 0 +do { + println("i ainda é menor que 10") + i += 1 +} while (i < 10) + +// A forma idiomática em Scala de definir acções recorrentes é através de +// recursão em cauda. +// Funções recursivas necessitam de um tipo de retorno definido explicitamente. +// Neste caso, é Unit. +def mostraNumerosEntre(a: Int, b: Int): Unit = { + print(a) + if (a < b) + mostraNumerosEntre(a + 1, b) +} +mostraNumerosEntre(1, 14) + + +// Condicionais + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + + +///////////////////////////////////////////////// +// 4. Estruturas de dados +///////////////////////////////////////////////// + +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21) // Lança uma excepção + +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle") // Lança uma excepção + +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") + +val s = Set(1, 3, 7) +s(0) +s(1) + +/* Veja a documentação de mapas de scala em - + * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map + * e verifique que a consegue aceder + */ + + +// Tuplos + +(1, 2) + +(4, 3, 2) + +(1, 2, "três") + +(a, 2, "três") + +// Porquê ter isto? +val divideInts = (x: Int, y: Int) => (x / y, x % y) + +divideInts(10, 3) // A função divideInts returna o resultado e o resto + +// Para aceder aos elementos de um tuplo, pode-se usar _._n, onde n é o indice +// (começado em 1) do elemento +val d = divideInts(10, 3) + +d._1 + +d._2 + + +///////////////////////////////////////////////// +// 5. Programação Orientada a Objectos +///////////////////////////////////////////////// + +/* + Aparte: Até agora tudo o que fizemos neste tutorial foram expressões simples + (valores, funções, etc). Estas expressões são suficientes para executar no + interpretador da linha de comandos para testes rápidos, mas não podem existir + isoladas num ficheiro de Scala. Por exemplo, não é possivel correr um + ficheiro scala que apenas contenha "val x = 5". Em vez disso, as únicas + construções de topo permitidas são: + + - object + - class + - case class + - trait + + Vamos agora explicar o que são: +*/ + +// Classes são semelhantes a classes noutras linguagens. Os argumentos do +// construtor são declarados após o nome da classe, sendo a inicialização feita +// no corpo da classe. +class Cão(rc: String) { + // Código de construção + var raça: String = rc + + // Define um método chamado "ladra", que retorna uma String + def ladra = "Woof, woof!" + + // Valores e métodos são assumidos como públicos, mas é possivel usar + // os códigos "protected" and "private". + private def dormir(horas: Int) = + println(s"Vou dormir por $horas horas") + + // Métodos abstractos são métodos sem corpo. Se descomentarmos a próxima + // linha, a classe Cão é declarada como abstracta + // abstract class Cão(...) { ... } + // def persegue(oQue: String): String +} + +val oMeuCão = new Cão("greyhound") +println(oMeuCão.raça) // => "greyhound" +println(oMeuCão.ladra) // => "Woof, woof!" + + +// O termo "object" cria um tipo e uma instancia singleton desse tipo. É comum +// que classes de Scala possuam um "objecto companheiro", onde o comportamento +// por instância é capturado nas classes, equanto que o comportamento +// relacionado com todas as instancias dessa classe ficam no objecto. +// A diferença é semelhante a métodos de classes e métodos estáticos noutras +// linguagens. Note que objectos e classes podem ter o mesmo nome. +object Cão { + def raçasConhecidas = List("pitbull", "shepherd", "retriever") + def criarCão(raça: String) = new Cão(raça) +} + + +// Case classes são classes com funcionalidades extra incluidas. Uma questão +// comum de iniciantes de scala é quando devem usar classes e quando devem usar +// case classes. A linha é difusa mas, em geral, classes tendem a concentrar-se +// em encapsulamento, polimorfismo e comportamento. Os valores nestas classes +// tendem a ser privados, sendo apenas exposotos métodos. O propósito principal +// das case classes é armazenarem dados imutáveis. Geralmente possuem poucos +// métods, sendo que estes raramente possuem efeitos secundários. +case class Pessoa(nome: String, telefone: String) + +// Cria uma nova instancia. De notar que case classes não precisam de "new" +val jorge = Pessoa("Jorge", "1234") +val cátia = Pessoa("Cátia", "4567") + +// Case classes trazem algumas vantagens de borla, como acessores: +jorge.telefone // => "1234" + +// Igualdade por campo (não é preciso fazer override do .equals) +Pessoa("Jorge", "1234") == Pessoa("Cátia", "1236") // => false + +// Cópia simples +// outroJorge == Person("jorge", "9876") +val outroJorge = jorge.copy(telefone = "9876") + +// Entre outras. Case classes também suportam correspondência de padrões de +// borla, como pode ser visto de seguida. + + +// Traits em breve! + + +///////////////////////////////////////////////// +// 6. Correspondência de Padrões +///////////////////////////////////////////////// + +// A correspondência de padrões é uma funcionalidade poderosa e bastante +// utilizada em Scala. Eis como fazer correspondência de padrões numa case class: +// Nota: Ao contrário de outras linguagens, cases em scala não necessitam de +// breaks, a computação termina no primeiro sucesso. + +def reconhecePessoa(pessoa: Pessoa): String = pessoa match { + // Agora, especifique os padrões: + case Pessoa("Jorge", tel) => "Encontramos o Jorge! O seu número é " + tel + case Pessoa("Cátia", tel) => "Encontramos a Cátia! O seu número é " + tel + case Pessoa(nome, tel) => "Econtramos alguém : " + nome + ", telefone : " + tel +} + +val email = "(.*)@(.*)".r // Define uma regex para o próximo exemplo. + +// A correspondência de padrões pode parecer familiar aos switches em linguagens +// derivadas de C, mas é muto mais poderoso. Em Scala, é possível fazer +// correspondências com muito mais: +def correspondeTudo(obj: Any): String = obj match { + // Pode-se corresponder valores: + case "Olá mundo" => "Recebi uma string Olá mundo." + + // Corresponder por tipo: + case x: Double => "Recebi um Double: " + x + + // Corresponder tendo em conta condições especificas: + case x: Int if x > 10000 => "Recebi um número bem grande!" + + // Fazer correspondências com case classes (visto anteriormente): + case Pessoa(nome, tel) => s"Recebi o contacto para $nome!" + + // Fazer correspondência com expressões regulares: + case email(nome, dominio) => s"Recebi o endereço de email $nome@$dominio" + + // Corresponder tuplos: + case (a: Int, b: Double, c: String) => s"Recebi o tuplo: $a, $b, $c" + + // Corresponder estruturas de dados: + case List(1, b, c) => s"Recebi uma lista de 3 elementos começada em 1: 1, $b, $c" + + // Combinar padrões: + case List(List((1, 2, "YAY"))) => "Recebi uma lista de lista de triplo" +} + +// Na realidade, é possível fazer correspondência com qualquer objecto que +// defina o método "unapply". Esta funcionalidade é tão poderosa que permite +// definir funções sob a forma de padrões: +val funcPaddrao: Pessoa => String = { + case Pessoa("Jorge", tel) => s"Número do Jorge: $tel" + case Pessoa(nome, tel) => s"Número de alguém: $tel" +} + + +///////////////////////////////////////////////// +// 7. Programação Funcional +///////////////////////////////////////////////// + +// Scala permite que funções e métodos retornem, ou recebam como parámetros, +// outras funções ou métodos + +val soma10: Int => Int = _ + 10 // Função que recebe um Int e retorna um Int +List(1, 2, 3) map soma10 // List(11, 12, 13) - soma10 é aplicado a cada elemento + +// Funções anónimas também podem ser usadas +List(1, 2, 3) map (x => x + 10) + +// Sendo que o símbolo _ também pode ser usado se a função anónima só receber +// um argumento. Este fica com o valor da variável +List(1, 2, 3) map (_ + 10) + +// Se tanto o bloco como a função apenas receberem um argumento, o próprio +// _ pode ser omitido +List("Dom", "Bob", "Natalia") foreach println + + +// Combinadores + +s.map(quadrado) + +val sQuadrado = s.map(quadrado) + +sQuadrado.filter(_ < 10) + +sQuadrado.reduce (_+_) + +// O método filter recebe um predicado (uma função de A => Boolean) e escolhe +// todos os elementos que satisfazem o predicado +List(1, 2, 3) filter (_ > 2) // List(3) +case class Pessoa(nome: String, idade: Int) +List( + Pessoa(nome = "Dom", idade = 23), + Pessoa(nome = "Bob", idade = 30) +).filter(_.idade > 25) // List(Pessoa("Bob", 30)) + + +// O método foreach recebe uma função de A => Unit, executando essa função em +// cada elemento da colecção +val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println + +// Compreensões For + +for { n <- s } yield quadrado(n) + +val nQuadrado2 = for { n <- s } yield quadrado(n) + +for { n <- nQuadrado2 if n < 10 } yield n + +for { n <- s; nQuadrado = n * n if nQuadrado < 10} yield nQuadrado + +/* Nota: isto não são ciclos for: A semântica de um ciclo é 'repetir', enquanto + que uma compreensão define a relação entre dois conjuntos de dados. */ + + +///////////////////////////////////////////////// +// 8. Implicitos +///////////////////////////////////////////////// + +/* AVISO IMPORTANTE: Implicitos são um conjunto de funcionalidades muito + * poderosas em Scala, que podem ser fácilmente abusadas. Iniciantes devem + * resistir a tentação de usá-los até que compreendam não só como funcionam, + * mas também as melhores práticas. Apenas incluimos esta secção no tutorial + * devido a estes serem tão comuns em bibliotecas de Scala que muitas delas + * se tornam impossíveis de usar sem conhecer implicitos. Este capítulo serve + * para compreender como trabalhar com implicitos, não como declará-los. +*/ + +// Qualquer valor (vals, funções, objectos, etc) pode ser declarado como +// implicito usando a palavra "implicit". Vamos usar a classe Cão da secção 5 +// nestes exemplos + +implicit val oMeuIntImplicito = 100 +implicit def aMinhaFunçãoImplicita(raça: String) = new Cão("Golden " + raça) + +// Por si só, a palavra implicit não altera o comportamento de um valor, sendo +// que estes podem ser usados da forma habitual. +oMeuIntImplicito + 2 // => 102 +aMinhaFunçãoImplicita("Pitbull").raça // => "Golden Pitbull" + +// A diferença é que estes valores podem ser utilizados quando outro pedaço de +// código "necessite" de uma valor implicito. Um exemplo são argumentos +// implicitos de funções: +def enviaCumprimentos(aQuem: String)(implicit quantos: Int) = + s"Olá $aQuem, $quantos cumprimentos para ti e para os teus!" + +// Se dermos um valor a "quantos", a função comporta-se normalmente +enviaCumprimentos("João")(1000) // => "Olá João, 1000 cumprimentos para ti e para os teus!" + +// Mas, se omitirmos o parâmetro implicito, um valor implicito do mesmo tipo é +// usado, neste caso, "oMeuInteiroImplicito" +enviaCumprimentos("Joana") // => "Olá Joana, 100 cumprimentos para ti e para os teus!" + +// Parâmentros implicitos de funções permitem-nos simular classes de tipos de +// outras linguagens funcionais. Isto é tão comum que tem a sua própria notação. +// As seguintes linhas representam a mesma coisa +// def foo[T](implicit c: C[T]) = ... +// def foo[T : C] = ... + + +// Outra situação em que o compilador prouca um implicito é se encontrar uma +// expressão +// obj.método(...) +// mas "obj" não possuir um método chamado "método". Neste cso, se houver uma +// conversão implicita A => B, onde A é o tipo de obj, e B possui um método +// chamado "método", a conversão é aplicada. Ou seja, tendo +// aMinhaFunçãoImplicita definida, podemos dizer +"Retriever".raça // => "Golden Retriever" +"Sheperd".ladra // => "Woof, woof!" + +// Neste caso, a String é primeiro convertida para Cão usando a nossa funão, +// sendo depois chamado o método apropriado. Esta é uma funcionalidade +// incrivelmente poderosa, sendo que deve ser usada com cautela. Na verdade, +// ao definir a função implicita, o compilador deve lançar um aviso a insisitir +// que só deve definir a função se souber o que está a fazer. + + +///////////////////////////////////////////////// +// 9. Misc +///////////////////////////////////////////////// + +// Importar coisas +import scala.collection.immutable.List + +// Importar todos os "sub pacotes" +import scala.collection.immutable._ + +// Importar multiplas classes numa linha +import scala.collection.immutable.{List, Map} + +// Renomear uma classe importada usando '=>' +import scala.collection.immutable.{List => ImmutableList} + +// Importar todas as classes excepto algumas. Set e Map são excluidos: +import scala.collection.immutable.{Map => _, Set => _, _} + +// O ponto de entrada de um programa em Scala é definido por un ficheiro .scala +// com um método main: +object Aplicação { + def main(args: Array[String]): Unit = { + // código aqui. + } +} + +// Ficheiros podem conter várias classes o objectos. Compilar com scalac + + + + +// Input e output + +// Ler um ficheiro linha a linha +import scala.io.Source +for(linha <- Source.fromFile("ficheiro.txt").getLines()) + println(linha) + +// Escrever um ficheiro usando o PrintWriter de Java +val writer = new PrintWriter("ficheiro.txt") +writer.write("Escrevendo linha por linha" + util.Properties.lineSeparator) +writer.write("Outra linha aqui" + util.Properties.lineSeparator) +writer.close() + +``` + +## Mais recursos + +* [Scala for the impatient](http://horstmann.com/scala/) +* [Twitter Scala school](http://twitter.github.io/scala_school/) +* [The scala documentation](http://docs.scala-lang.org/) +* [Try Scala in your browser](http://scalatutorials.com/tour/) +* Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) diff --git a/pt-pt/swift-pt.html.markdown b/pt-pt/swift-pt.html.markdown new file mode 100644 index 00000000..6b263942 --- /dev/null +++ b/pt-pt/swift-pt.html.markdown @@ -0,0 +1,609 @@ +--- +language: swift +filename: learnswift-pt.swift +contributors: + - ["Grant Timmerman", "http://github.com/grant"] + - ["Christopher Bess", "http://github.com/cbess"] + - ["Joey Huang", "http://github.com/kamidox"] + - ["Anthony Nguyen", "http://github.com/anthonyn60"] + - ["Clayton Walker", "https://github.com/cwalk"] +translators: + - ["João Costa", "https://github.com/joaofcosta"] +lang: pt-pt +--- + +Swift é uma linguagem de programação criada pela Apple para o desenvolvimento em iOS e OS X. +Desenhada de forma a coexistir com Objective-C e ser mais resiliente contra código errôneo, a linguagem Swift foi introduzida em 2014 na conferência para desenvolvedores WWDC da Apple. +Swift usa o compilador LLVM incluido no XCode 6+. + +O livro oficial [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) da Apple está agora disponivel via iBooks. + +Consulta também o [guia de iniciação](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/) da Apple, que contêm um tutorial completo em Swift. + +```swift +// importar um módulo +import UIKit + +// +// MARK: Básico +// + +// O Xcode suporta landmarks para anotação de código e lista-as na jump bar +// MARK: Marco de secção (MARK) +// TODO: Algo a fazer em breve +// FIXME: Reparar este código + +// Em Swift 2, println e print foram unidos num só método print. O print automaticamente acrescenta uma nova linha. +print("Hello, world") // println mudou para print +print("Hello, world", appendNewLine: false) // imprimir sem acrescentar uma nova linha + +// variáveis (var) podem ser modificadas depois de inicializadas +// constantes (let) NÂO podem ser modificadas depois de inicializadas + +var myVariable = 42 +let øπΩ = "value" // nomes de variáveis em unicode +let π = 3.1415926 +let convenience = "keyword" // nome de variável contextual +let weak = "keyword"; let override = "another keyword" // expressões podem ser separadas com ';' +let `class` = "keyword" // plicals permitem que keywords sejam usadas como nomes de vartiáveis +let explicitDouble: Double = 70 +let intValue = 0007 // 7 +let largeIntValue = 77_000 // 77000 +let label = "some text " + String(myVariable) // Casting +let piText = "Pi = \(π), Pi 2 = \(π * 2)" // interpolação de Strings + +// Valores especificos à build +// usam a configuração de build -D +#if false + print("Not printed") + let buildValue = 3 +#else + let buildValue = 7 +#endif +print("Build value: \(buildValue)") // Build value: 7 + +/* + Optionals são um dos recursos de Swift, Optionals tanto podem conter + um valor ou conter nil (sem valor) que indica que não existe um valor. + Adicionar um ponto de exclamção (?) após definir o tipo declara + esse valor como um Optional. + + Como Swift requere que todas as propriedades tenham um valor, até nil + tem que ser explicitamente guardado como um valor Optional. + + Optional<T> é uma enumeração. +*/ +var someOptionalString: String? = "optional" // Pode assumir o valor nil +// Igual ao de cima, mas ? é um operando pósfixo (açúcar sintático) +var someOptionalString2: Optional<String> = "optional" + +if someOptionalString != nil { + // Não sou nil + if someOptionalString!.hasPrefix("opt") { + print("has the prefix") + } + + let empty = someOptionalString?.isEmpty +} +someOptionalString = nil + +/* + Tentar usar ! para aceder a Optional com valor não existente, ou seja, nil, + causa em erro de execução. + É necessário ter sempre a certeza que um Optional não tem valor nil + antes de usar ! para fazer 'force-unwrap' ao seu valor. +*/ + +// Optional implicitamente desembrulhado +var unwrappedString: String! = "Value is expected." +// O mesmo de cima, mas ! é um operando pósfixo (mais açúcar sintático) +var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Value is expected." + +if let someOptionalStringConstant = someOptionalString { + // Tem um valor diferente de nil + if !someOptionalStringConstant.hasPrefix("ok") { + // Não tem o prefixo + } +} + +// Swift tem suporte para guardar valores de qualquer tipo. +// AnyObject == id +// Ao contrátio do `id` de Objective-C, AnyObject funciona com qualquer valor (Class, Int, struct, etc.) +var anyObjectVar: AnyObject = 7 +anyObjectVar = "Changed value to a string, not good practice, but possible." + +/* + Comentar aqui + + /* + Também é possível fazer comentários aninhados + */ +*/ + +// +// MARK: Coleções (Collections) +// + +/* + Os tipos Array e Dictionary são structs e, portanto, `let` e `var` + também indicam se eles são mutáveis (var) or imutáveis (let) + na altura em que se declaram estes tipos. +*/ + +// Array +var shoppingList = ["catfish", "water", "lemons"] +shoppingList[1] = "bottle of water" +let emptyArray = [String]() // let == imutável +let emptyArray2 = Array<String>() // mesmo de cima +var emptyMutableArray = [String]() // var == mutável + + +// Dictionary +var occupations = [ + "Malcolm": "Captain", + "kaylee": "Mechanic" +] +occupations["Jayne"] = "Public Relations" +let emptyDictionary = [String: Float]() // let == imutável +let emptyDictionary2 = Dictionary<String, Float>() // mesmo de cima +var emptyMutableDictionary = [String: Float]() // var == mutável + + +// +// MARK: Controlo de Fluxo (Control Flow) +// + +// for loop (array) +let myArray = [1, 1, 2, 3, 5] +for value in myArray { + if value == 1 { + print("One!") + } else { + print("Not one!") + } +} + +// for loop (dictionary) +var dict = ["one": 1, "two": 2] +for (key, value) in dict { + print("\(key): \(value)") +} + +// ciclo for (limite) +for i in -1...shoppingList.count { + print(i) +} +shoppingList[1...2] = ["steak", "peacons"] +// usar ..< para excluir o último número + +// ciclo while +var i = 1 +while i < 1000 { + i *= 2 +} + +// ciclo do-whie +do { + print("hello") +} while 1 == 2 + +// Switch +// Muito poderoso, imagine `if`s com açúcar sintático +// Funciona para String, instâncias de objectos e primitivas (Int, Double, etc.) +let vegetable = "red pepper" +switch vegetable { +case "celery": + let vegetableComment = "Add some raisins and make ants on a log." +case "cucumber", "watercress": + let vegetableComment = "That would make a good tea sandwich." +case let localScopeValue where localScopeValue.hasSuffix("pepper"): + let vegetableComment = "Is it a spicy \(localScopeValue)?" +default: // obrigatório (de forma a cobrir todos os possíveis inputs) + let vegetableComment = "Everything tastes good in soup." +} + + +// +// MARK: Funções (Functions) +// + +// Funções são tipos de primeira classe, o que significa que podem ser +// aninhadas dentro de outras funções e passadas como argumento + +// Função em Swift com documentação no header + +/** + Função de cumprimento. + + - Um ponto em documentação + - Outro ponto na documentação + + :param: nome Um nome + :param: dia Um dia + :returns: Uma string com um cumprimento contendo o nome e o dia. +*/ +func greet(nome: String, dia: String) -> String { + return "Hello \(nome), today is \(dia)." +} +greet("Bob", "Tuesday") + +// Semelhante ao método de cima excepto ao comportamento dos argumentos +func greet2(#nomeObrigatório: String, nomeArgumentoExterno nomeArgumentoLocal: String) -> String { + return "Hello \(nomeObrigatório), the day is \(nomeArgumentoLocal)" +} +greet2(nomeObrigatório:"John", nomeArgumentoExterno: "Sunday") + +// Função que devolve vários itens num tuplo +func getGasPrices() -> (Double, Double, Double) { + return (3.59, 3.69, 3.79) +} +let pricesTuple = getGasPrices() +let price = pricesTuple.2 // 3.79 +// Ignorar tuplos ou outros valores usando _ (underscore) +let (_, price1, _) = pricesTuple // price1 == 3.69 +print(price1 == pricesTuple.1) // true +print("Gas price: \(price)") + +// Argumentos variáveis +func setup(numbers: Int...) { + // é um array + let number = numbers[0] + let argCount = numbers.count +} + +// Passar e devolver funções +func makeIncrementer() -> (Int -> Int) { + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne +} +var increment = makeIncrementer() +increment(7) + +// Passar por referência (inout) +func swapTwoInts(inout a: Int, inout b: Int) { + let tempA = a + a = b + b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(&someIntA, &someIntB) +print(someIntB) // 7 + + +// +// MARK: Closures +// +var numbers = [1, 2, 6] + +// Funções são casos especiais de closures ({}) + +// Exemplo de um Closure. +// `->` separa o argumento e o tipo de retorno. +// `in` separa o cabeçalho do closure do corpo do closure. +numbers.map({ + (number: Int) -> Int in + let result = 3 * number + return result +}) + +// Quando o tipo é conhecido, como em cima, podemos fazer o seguinte +numbers = numbers.map({ number in 3 * number }) +// Ou até mesmo isto +//numbers = numbers.map({ $0 * 3 }) + +print(numbers) // [3, 6, 18] + +// Closure à direita (Trailing closure) +numbers = sorted(numbers) { $0 > $1 } + +print(numbers) // [18, 6, 3] + +// Super curto, pois o operador < consegue inferir o tipo + +numbers = sorted(numbers, < ) + +print(numbers) // [3, 6, 18] + +// +// MARK: Estruturas (Structures) +// + +// Estruturas (struct) e classes (class) têm capacidades muito semelhantes +struct NamesTable { + let names = [String]() + + // Custom subscript + subscript(index: Int) -> String { + return names[index] + } +} + +// Estruturas têm um inicializador implicito que é automaticamente gerado +let namesTable = NamesTable(names: ["Me", "Them"]) +let name = namesTable[1] +print("Name is \(name)") // Name is Them + +// +// MARK: Classes +// + +// Classes, estruturas e os seus membros têm três níveis de controlo de acesso +// Nomeadamente: interno (predefinição)(internal) , público (public), privado (private) + +public class Shape { + public func getArea() -> Int { + return 0; + } +} + +// Todos os métodos e propriedades de uma classe são públicos. +// Se só for necessário guarda dados num +// objecto estruturado, então é melhor usar uma `struct` + +internal class Rect: Shape { + var sideLength: Int = 1 + + // Propriedade getter e setter personalizado + private var perimeter: Int { + get { + return 4 * sideLength + } + set { + // `newValue` é uma variável implicita disponível aos setters + sideLength = newValue / 4 + } + } + + // Carregar preguiçosamente uma propriedade + // subShape permanece a nil (unintialized) até o getter ser invocado + lazy var subShape = Rect(sideLength: 4) + + // Se não for necessário um getter e setter personalizado, + // mas se quiser correr o código antes e depois de modificar ou aceder + // uma propriedade, é possível usar `willSet` e `didSet` + var identifier: String = "defaultID" { + // o argumento de `willSet` é o nome da variável para o novo valor + willSet(someIdentifier) { + print(someIdentifier) + } + } + + init(sideLength: Int) { + self.sideLength = sideLength + // invocar super.init no final do método de inicialização + super.init() + } + + func shrink() { + if sideLength > 0 { + sideLength -= 1 + } + } + + override func getArea() -> Int { + return sideLength * sideLength + } +} + +// A class `Square` estende (extends) a classe `Rect` (hierarquia) +class Square: Rect { + convenience init() { + self.init(sideLength: 5) + } +} + +var mySquare = Square() +print(mySquare.getArea()) // 25 +mySquare.shrink() +print(mySquare.sideLength) // 4 + +// Cast de uma instância de `Square` para `Shape` +let aShape = mySquare as Shape + +// Compara instâncias, não é igual a == , visto que == compara objects (igual a) +if mySquare === mySquare { + print("Yep, it's mySquare") +} + +// Inicializador (init) com Optional +class Circle: Shape { + var radius: Int + override func getArea() -> Int { + return 3 * radius * radius + } + + // Colocar um ponto de interrpgação depois de `init` cria um inicializador + // Optional, o qual pode retornar nil + init?(radius: Int) { + self.radius = radius + super.init() + + if radius <= 0 { + return nil + } + } +} + +var myCircle = Circle(radius: 1) +print(myCircle?.getArea()) // Optional(3) +print(myCircle!.getArea()) // 3 +var myEmptyCircle = Circle(radius: -1) +print(myEmptyCircle?.getArea()) // "nil" +if let circle = myEmptyCircle { + // Não vai executar pois a variável myEmptyCircle é igual a nil + print("circle is not nil") +} + + +// +// MARK: Enumerações (Enums) +// + +// Enums pode opcionalmente ser um tipo especifico ou não. +// Enums podem conter métodos tal como as classes. + +enum suit { + case spades, hearts, diamonds, clubs + func getIcon() -> String { + switch self { + case .spades: return "♤" + case .hearts: return "♡" + case .diamonds: return "♢" + case .clubs: return "♧" + } + } +} + +// Os valores de Enum permitem syntax reduzida, não é preciso escrever o tipo do enum +// quando a variável é explicitamente definida. +var suitValue: Suit = .hearts + +// Enums que não sejam inteiros obrigam a atribuições valor bruto (raw value) diretas +enum BookName: String { + case john = "John" + case luke = "Luke" +} +print("Name: \(BookName.john.rawValue)") + +// Enum com valores associados +enum Furniture { + // Associar com um inteiro (Int) + case desk(height: Int) + // Associar com uma String e um Int + case chair(String, Int) + + func description() -> String { + switch self { + case .desk(let height): + return "Desk with \(height) cm" + case .chair(let brand, let height): + return "Chair of \(brand) with \(height) cm" + } + } +} + +var desk: Furniture = .desk(height: 80) +print(desk.description()) // "Desk with 80 cm" +var chair = Furniture.chair("Foo", 40) +print(chair.description()) // "Chair of Foo with 40 cm" + + +// +// MARK: Protocolos (Protocols) +// + +// Protocolos (`protcol`s) obrigam a que os tipos tenham +// propriedades de instância, métodos de instância, métodos de tipo, +// operadores e subscripts específicos. + +protocol ShapeGenerator { + var enabled: Bool { get set } + func buildShape() -> Shape +} + +// Protocolos definidos com @objc permitem funções com optional +// que permitem verificar se existem conformidade +@objc protocol TransformShape { + optional func reshaped() + optional func canReshape() -> Bool +} + +class MyShape: Rect { + var delegate: TransformShape? + + func grow() { + sideLength += 2 + + // Coloca um ponto de interrogação após uma propriedade opcional, método + // ou subscript para graciosamente ignorar um valor nil e retornar nil + // em vez de provoar um erro em tempo de execução ("optional chaining"). + if let allow = self.delegate?.canReshape?() { + // testar o delegate e depois o método + self.delegate?.reshaped?() + } + } +} + + +// +// MARK: Outro +// + +// extensões (`extension`s): Adiciona funcionalidade extra a um tipo já existente. + +// Square agora "conforma" com o protocolo `Printable` +extension Square: Printable { + var description: String { + return "Area: \(self.getArea()) - ID: \(self.identifier)" + } +} + +print("Square: \(mySquare)") + +// Também é possível extender tipos já embutidos +extension Int { + var customProperty: String { + return "This is \(self)" + } + + func multiplyBy(num: Int) -> Int { + return num * self + } +} + +print(7.customProperty) // "This is 7" +print(14.multiplyBy(3)) // 42 + +// Generics: Semelhante a Java e C#. Usa a palavra-chave `where` para +// especificar requisitos do `generics`. + +func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { + for (index, value) in enumerate(array) { + if value == valueToFind { + return index + } + } + return nil +} +let foundAtIndex = findIndex([1, 2, 3, 4], 3) +print(foundAtIndex == 2) // true + +// Operadores: +// Operadores personalizados podem começar com caracteres: +// / = - + * % < > ! & | ^ . ~ +// ou +// Caracteres Unicode matemáticos, símbolos, setas, dingbat e +// caracteres de desenho linha/caixa. +operador prefixo !!! {} + +// Um operador prefixo que triplica o comprimento do lado quando usado +prefix func !!! (inout shape: Square) -> Square { + shape.sideLength *= 3 + return shape +} + +// valor atual +print(mySquare.sideLength) // 4 + +// muda o comprimento deste lado usando o operador personalizado !!!, aumenta +// o comprimento 3x +!!!mySquare +print(mySquare.sideLength) // 12 + +// Operadores também podem ser generics +infix operator <-> {} +func <-><T: Equatable> (inout a: T, inout b: T) { + let c = a + a = b + b = c +} + +var foo: Float = 10 +var bar: Float = 20 + +foo <-> bar +print("foo is \(foo), bar is \(bar)") // "foo is 20.0, bar is 10.0" +``` |