diff options
-rw-r--r-- | coffeescript.html.markdown | 2 | ||||
-rw-r--r-- | es-es/visualbasic-es.html.markdown | 286 | ||||
-rw-r--r-- | forth.html.markdown | 4 | ||||
-rw-r--r-- | fr-fr/haml-fr.html.markdown | 156 | ||||
-rw-r--r-- | fr-fr/scala.html.markdown | 9 | ||||
-rw-r--r-- | git.html.markdown | 2 | ||||
-rw-r--r-- | hu-hu/ruby.html.markdown | 555 | ||||
-rw-r--r-- | json.html.markdown | 2 | ||||
-rw-r--r-- | julia.html.markdown | 26 | ||||
-rw-r--r-- | matlab.html.markdown | 54 | ||||
-rw-r--r-- | perl.html.markdown | 2 | ||||
-rw-r--r-- | perl6.html.markdown | 91 | ||||
-rw-r--r-- | pt-br/clojure-macros-pt.html.markdown | 154 | ||||
-rw-r--r-- | pt-pt/scala-pt.html.markdown | 651 | ||||
-rw-r--r-- | scala.html.markdown | 12 |
15 files changed, 1944 insertions, 62 deletions
diff --git a/coffeescript.html.markdown b/coffeescript.html.markdown index f19181ce..89a29677 100644 --- a/coffeescript.html.markdown +++ b/coffeescript.html.markdown @@ -7,7 +7,7 @@ filename: coffeescript.coffee --- CoffeeScript is a little language that compiles one-to-one into the equivalent JavaScript, and there is no interpretation at runtime. -As one of the succeeders of JavaScript, CoffeeScript tries its best to output readable, pretty-printed and smooth-running JavaScript codes working well in every JavaScript runtime. +As one of the successors to JavaScript, CoffeeScript tries its best to output readable, pretty-printed and smooth-running JavaScript code, which works well in every JavaScript runtime. See also [the CoffeeScript website](http://coffeescript.org/), which has a complete tutorial on CoffeeScript. diff --git a/es-es/visualbasic-es.html.markdown b/es-es/visualbasic-es.html.markdown new file mode 100644 index 00000000..c7f581c0 --- /dev/null +++ b/es-es/visualbasic-es.html.markdown @@ -0,0 +1,286 @@ +--- +language: Visual Basic +contributors: + - ["Brian Martin", "http://brianmartin.biz"] +translators: + - ["Adolfo Jayme Barrientos", "https://github.com/fitojb"] +author: Brian Martin +author_url: https://github.com/fitojb +filename: learnvisualbasic-es.vb +lang: es-es +--- + +```vb +Module Module1 + + Sub Main() + ' Un vistazo rápido a las aplicaciones de consola de Visual Basic antes + ' de que profundicemos en el tema. + ' El apóstrofo inicia una línea de comentario. + ' Para explorar este tutorial dentro del Compilador de Visual Basic, + ' he creado un sistema de navegación. + ' Dicho sistema se explicará a medida que avancemos en este + ' tutorial; gradualmente entenderás lo que significa todo. + Console.Title = ("Aprende X en Y minutos") + Console.WriteLine("NAVEGACIÓN") 'Mostrar + Console.WriteLine("") + Console.ForegroundColor = ConsoleColor.Green + Console.WriteLine("1. Salida «Hola, mundo»") + Console.WriteLine("2. Entrada «Hola, mundo»") + Console.WriteLine("3. Calcular números enteros") + Console.WriteLine("4. Calcular números decimales") + Console.WriteLine("5. Una calculadora funcional") + Console.WriteLine("6. Uso de bucles «Do While»") + Console.WriteLine("7. Uso de bucles «For While»") + Console.WriteLine("8. Declaraciones condicionales") + Console.WriteLine("9. Selecciona una bebida") + Console.WriteLine("50. Acerca de") + Console.WriteLine("Elige un número de la lista anterior") + Dim selection As String = Console.ReadLine + Select Case selection + Case "1" 'Salida «hola, mundo» + Console.Clear() 'Limpia la consola y abre la subrutina privada + SalidaHolaMundo() 'Abre la subrutina privada nombrada + Case "2" 'Entrada «hola, mundo» + Console.Clear() + EntradaHolaMundo() + Case "3" 'Calcular números enteros + Console.Clear() + CalcularNumerosEnteros() + Case "4" 'Calcular números decimales + Console.Clear() + CalcularNumerosDecimales() + Case "5" 'Una calculadora funcional + Console.Clear() + CalculadoraFuncional() + Case "6" 'Uso de bucles «Do While» + Console.Clear() + UsoBuclesDoWhile() + Case "7" 'Uso de bucles «For While» + Console.Clear() + UsoBuclesFor() + Case "8" 'Declaraciones condicionales + Console.Clear() + DeclaracionCondicional() + Case "9" 'Declaración «If/Else» + Console.Clear() + DeclaracionIfElse() 'Selecciona una bebida + Case "50" 'Cuadro de mensaje «Acerca de» + Console.Clear() + Console.Title = ("Aprende X en Y minutos :: Acerca de") + MsgBox("Tutorial escrito por Brian Martin (@BrianMartinn") + Console.Clear() + Main() + Console.ReadLine() + + End Select + End Sub + + 'Uno - He usado números para guiarme por el sistema de navegación anterior + 'cuando regrese posteriormente a implementarlo. + + 'Usamos subrutinas privadas para separar distintas secciones del programa. + Private Sub SalidaHolaMundo() + 'Título de la aplicación de consola + Console.Title = "Salida «Hola, mundo» | Aprende X en Y minutos" + 'Usa Console.Write("") o Console.WriteLine("") para mostrar salidas. + 'Seguido por Console.Read(), o bien, Console.Readline() + 'Console.ReadLine() muestra la salida en la consola. + Console.WriteLine("Hola, mundo") + Console.ReadLine() + End Sub + + 'Dos + Private Sub EntradaHolaMundo() + Console.Title = "«Hola, mundo, soy...» | Aprende X en Y minutos" + ' Variables + ' Los datos que introduzca un usuario deben almacenarse. + ' Las variables también empiezan por Dim y terminan por As VariableType. + + ' En este tutorial queremos conocer tu nombre y hacer que el programa + ' responda a este. + Dim nombredeusuario As String + 'Usamos «string» porque es una variable basada en texto. + Console.WriteLine("Hola, ¿cómo te llamas? ") 'Preguntar nombre de usuario. + nombredeusuario = Console.ReadLine() 'Almacenar nombre del usuario. + Console.WriteLine("Hola, " + nombredeusuario) 'La salida es Hola, nombre + Console.ReadLine() 'Muestra lo anterior. + 'El código anterior te hará una pregunta y mostrará la respuesta. + 'Entre otras variables está Integer, la cual usaremos para números enteros. + End Sub + + 'Tres + Private Sub CalcularNumerosEnteros() + Console.Title = "Calcular números enteros | Aprende X en Y minutos" + Console.Write("Primer número: ") 'Escribe un núm. entero, 1, 2, 104, etc + Dim a As Integer = Console.ReadLine() + Console.Write("Segundo número: ") 'Escribe otro número entero. + Dim b As Integer = Console.ReadLine() + Dim c As Integer = a + b + Console.WriteLine(c) + Console.ReadLine() + 'Lo anterior es una calculadora sencilla + End Sub + + 'Cuatro + Private Sub CalcularNumerosDecimales() + Console.Title = "Calcular con tipo doble | Aprende X en Y minutos" + 'Por supuesto, nos gustaría sumar decimales. + 'Por ello podríamos cambiar del tipo Integer al Double. + + 'Escribe un número fraccionario, 1.2, 2.4, 50.1, 104.9 etc + Console.Write("Primer número: ") + Dim a As Double = Console.ReadLine + Console.Write("Segundo número: ") 'Escribe el segundo número. + Dim b As Double = Console.ReadLine + Dim c As Double = a + b + Console.WriteLine(c) + Console.ReadLine() + 'Este programa puede sumar 1.1 y 2.2 + End Sub + + 'Cinco + Private Sub CalculadoraFuncional() + Console.Title = "La calculadora funcional | Aprende X en Y minutos" + 'Pero si quieres que la calculadora reste, divida, multiplique y + 'sume. + 'Copia y pega lo anterior. + Console.Write("Primer número: ") + Dim a As Double = Console.ReadLine + Console.Write("Segundo número: ") + Dim b As Integer = Console.ReadLine + Dim c As Integer = a + b + Dim d As Integer = a * b + Dim e As Integer = a - b + Dim f As Integer = a / b + + 'Mediante las líneas siguientes podremos restar, + 'multiplicar y dividir los valores a y b + Console.Write(a.ToString() + " + " + b.ToString()) + 'Queremos dar un margen izquierdo de 3 espacios a los resultados. + Console.WriteLine(" = " + c.ToString.PadLeft(3)) + Console.Write(a.ToString() + " * " + b.ToString()) + Console.WriteLine(" = " + d.ToString.PadLeft(3)) + Console.Write(a.ToString() + " - " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.Write(a.ToString() + " / " + b.ToString()) + Console.WriteLine(" = " + f.ToString.PadLeft(3)) + Console.ReadLine() + + End Sub + + 'Seis + Private Sub UsoBuclesDoWhile() + 'Igual que la subrutina privada anterior + 'Esta vez preguntaremos al usuario si quiere continuar (¿sí o no?) + 'Usamos el bucle Do While porque no sabemos si el usuario quiere + 'usar el programa más de una vez. + Console.Title = "Uso de bucles «Do While» | Aprende X en Y minutos" + Dim respuesta As String 'Usamos la variable «String» porque la resp. es texto + Do 'Comenzamos el programa con + Console.Write("Primer número: ") + Dim a As Double = Console.ReadLine + Console.Write("Segundo número: ") + Dim b As Integer = Console.ReadLine + Dim c As Integer = a + b + Dim d As Integer = a * b + Dim e As Integer = a - b + Dim f As Integer = a / b + + Console.Write(a.ToString() + " + " + b.ToString()) + Console.WriteLine(" = " + c.ToString.PadLeft(3)) + Console.Write(a.ToString() + " * " + b.ToString()) + Console.WriteLine(" = " + d.ToString.PadLeft(3)) + Console.Write(a.ToString() + " - " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.Write(a.ToString() + " / " + b.ToString()) + Console.WriteLine(" = " + f.ToString.PadLeft(3)) + Console.ReadLine() + 'Preguntar si el usuario quiere continuar. Desafortunadamente, + 'distingue entre mayúsculas y minúsculas. + Console.Write("¿Quieres continuar? (s / n)") + 'El programa toma la variable, la muestra y comienza de nuevo. + respuesta = Console.ReadLine + 'La orden que hará funcionar esta variable es en este caso «s» + Loop While respuesta = "s" + + End Sub + + 'Siete + Private Sub UsoBuclesFor() + 'A veces el programa debe ejecutarse solo una vez. + 'En este programa contaremos a partir de 10. + + Console.Title = "Uso de bucles «For» | Aprende X en Y minutos" + 'Declarar Variable y desde qué número debe contar en Step -1, + 'Step -2, Step -3, etc. + For i As Integer = 10 To 0 Step -1 + Console.WriteLine(i.ToString) 'Muestra el valor del contador + Next i 'Calcular el valor nuevo + Console.WriteLine("Iniciar") '¡¡Comencemos el programa, nene!! + Console.ReadLine() '¡¡ZAS!! - Quizá me he emocionado bastante :) + End Sub + + 'Ocho + Private Sub DeclaracionCondicional() + Console.Title = "Declaraciones condicionales | Aprende X en Y minutos" + Dim nombredeUsuario As String = Console.ReadLine + Console.WriteLine("Hola, ¿cómo te llamas? ") 'Preguntar nombre de usuario. + nombredeUsuario = Console.ReadLine() 'Almacena el nombre de usuario. + If nombredeUsuario = "Adam" Then + Console.WriteLine("Hola, Adam") + Console.WriteLine("Gracias por crear este útil sitio web") + Console.ReadLine() + Else + Console.WriteLine("Hola, " + nombredeUsuario) + Console.WriteLine("¿Has visitado www.learnxinyminutes.com?") + Console.ReadLine() 'Termina y muestra la declaración anterior. + End If + End Sub + + 'Nueve + Private Sub DeclaracionIfElse() + Console.Title = "Declaración «If / Else» | Aprende X en Y minutos" + 'A veces es importante considerar más de dos alternativas. + 'A veces, algunas de estas son mejores. + 'Cuando esto sucede, necesitaríamos más de una declaración «if». + 'Una declaración «if» es adecuada para máquinas expendedoras. + 'En las que el usuario escribe un código (A1, A2, A3) para elegir. + 'Pueden combinarse todas las elecciones en una sola declaración «if». + + Dim seleccion As String = Console.ReadLine 'Valor de la selección + Console.WriteLine("A1. para 7Up") + Console.WriteLine("A2. para Fanta") + Console.WriteLine("A3. para Dr. Pepper") + Console.WriteLine("A4. para Coca-Cola") + Console.ReadLine() + If selection = "A1" Then + Console.WriteLine("7up") + Console.ReadLine() + ElseIf selection = "A2" Then + Console.WriteLine("fanta") + Console.ReadLine() + ElseIf selection = "A3" Then + Console.WriteLine("dr. pepper") + Console.ReadLine() + ElseIf selection = "A4" Then + Console.WriteLine("coca-cola") + Console.ReadLine() + Else + Console.WriteLine("Selecciona un producto") + Console.ReadLine() + End If + + End Sub + +End Module + +``` + +## Referencias + +Aprendí Visual Basic en la aplicación de consola. Esta me permitió entender los principios de la programación para, posteriormente, aprender otros lenguajes con facilidad. + +He creado un <a href="http://www.vbbootcamp.co.uk/" Title="Tutorial de Visual Basic">tutorial de Visual Basic</a> más exhaustivo para quienes quieran saber más. + +Toda la sintaxis es válida. Copia el código y pégalo en el compilador de Visual Basic y ejecuta (F5) el programa. diff --git a/forth.html.markdown b/forth.html.markdown index f7c0bf34..b4a5581b 100644 --- a/forth.html.markdown +++ b/forth.html.markdown @@ -117,7 +117,7 @@ one-to-12 \ 0 1 2 3 4 5 6 7 8 9 10 11 12 ok : threes ( n n -- ) ?do i . 3 +loop ; \ ok 15 0 threes \ 0 3 6 9 12 ok -\ Indefinite loops with `begin` <stuff to do> <flag> `unil`: +\ Indefinite loops with `begin` <stuff to do> <flag> `until`: : death ( -- ) begin ." Are we there yet?" 0 until ; \ ok \ ---------------------------- Variables and Memory ---------------------------- @@ -133,7 +133,7 @@ variable age \ ok age @ . \ 21 ok age ? \ 21 ok -\ Constants are quite simiar, except we don't bother with memory addresses: +\ Constants are quite similar, except we don't bother with memory addresses: 100 constant WATER-BOILING-POINT \ ok WATER-BOILING-POINT . \ 100 ok diff --git a/fr-fr/haml-fr.html.markdown b/fr-fr/haml-fr.html.markdown new file mode 100644 index 00000000..0267a380 --- /dev/null +++ b/fr-fr/haml-fr.html.markdown @@ -0,0 +1,156 @@ +--- +language: haml +filename: learnhaml.haml +contributors: + - ["Simon Neveu", "https://github.com/sneveu"] + - ["Thibault", "https://github.com/iTech-"] +--- + +Haml est un langage de balisage utilisé majoritairement avec Ruby, qui décrit de manière simple et propre le HTML de n'importe quelle page web sans l'utilisation des traditionnelles lignes de code. Le langage est une alternative très populaire au langage de templates Rails (.erb) et permet d'intégrer du code en Ruby dans votre balisage. + +Son but est de réduire le nombre de répétitions dans le balisage en fermant des balises pour vous en se basant sur l'indentation de votre code. Finalement, le balisage est bien structuré, ne contient pas de répétition, est logique et facile à lire. + +Vous pouvez aussi utiliser Haml sur un projet indépendant de Ruby, en installant les gems de Haml et en le convertissant en html grâce aux commandes. + +$ haml fichier_entree.haml fichier_sortie.html + + +```haml +/ ------------------------------------------- +/ Indentation +/ ------------------------------------------- + +/ + A cause de l'importance de l'indentation sur la manière dont votre code sera + converti, l'indentation doit être constante à travers votre document. Un + simple changement d'indentation entrainera une erreur. En général, on utilise + deux espaces, mais ce genre de décision sur l'indentation vous appartient, du + moment que vous vous y tenez. + +/ ------------------------------------------- +/ Commentaires +/ ------------------------------------------- + +/ Ceci est un commentaire en Haml. + +/ + Pour écrire un commentaire sur plusieurs lignes, indentez votre code + commenté en le commençant par un slash + +-# Ceci est un commentaire silencieux, qui n'apparaîtra pas dans le fichier + + +/ ------------------------------------------- +/ Eléments HTML +/ ------------------------------------------- + +/ Pour écrire vos balises, utilisez un pourcentage suivi du nom de votre balise +%body + %header + %nav + +/ Remarquez qu'il n'y a aucunes balises fermées. Le code produira alors ceci + <body> + <header> + <nav></nav> + </header> + </body> + +/ La balise div est l'élément par défaut, vous pouvez donc l'écrire comme ceci +.balise + +/ Pour ajouter du contenu à votre balise, ajoutez le texte après sa déclaration +%h1 Titre contenu + +/ Pour écrire du contenu sur plusieurs lignes, imbriquez le +%p + Ce paragraphe contient beaucoup de contenu qui pourrait + probablement tenir sur deux lignes séparées. + +/ + Vous pouvez utiliser des caractères html spéciaux en utilisant &=. Cela va + convertir les caractères comme &, /, : en leur équivalent HTML. Par exemple + +%p + &= "Oui & oui" + +/ Produira 'Oui & oui' + +/ Vous pouvez écrire du contenu html sans qu'il soit converti en utilisant != +%p + != "Voici comment écrire une balise de paragraphe <p></p>" + +/ Cela produira 'Voici comment écrire une balise de paragraphe <p></p>' + +/ Une classe CSS peut être ajouté à votre balise en chainant le nom de la classe +%div.truc.machin + +/ ou en utilisant un hash de Ruby +%div{:class => 'truc machin'} + +/ Des attributs pour n'importe quelles balises peuvent être ajoutés au hash +%a{:href => '#', :class => 'machin', :title => 'Titre machin'} + +/ Pour affecter une valeur à un booléen, utilisez 'true' +%input{:selected => true} + +/ Pour écrire des data-attributes, utilisez le :data avec la valeur d'un hash +%div{:data => {:attribute => 'machin'}} + + +/ ------------------------------------------- +/ Insérer du Ruby +/ ------------------------------------------- + +/ + Pour transférer une valeur de Ruby comme contenu d'une balise, utilisez le + signe égal suivi du code Ruby + +%h1= livre.titre + +%p + = livre.auteur + = livre.editeur + + +/ Pour lancer du code Ruby sans le convertir en HTML, utilisez un trait d'union +- livres = ['livre 1', 'livre 2', 'livre 3'] + +/ Ceci vous permet de faire des choses géniales comme des blocs Ruby +- livre.shuffle.each_with_index do |livre, index| + %h1= livre + + if livre do + %p Ceci est un livre + +/ + Encore une fois il n'est pas nécessaire d'ajouter une balise fermante, même + pour Ruby. + L'indentation le fera pour vous. + + +/ ------------------------------------------- +/ Ruby en-ligne / Interpolation en Ruby +/ ------------------------------------------- + +/ Inclure une variable Ruby dans une ligne en utilisant #{} +%p Votre meilleur score est #{record} + + +/ ------------------------------------------- +/ Filtres +/ ------------------------------------------- + +/ + Utilisez les deux points pour définir un filtre Haml, vous pouvez par exemple + utiliser un filtre :javascript pour écrire du contenu en-ligne js + +:javascript + console.log('Ceci est la balise en-ligne <script>'); + +``` + +## Lectures complémentaires + +- [Qu'est-ce que HAML ?](http://haml.info/) - Une bonne introduction qui explique très bien les avantages d'utiliser HAML. +- [Documentation officielle](http://haml.info/docs/yardoc/file.REFERENCE.html) - Si vous souhaitez en apprendre plus et aller plus loin. diff --git a/fr-fr/scala.html.markdown b/fr-fr/scala.html.markdown index a43edf16..c6d06361 100644 --- a/fr-fr/scala.html.markdown +++ b/fr-fr/scala.html.markdown @@ -208,6 +208,7 @@ sSquared.reduce (_+_) // La fonction filter prend un prédicat (une fonction de type A -> Booléen) et // sélectionne tous les éléments qui satisfont ce prédicat List(1, 2, 3) filter (_ > 2) // List(3) +case class Person(name: String, age: Int) List( Person(name = "Dom", age = 23), Person(name = "Bob", age = 30) @@ -217,6 +218,7 @@ List( // Scala a une méthode foreach définie pour certaines collections // qui prend en argument une fonction renvoyant Unit (une méthode void) +val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) aListOfNumbers foreach (x => println(x)) aListOfNumbers foreach println @@ -271,11 +273,12 @@ i // Montre la valeur de i. Notez que while est une boucle au sens classique. // mais utiliser des combinateurs et des compréhensions comme ci-dessus est plus // facile pour comprendre et pour faire la parallélisation +i = 0 // La boucle do while do { println("x is still less then 10"); - x += 1 -} while (x < 10) + i += 1 +} while (i < 10) // La récursivité est un moyen idiomatique de faire une chose répétitive en Scala. @@ -370,7 +373,7 @@ val email(user, domain) = "henry@zkpr.com" "Les chaînes de caractères Scala sont entourées de doubles guillements" 'a' // Un caractère de Scala -'Les simples guillemets n'existent pas en Scala // Erreur +// 'Les simples guillemets n'existent pas en Scala' // Erreur "Les chaînes de caractères possèdent les méthodes usuelles de Java".length "Il y a aussi quelques méthodes extra de Scala.".reverse diff --git a/git.html.markdown b/git.html.markdown index b1347309..72079f6c 100644 --- a/git.html.markdown +++ b/git.html.markdown @@ -484,6 +484,8 @@ $ git rm /pather/to/the/file/HelloWorld.c * [Udemy Git Tutorial: A Comprehensive Guide](https://blog.udemy.com/git-tutorial-a-comprehensive-guide/) +* [Git Immersion - A Guided tour that walks through the fundamentals of git](http://gitimmersion.com/) + * [git-scm - Video Tutorials](http://git-scm.com/videos) * [git-scm - Documentation](http://git-scm.com/docs) diff --git a/hu-hu/ruby.html.markdown b/hu-hu/ruby.html.markdown new file mode 100644 index 00000000..169f2b8e --- /dev/null +++ b/hu-hu/ruby.html.markdown @@ -0,0 +1,555 @@ +--- +language: ruby +lang: hu-hu +filenev: learnruby.rb +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] + - ["Tristan Hume", "http://thume.ca/"] + - ["Nick LaMuro", "https://github.com/NickLaMuro"] + - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"] + - ["Ariel Krakowski", "http://www.learneroo.com"] + - ["Dzianis Dashkevich", "https://github.com/dskecse"] + - ["Levi Bostian", "https://github.com/levibostian"] + - ["Rahil Momin", "https://github.com/iamrahil"] + translators: + - ["Zsolt Prontvai", "https://github.com/prozsolt"] +--- + +```ruby +# Ez egy komment + +=begin +Ez egy többsoros komment +Senki sem használja +Neked sem kellene +=end + +# Először is: Minden objektum + +# A számok objektumok + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# Néhány alapvető számtani művelet +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 +2**5 #=> 32 + +# A számtani művelet csak szintaktikus cukor +# az objektumon történő függvény hívásra +1.+(3) #=> 4 +10.* 5 #=> 50 + +# A speciális értékek objektumok +nil # Nincs itt semmi látnivaló +true # igaz +false # hamis + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# Egyenlőség +1 == 1 #=> true +2 == 1 #=> false + +# Egyenlőtlenség +1 != 1 #=> false +2 != 1 #=> true + +# A false-on kívül, nil az egyetlen hamis érték + +!nil #=> true +!false #=> true +!0 #=> false + +# Még több összehasonlítás +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# Logikai operátorok +true && false #=> false +true || false #=> true +!true #=> false + +# A logikai operátoroknak alternatív verziójuk is van sokkal kisebb +# precedenciával. Ezeket arra szánták, hogy több állítást összeláncoljanak +# amíg egyikük igaz vagy hamis értékkel nem tér vissza. + +# `csinalj_valami_mast` csak akkor fut le, ha `csinalj_valamit` igaz értékkel +# tért vissza. +csinalj_valamit() and csinalj_valami_mast() +# `log_error` csak akkor fut le, ha `csinalj_valamit` hamis értékkel +# tért vissza. +csinalj_valamit() or log_error() + + +# A sztringek objektumok + +'Én egy sztring vagyok'.class #=> String +"Én is egy sztring vagyok".class #=> String + +helykitolto = 'interpolációt használhatok' +"Sztring #{helykitolto}, ha dupla időzőjelben van a sztringem" +#=> "Sztring interpolációt használhatok, ha dupla időzőjelben van a sztringem" + +# A szimpla idézőjelet preferáljuk, ahol csak lehet, +# mert a dupla idézőjel extra számításokat végez. + +# Kombinálhatunk sztringeket, de nem számokkal +'hello ' + 'world' #=> "hello world" +'hello ' + 3 #=> TypeError: can't convert Fixnum into String +'hello ' + 3.to_s #=> "hello 3" + +# kiírás a kimenetre +puts "Írok" + +# Változók +x = 25 #=> 25 +x #=> 25 + +# Értékadás az adott értékkel tér vissza +# Ez azt jelenti, hogy használhatunk többszörös értékadást: + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# Konvencióból, snake_case változó neveket használj +snake_case = true + +# Leíró változó neveket használj +ut_a_projekt_gyokerehez = '/jo/nev/' +ut = '/rossz/nev/' + +# A szimbólumok (objektumok) +# A szimbólumok megváltoztathatatlan, újra felhasználható konstans, +# mely belsőleg egész számként reprezentált. Sokszor sztring helyett használják, +# hogy effektíven közvetítsünk konkrét, értelmes értékeket + +:fuggoben.class #=> Symbol + +statusz = :fuggoben + +statusz == :fuggoben #=> true + +statusz == 'fuggoben' #=> false + +statusz == :jovahagyott #=> false + +# Tömbök + +# Ez egy tömb +tomb = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# A tömmbök különböző tipusú dolgokat tartalmazhat + +[1, 'hello', false] #=> [1, "hello", false] + +# Tömbök indexelhetőek +# Az elejéről +tomb[0] #=> 1 +tomb[12] #=> nil + +# Akárcsak a számtani műveletek [var] hozzáférés +# is csak szintaktikus cukor +# a [] függvény hívására az objektumon +tomb.[] 0 #=> 1 +tomb.[] 12 #=> nil + +# A végéről +tomb[-1] #=> 5 + +# Kezdőértékkel és hosszal +tomb[2, 3] #=> [3, 4, 5] + +# Tömb megfordítása +a=[1,2,3] +a.reverse! #=> [3,2,1] + +# Vagy tartománnyal +tomb[1..3] #=> [2, 3, 4] + +# Így adhatunk a tömbhöz +tomb << 6 #=> [1, 2, 3, 4, 5, 6] +# Vagy így +tomb.push(6) #=> [1, 2, 3, 4, 5, 6] + +# Ellenőrízük, hogy a tömb tartalmaz egy elemet +tomb.include?(1) #=> true + +# Hash-ek a ruby elsődleges szótárjai kulcs/érték párokkal +# Hash-eket kapcsos zárójellel jelöljük +hash = { 'szin' => 'zold', 'szam' => 5 } + +hash.keys #=> ['szin', 'szam'] + +# Hash-ekben könnyen kreshetünk a kulcs segítségével: +hash['szin'] #=> 'zold' +hash['szam'] #=> 5 + +# Nem létező kulcsra keresve nil-t kapunk: +hash['nincs itt semmi'] #=> nil + +# Ruby 1.9-től, egy külnleges szintaxist is használhatunk a szimbólumot +# használunk kulcsnak + +uj_hash = { defcon: 3, action: true } + +uj_hash.keys #=> [:defcon, :action] + +# Ellenőrizzük, hogy az adott kulcs és érték bene-e van a hash-ben +uj_hash.has_key?(:defcon) #=> true +uj_hash.has_value?(3) #=> true + +# Tip: A tömbök és hash-ek is felsorolhatóak +# Sok közös függvényük van, akár az each, map, count, és több + +# Kontroll Struktúrák + +if true + 'ha állítás' +elsif false + 'különben ha, opcionális' +else + 'különben, szintén opcionális' +end + +for szamlalo in 1..5 + puts "iteracio #{szamlalo}" +end +#=> iteracio 1 +#=> iteracio 2 +#=> iteracio 3 +#=> iteracio 4 +#=> iteracio 5 + +# HOWEVER, No-one uses for loops. +# Instead you should use the "each" method and pass it a block. +# A block is a bunch of code that you can pass to a method like "each". +# It is analogous to lambdas, anonymous functions or closures in other +# programming languages. +# +# The "each" method of a range runs the block once for each element of the range. +# The block is passed a counter as a parameter. +# Calling the "each" method with a block looks like this: + +(1..5).each do |counter| + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +# You can also surround blocks in curly brackets: +(1..5).each { |counter| puts "iteration #{counter}" } + +# The contents of data structures can also be iterated using each. +array.each do |element| + puts "#{element} is part of the array" +end +hash.each do |key, value| + puts "#{key} is #{value}" +end + +counter = 1 +while counter <= 5 do + puts "iteration #{counter}" + counter += 1 +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +jegy = '4' + +case jegy +when '5' + puts 'Kitünő' +when '4' + puts 'Jó' +when '3' + puts 'Közepes' +when '2' + puts 'Elégsége' +when '1' + puts 'Elégtelen' +else + puts 'Alternatív értékelés, hm?' +end +#=> "Jó" + +# case-ek tartományokat is használhatnak +jegy = 82 +case jegy +when 90..100 + puts 'Hurrá!' +when 80...90 + puts 'Jó munka' +else + puts 'Megbuktál!' +end +#=> "Jó munka" + +# kivétel kezelés: +begin + # kód ami kivételt dobhat + raise NoMemoryError, 'Megtelt a memória' +rescue NoMemoryError => kivetel_valtozo + puts 'NoMemoryError-t dobott', kivetel_valtozo +rescue RuntimeError => mas_kivetel_valtozo + puts 'RuntimeError dobott most' +else + puts 'Ez akkor fut ha nem dob kivételt' +ensure + puts 'Ez a kód mindenképpen lefut' +end + +# Függvények + +def ketszeres(x) + x * 2 +end + +# Függvények (és egyébb blokkok) implicit viszatértnek az utolsó értékkel +ketszeres(2) #=> 4 + +# Zárójelezés opcionális, ha az eredmény félreérthetetlen +ketszeres 3 #=> 6 + +ketszeres ketszeres 3 #=> 12 + +def osszeg(x, y) + x + y +end + +# Függvény argumentumait vesszővel választjuk el. +osszeg 3, 4 #=> 7 + +osszeg osszeg(3, 4), 5 #=> 12 + +# yield +# Minden függvénynek van egy implicit, opcionális block paramétere +# 'yield' kulcsszóval hívhatjuk + +def korulvesz + puts '{' + yield + puts '}' +end + +korulvesz { puts 'hello world' } + +# { +# hello world +# } + + +# Fuggvénynek átadhatunk blokkot +# "&" jelöli az átadott blokk referenciáját +def vendegek(&block) + block.call 'valami_argumentum' +end + +# Argumentum lisát is átadhatunk, ami tömbé lesz konvertálva +# Erre való a splat operátor ("*") +def vendegek(*array) + array.each { |vendeg| puts vendeg } +end + +# Osztályt a class kulcsszóval definiálhatunk +class Ember + + # Az osztály változó. Az osztály minden példánnyával megvan osztva + @@faj = 'H. sapiens' + + # Alap inicializáló + def initialize(nev, kor = 0) + # Hozzárendeli az argumentumot a "nev" példány változóhoz + @nev = nev + # Ha nem adtunk meg kort akkor az alapértemezet értéket fogja használni + @kor = kor + end + + # Alap setter függvény + def nev=(nev) + @nev = nev + end + + # Alap getter függvény + def nev + @nev + end + + # A fönti funkcionalítást az attr_accessor függvénnyel is elérhetjük + attr_accessor :nev + + # Getter/setter függvények egyenként is kreálhatóak + attr_reader :nev + attr_writer :nev + + # Az osztály függvények "self"-et hasznalnak, hogy megkülönböztessék magukat a + # példány függvényektől + # Az osztályn hívhatóak, nem a példányon + def self.mond(uzenet) + puts uzenet + end + + def faj + @@faj + end +end + + +# Példányosítsuk az osztályt +jim = Ember.new('Jim Halpert') + +dwight = Ember.new('Dwight K. Schrute') + +# Hívjunk meg pár függvényt +jim.faj #=> "H. sapiens" +jim.nev #=> "Jim Halpert" +jim.nev = "Jim Halpert II" #=> "Jim Halpert II" +jim.nev #=> "Jim Halpert II" +dwight.faj #=> "H. sapiens" +dwight.nev #=> "Dwight K. Schrute" + +# Hívjuk meg az osztály függvényt +Ember.mond('Hi') #=> "Hi" + +# Változók szókjait az elnevezésük definiálja +# $ kezdetű változók globálisak +$var = "Én egy globális változó vagyok" +defined? $var #=> "global-variable" + +# Változók amik @-al kezdődnek példány szkópjuk van +@var = "Én egy példány változó vagyok" +defined? @var #=> "instance-variable" + +# Változók amik @@-al kezdődnek példány szkópjuk van +@@var = "Én egy osztály változó vagyok" +defined? @@var #=> "class variable" + +# Változók amik nagy betűvel kezdődnek a konstansok +Var = "Konstans vagyok" +defined? Var #=> "constant" + +# Az osztály is objetum. Tehát az osztálynak lehet példány változója +# Az osztályváltozón osztozik minden pédány és leszármazott + +# Ős osztály +class Ember + @@foo = 0 + + def self.foo + @@foo + end + + def self.foo=(ertek) + @@foo = ertek + end +end + +# Leszarmazott osztály +class Dolgozo < Ember +end + +Ember.foo # 0 +Dolgozo.foo # 0 + +Ember.foo = 2 # 2 +Dolgozo.foo # 2 + +# Az osztálynak példány változóját nem látja az osztály leszármazottja. + +class Ember + @bar = 0 + + def self.bar + @bar + end + + def self.bar=(ertek) + @bar = ertek + end +end + +class Doctor < Ember +end + +Ember.bar # 0 +Doctor.bar # nil + +module ModulePelda + def foo + 'foo' + end +end + +# Modulok include-olása a fügvényeiket az osztály példányaihoz köti. +# Modulok extend-elésa a fügvényeiket magához az osztályhoz köti. + +class Szemely + include ModulePelda +end + +class Konyv + extend ModulePelda +end + +Szemely.foo # => NoMethodError: undefined method `foo' for Szemely:Class +Szemely.new.foo # => 'foo' +Konyv.foo # => 'foo' +Konyv.new.foo # => NoMethodError: undefined method `foo' + +# Callback-ek végrehajtódnak amikor include-olunk és extend-elünk egy modult + +module ConcernPelda + def self.included(base) + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + end + + module ClassMethods + def bar + 'bar' + end + end + + module InstanceMethods + def qux + 'qux' + end + end +end + +class Valami + include ConcernPelda +end + +Valami.bar # => 'bar' +Valami.qux # => NoMethodError: undefined method `qux' +Valami.new.bar # => NoMethodError: undefined method `bar' +Valami.new.qux # => 'qux' +``` + +## Egyéb források + +- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) +- [Official Documentation](http://www.ruby-doc.org/core-2.1.1/) +- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/) +- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - A régebbi [ingyenes változat](http://ruby-doc.com/docs/ProgrammingRuby/) elérhető online. +- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) diff --git a/json.html.markdown b/json.html.markdown index a85cecc4..a1629137 100644 --- a/json.html.markdown +++ b/json.html.markdown @@ -14,7 +14,7 @@ C-style (`//`, `/* */`) comments. Some parsers also tolerate a trailing comma (i.e. a comma after the last element of an array or the after the last property of an object), but they should be avoided for better compatibility. -For the purposes of this, however, everything is going to be 100% valid JSON. Luckily, it kind of speaks for itself. +For the purposes of this, however, everything is going to be 100% valid JSON. Luckily, it kind of speaks for itself. ```json { diff --git a/julia.html.markdown b/julia.html.markdown index 66329feb..c5089dc3 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -81,10 +81,13 @@ false # Strings are created with " "This is a string." +# Julia has several types of strings, including ASCIIString and UTF8String. +# More on this in the Types section. + # Character literals are written with ' 'a' -# A string can be indexed like an array of characters +# Some strings can be indexed like an array of characters "This is a string"[1] # => 'T' # Julia indexes from 1 # However, this is will not work well for UTF8 strings, # so iterating over strings is recommended (map, for loops, etc). @@ -314,7 +317,7 @@ end # For loops iterate over iterables. -# Iterable types include Range, Array, Set, Dict, and String. +# Iterable types include Range, Array, Set, Dict, and AbstractString. for animal=["dog", "cat", "mouse"] println("$animal is a mammal") # You can use $ to interpolate variables or expression into strings @@ -537,6 +540,17 @@ subtypes(Number) # => 6-element Array{Any,1}: # Real subtypes(Cat) # => 0-element Array{Any,1} +# AbstractString, as the name implies, is also an abstract type +subtypes(AbstractString) # 8-element Array{Any,1}: + # Base.SubstitutionString{T<:AbstractString} + # DirectIndexString + # RepString + # RevString{T<:AbstractString} + # RopeString + # SubString{T<:AbstractString} + # UTF16String + # UTF8String + # Every type has a super type; use the `super` function to get it. typeof(5) # => Int64 super(Int64) # => Signed @@ -546,17 +560,21 @@ super(Number) # => Any super(super(Signed)) # => Number super(Any) # => Any # All of these type, except for Int64, are abstract. +typeof("fire") # => ASCIIString +super(ASCIIString) # => DirectIndexString +super(DirectIndexString) # => AbstractString +# Likewise here with ASCIIString # <: is the subtyping operator type Lion <: Cat # Lion is a subtype of Cat mane_color - roar::String + roar::AbstractString end # You can define more constructors for your type # Just define a function of the same name as the type # and call an existing constructor to get a value of the correct type -Lion(roar::String) = Lion("green",roar) +Lion(roar::AbstractString) = Lion("green",roar) # This is an outer constructor because it's outside the type definition type Panther <: Cat # Panther is also a subtype of Cat diff --git a/matlab.html.markdown b/matlab.html.markdown index 02fe5962..0cbc6f57 100644 --- a/matlab.html.markdown +++ b/matlab.html.markdown @@ -3,6 +3,7 @@ language: Matlab contributors: - ["mendozao", "http://github.com/mendozao"] - ["jamesscottbrown", "http://jamesscottbrown.com"] + - ["Colton Kohnke", "http://github.com/voltnor"] --- @@ -464,6 +465,59 @@ mean % mean value std % standard deviation perms(x) % list all permutations of elements of x + +% Classes +% Matlab can support object-oriented programming. +% Classes must be put in a file of the class name with a .m extension. +% To begin, we create a simple class to store GPS waypoints. +% Begin WaypointClass.m +classdef WaypointClass % The class name. + properties % The properties of the class behave like Structures + latitude + longitude + end + methods + % This method that has the same name of the class is the constructor. + function obj = WaypointClass(lat, lon) + obj.latitude = lat; + obj.longitude = lon; + end + + % Other functions that use the Waypoint object + function r = multiplyLatBy(obj, n) + r = n*[obj.latitude]; + end + + % If we want to add two Waypoint objects together without calling + % a special function we can overload Matlab's arithmetic like so: + function r = plus(o1,o2) + r = WaypointClass([o1.latitude] +[o2.latitude], ... + [o1.longitude]+[o2.longitude]); + end + end +end +% End WaypointClass.m + +% We can create an object of the class using the constructor +a = WaypointClass(45.0, 45.0) + +% Class properties behave exactly like Matlab Structures. +a.latitude = 70.0 +a.longitude = 25.0 + +% Methods can be called in the same way as functions +ans = multiplyLatBy(a,3) + +% The method can also be called using dot notation. In this case, the object +% does not need to be passed to the method. +ans = a.multiplyLatBy(a,1/3) + +% Matlab functions can be overloaded to handle objects. +% In the method above, we have overloaded how Matlab handles +% the addition of two Waypoint objects. +b = WaypointClass(15.0, 32.0) +c = a + b + ``` ## More on Matlab diff --git a/perl.html.markdown b/perl.html.markdown index 4e172406..1b86f410 100644 --- a/perl.html.markdown +++ b/perl.html.markdown @@ -102,6 +102,8 @@ for (@elements) { print; } +# the Perlish post-condition way again +print for @elements; #### Regular expressions diff --git a/perl6.html.markdown b/perl6.html.markdown index 43327edb..0f015b45 100644 --- a/perl6.html.markdown +++ b/perl6.html.markdown @@ -75,7 +75,7 @@ say @array; #=> a 6 b # except they get "flattened" (hash context), removing duplicated keys. my %hash = 1 => 2, 3 => 4; -my %hash = autoquoted => "key", # keys get auto-quoted +my %hash = foo => "bar", # keys get auto-quoted "some other" => "value", # trailing commas are okay ; my %hash = <key1 value1 key2 value2>; # you can also create a hash @@ -96,7 +96,6 @@ say %hash<key2>; # If it's a string, you can actually use <> # (`{key1}` doesn't work, as Perl6 doesn't have barewords) ## * Subs (subroutines, or functions in most other languages). -# Stored in variable, they use `&`. sub say-hello { say "Hello, world" } sub say-hello-to(Str $name) { # You can provide the type of an argument @@ -107,8 +106,8 @@ sub say-hello-to(Str $name) { # You can provide the type of an argument ## It can also have optional arguments: sub with-optional($arg?) { # the "?" marks the argument optional - say "I might return `(Any)` if I don't have an argument passed, - or I'll return my argument"; + say "I might return `(Any)` (Perl's "null"-like value) if I don't have + an argument passed, or I'll return my argument"; $arg; } with-optional; # returns Any @@ -125,7 +124,7 @@ hello-to('You'); #=> Hello, You ! ## You can also, by using a syntax akin to the one of hashes (yay unified syntax !), ## pass *named* arguments to a `sub`. -# They're optional, and will default to "Any" (Perl's "null"-like value). +# They're optional, and will default to "Any". sub with-named($normal-arg, :$named) { say $normal-arg + $named; } @@ -162,7 +161,7 @@ named-def; #=> 5 named-def(def => 15); #=> 15 # Since you can omit parenthesis to call a function with no arguments, -# you need "&" in the name to capture `say-hello`. +# you need "&" in the name to store `say-hello` in a variable. my &s = &say-hello; my &other-s = sub { say "Anonymous function !" } @@ -173,8 +172,8 @@ sub as-many($head, *@rest) { # `*@` (slurpy) will basically "take everything els say @rest.join(' / ') ~ " !"; } say as-many('Happy', 'Happy', 'Birthday'); #=> Happy / Birthday ! - # Note that the splat did not consume - # the parameter before. + # Note that the splat (the *) did not + # consume the parameter before. ## You can call a function with an array using the # "argument list flattening" operator `|` @@ -380,7 +379,9 @@ say join(' ', @array[-> $n { 15..$n }]); # You can use that in most places you'd expect, even assigning to an array my @numbers = ^20; -my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99 + +# Here numbers increase by "6"; more on `...` operator later. +my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; @numbers[5..*] = 3, 9 ... *; # even though the sequence is infinite, # only the 15 needed values will be calculated. say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 @@ -525,7 +526,7 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (here with `sub`) # The constructs for declaring types are "class", "role", # which you'll see later. -# For now, let us examinate "subset": +# For now, let us examine "subset": # a "subset" is a "sub-type" with additional checks. # For example: "a very big integer is an Int that's greater than 500" # You can specify the type you're subtyping (by default, Any), @@ -608,27 +609,26 @@ sub foo { bar(); # call `bar` in-place } sub bar { - say $*foo; # `$*a` will be looked in the call stack, and find `foo`'s, + say $*foo; # `$*foo` will be looked in the call stack, and find `foo`'s, # even though the blocks aren't nested (they're call-nested). #=> 1 } ### Object Model -## Perl 6 has a quite comprehensive object model # You declare a class with the keyword `class`, fields with `has`, -# methods with `method`. Every field to private, and is named `$!attr`, -# but you have `$.` to get a public (immutable) accessor along with it. -# (using `$.` is like using `$!` plus a `method` with the same name) +# methods with `method`. Every attribute that is private is named `$!attr`. +# Immutable public attributes are named `$.attr` +# (you can make them mutable with `is rw`) -# (Perl 6's object model ("SixModel") is very flexible, +# Perl 6's object model ("SixModel") is very flexible, # and allows you to dynamically add methods, change semantics, etc ... # (this will not be covered here, and you should refer to the Synopsis). class A { has $.field; # `$.field` is immutable. # From inside the class, use `$!field` to modify it. - has $.other-field is rw; # You can obviously mark a public field `rw`. + has $.other-field is rw; # You can mark a public attribute `rw`. has Int $!private-field = 10; method get-value { @@ -656,7 +656,6 @@ $a.other-field = 10; # This, however, works, because the public field # is mutable (`rw`). ## Perl 6 also has inheritance (along with multiple inheritance) -# (though considered a misfeature by many) class A { has $.val; @@ -751,7 +750,7 @@ fail "foo"; # We're not trying to access the value, so no problem. try { fail "foo"; CATCH { - default { say "It threw because we try to get the fail's value!" } + default { say "It threw because we tried to get the fail's value!" } } } @@ -763,7 +762,7 @@ try { ### Packages # Packages are a way to reuse code. Packages are like "namespaces", and any # element of the six model (`module`, `role`, `class`, `grammar`, `subset` -# and `enum`) are actually packages. (Packages are the lowest common denomitor) +# and `enum`) are actually packages. (Packages are the lowest common denominator) # Packages are important - especially as Perl is well-known for CPAN, # the Comprehensive Perl Archive Network. # You usually don't use packages directly: you use `class Package::Name::Here;`, @@ -773,7 +772,7 @@ module Hello::World { # Bracketed form # that can be redeclared as something else later. # ... declarations here ... } -module Parse::Text; # file-scoped form +unit module Parse::Text; # file-scoped form grammar Parse::Text::Grammar { # A grammar is a package, which you could `use` } @@ -797,10 +796,8 @@ my $actions = JSON::Tiny::Actions.new; # You've already seen `my` and `has`, we'll now explore the others. ## * `our` (happens at `INIT` time -- see "Phasers" below) -# Along with `my`, there are several others declarators you can use. -# The first one you'll want for the previous part is `our`. +# It's like `my`, but it also creates a package variable. # (All packagish things (`class`, `role`, etc) are `our` by default) -# it's like `my`, but it also creates a package variable: module Foo::Bar { our $n = 1; # note: you can't put a type constraint on an `our` variable our sub inc { @@ -829,7 +826,7 @@ constant why-not = 5, 15 ... *; say why-not[^5]; #=> 5 15 25 35 45 ## * `state` (happens at run time, but only once) -# State variables are only executed one time +# State variables are only initialized one time # (they exist in other langages such as C as `static`) sub fixed-rand { state $val = rand; @@ -862,7 +859,7 @@ for ^5 -> $a { ## * Compile-time phasers BEGIN { say "[*] Runs at compile time, as soon as possible, only once" } -CHECK { say "[*] Runs at compile time, instead as late as possible, only once" } +CHECK { say "[*] Runs at compile time, as late as possible, only once" } ## * Run-time phasers INIT { say "[*] Runs at run time, as soon as possible, only once" } @@ -870,10 +867,13 @@ END { say "Runs at run time, as late as possible, only once" } ## * Block phasers ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" } -LEAVE { say "Runs everytime you leave a block, even when an exception happened. Repeats on loop blocks." } +LEAVE { say "Runs everytime you leave a block, even when an exception + happened. Repeats on loop blocks." } -PRE { say "Asserts a precondition at every block entry, before ENTER (especially useful for loops)" } -POST { say "Asserts a postcondition at every block exit, after LEAVE (especially useful for loops)" } +PRE { say "Asserts a precondition at every block entry, + before ENTER (especially useful for loops)" } +POST { say "Asserts a postcondition at every block exit, + after LEAVE (especially useful for loops)" } ## * Block/exceptions phasers sub { @@ -891,12 +891,12 @@ for ^5 { ## * Role/class phasers COMPOSE { "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" } -# They allow for cute trick or clever code ...: -say "This code took " ~ (time - CHECK time) ~ "s to run"; +# They allow for cute tricks or clever code ...: +say "This code took " ~ (time - CHECK time) ~ "s to compile"; # ... or clever organization: sub do-db-stuff { - ENTER $db.start-transaction; # New transaction everytime we enter the sub + $db.start-transaction; # start a new transaction KEEP $db.commit; # commit the transaction if all went well UNDO $db.rollback; # or rollback if all hell broke loose } @@ -1020,7 +1020,7 @@ sub circumfix:<[ ]>(Int $n) { $n ** $n } say [5]; #=> 3125 - # circumfix is around. Again, not whitespace. + # circumfix is around. Again, no whitespace. sub postcircumfix:<{ }>(Str $s, Int $idx) { # post-circumfix is @@ -1052,9 +1052,9 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that) # Basically, they're operators that apply another operator. ## * Reduce meta-operator -# It's a prefix meta-operator that takes a binary functions and +# It's a prefix meta-operator that takes a binary function and # one or many lists. If it doesn't get passed any argument, -# it either return a "default value" for this operator +# it either returns a "default value" for this operator # (a meaningless value) or `Any` if there's none (examples below). # # Otherwise, it pops an element from the list(s) one at a time, and applies @@ -1089,7 +1089,7 @@ say [[&add]] 1, 2, 3; #=> 6 # This one is an infix meta-operator than also can be used as a "normal" operator. # It takes an optional binary function (by default, it just creates a pair), # and will pop one value off of each array and call its binary function on these -# until it runs out of elements. It runs the an array with all these new elements. +# until it runs out of elements. It returns an array with all of these new elements. (1, 2) Z (3, 4); # ((1, 3), (2, 4)), since by default, the function makes an array 1..3 Z+ 4..6; # (5, 7, 9), using the custom infix:<+> function @@ -1109,8 +1109,7 @@ say [[&add]] 1, 2, 3; #=> 6 # (and might include a closure), and on the right, a value or the predicate # that says when to stop (or Whatever for a lazy infinite list). my @list = 1, 2, 3 ... 10; # basic deducing -#my @list = 1, 3, 6 ... 10; # this throws you into an infinite loop, - # because Perl 6 can't figure out the end +#my @list = 1, 3, 6 ... 10; # this dies because Perl 6 can't figure out the end my @list = 1, 2, 3 ...^ 10; # as with ranges, you can exclude the last element # (the iteration when the predicate matches). my @list = 1, 3, 9 ... * > 30; # you can use a predicate @@ -1222,7 +1221,7 @@ so 'abbbbbbc' ~~ / a b ** 3..* c /; # `True` (infinite ranges are okay) # they use a more perl6-ish syntax: say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' # You can use ranges: -say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'aeiou' +say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae' # Just like in normal regexes, if you want to use a special character, escape it # (the last one is escaping a space) say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !' @@ -1244,7 +1243,7 @@ so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (the + doesn't replace the left so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing so 'fooABCABCbar' ~~ / foo [ A B C ] + bar /; # The previous line returns `True`. -# We match the "abc" 1 or more time (the `+` was applied to the group). +# We match the "ABC" 1 or more time (the `+` was applied to the group). # But this does not go far enough, because we can't actually get back what # we matched. @@ -1287,10 +1286,12 @@ say $/[0][0].Str; #=> ~ # This stems from a very simple fact: `$/` does not contain strings, integers or arrays, # it only contains match objects. These contain the `.list`, `.hash` and `.Str` methods. -# (but you can also just use `match<key>` for hash access and `match[idx]` for array access) +# (but you can also just use `match<key>` for hash access +# and `match[idx]` for array access) say $/[0].list.perl; #=> (Match.new(...),).list - # We can see it's a list of Match objects. Those contain a bunch of infos: - # where the match started/ended, the "ast" (see actions later), etc. + # We can see it's a list of Match objects. Those contain + # a bunch of infos: where the match started/ended, + # the "ast" (see actions later), etc. # You'll see named capture below with grammars. ## Alternatives - the `or` of regexps @@ -1328,7 +1329,7 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviously enough ... ### Extra: the MAIN subroutime # The `MAIN` subroutine is called when you run a Perl 6 file directly. -# It's very powerful, because Perl 6 actually parses the argument +# It's very powerful, because Perl 6 actually parses the arguments # and pass them as such to the sub. It also handles named argument (`--foo`) # and will even go as far as to autogenerate a `--help` sub MAIN($name) { say "Hello, $name !" } @@ -1346,7 +1347,7 @@ multi MAIN('add', $key, $value, Bool :$replace) { ... } multi MAIN('remove', $key) { ... } multi MAIN('import', File, Str :$as) { ... } # omitting parameter name # This produces: -# $ perl 6 cli.pl +# $ perl6 cli.pl # Usage: # t.pl [--replace] add <key> <value> # t.pl remove <key> diff --git a/pt-br/clojure-macros-pt.html.markdown b/pt-br/clojure-macros-pt.html.markdown new file mode 100644 index 00000000..dbc0c25c --- /dev/null +++ b/pt-br/clojure-macros-pt.html.markdown @@ -0,0 +1,154 @@ +--- +language: clojure +filename: learnclojure-pt.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Raphael Bezerra do Nascimento"] +lang: pt-br +--- + +Como todas as Lisps, a inerente [homoiconicity](https://en.wikipedia.org/wiki/Homoiconic) +do Clojure lhe dá acesso a toda a extensão da linguagem +para escrever rotinas de geração de código chamados "macros". Macros fornecem uma poderosa forma de adequar a linguagem +às suas necessidades. + +Pórem Tenha cuidado. É considerado má pratica escrever uma macro quando uma função vai fazer. Use uma macro apenas +quando você precisar do controle sobre quando ou se os argumentos para um formulário será avaliado. + +Você vai querer estar familiarizado com Clojure. Certifique-se de entender tudo em +[Clojure em Y Minutos](/docs/clojure/). + +```clojure +;; Defina uma macro utilizando defmacro. Sua macro deve ter como saida uma lista que possa +;; ser avaliada como codigo Clojure. +;; +;; Essa macro é a mesma coisa que se você escrever (reverse "Hello World") +(defmacro my-first-macro [] + (list reverse "Hello World")) + +;; Inspecione o resultado de uma macro utilizando macroexpand or macroexpand-1. +;; +;; Note que a chamada deve utilizar aspas simples. +(macroexpand '(my-first-macro)) +;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World") + +;; Você pode avaliar o resultad de macroexpand diretamente: +(eval (macroexpand '(my-first-macro))) +; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; mas você deve usar esse mais suscinto, sintax como de função: +(my-first-macro) ; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; Você pode tornar as coisas mais faceis pra você, utilizando a sintaxe de citação mais suscinta +;; para criar listas nas suas macros: +(defmacro my-first-quoted-macro [] + '(reverse "Hello World")) + +(macroexpand '(my-first-quoted-macro)) +;; -> (reverse "Hello World") +;; Note que reverse não é mais uma função objeto, mas um simbolo. + +;; Macros podem ter argumentos. +(defmacro inc2 [arg] + (list + 2 arg)) + +(inc2 2) ; -> 4 + +;; Mas se você tentar fazer isso com uma lista entre aspas simples, você vai receber um erro, por que o +;; argumento irá entra aspas simples também. Para contornar isso, Clojure prover uma maneira de utilizar aspas simples +;; em macros: `. Dentro `, você pode usar ~ para chegar ao escopo externo. +(defmacro inc2-quoted [arg] + `(+ 2 ~arg)) + +(inc2-quoted 2) + +;; Você pode usar os argumentos de destruturação habituais. Expandir lista de variaveis usando ~@ +(defmacro unless [arg & body] + `(if (not ~arg) + (do ~@body))) ; Lembrar o do! + +(macroexpand '(unless true (reverse "Hello World"))) +;; -> +;; (if (clojure.core/not true) (do (reverse "Hello World"))) + +;; (unless) avalia e retorna seu corpo, se o primeiro argumento é falso. +;; caso contrario, retorna nil + +(unless true "Hello") ; -> nil +(unless false "Hello") ; -> "Hello" + +;; Usado sem cuidados, macros podem fazer muito mal por sobreporem suas variaveis +(defmacro define-x [] + '(do + (def x 2) + (list x))) + +(def x 4) +(define-x) ; -> (2) +(list x) ; -> (2) + +;;s Para evitar isso, use gensym para receber um identificador unico +(gensym 'x) ; -> x1281 (ou outra coisa) + +(defmacro define-x-safely [] + (let [sym (gensym 'x)] + `(do + (def ~sym 2) + (list ~sym)))) + +(def x 4) +(define-x-safely) ; -> (2) +(list x) ; -> (4) + +;; Você pode usar # dentro de ` para produzir uma gensym para cada simbolo automaticamente +(defmacro define-x-hygenically [] + `(do + (def x# 2) + (list x#))) + +(def x 4) +(define-x-hygenically) ; -> (2) +(list x) ; -> (4) + +;; É típico o uso de funções de auxilio com macros. Vamos criar um pouco +;; Vamos criar um pouco para nos ajudar a suportar uma sintaxe aritmética inline (estupida) +(declare inline-2-helper) +(defn clean-arg [arg] + (if (seq? arg) + (inline-2-helper arg) + arg)) + +(defn apply-arg + "Given args [x (+ y)], return (+ x y)" + [val [op arg]] + (list op val (clean-arg arg))) + +(defn inline-2-helper + [[arg1 & ops-and-args]] + (let [ops (partition 2 ops-and-args)] + (reduce apply-arg (clean-arg arg1) ops))) + +;; Podemos testar isso imediatamente, sem criar uma macro +(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5)) + +; Entretanto, temos que tornar isso uma macro caso quisermos que isso seja rodado em tempo de compilação +(defmacro inline-2 [form] + (inline-2-helper form))) + +(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) +; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) + +(inline-2 (1 + (3 / 2) - (1 / 2) + 1)) +; -> 3 (Na verdade, 3N, desde que o numero ficou convertido em uma fração racional com / + +### Leitura adicional + +Escrevendo Macros de [Clojure para o Brave e True](http://www.braveclojure.com/) +[http://www.braveclojure.com/writing-macros/](http://www.braveclojure.com/writing-macros/) + +Documentos oficiais +[http://clojure.org/macros](http://clojure.org/macros) + +Quando utilizar macros? +[http://dunsmor.com/lisp/onlisp/onlisp_12.html](http://dunsmor.com/lisp/onlisp/onlisp_12.html) 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/scala.html.markdown b/scala.html.markdown index 7189be10..7f545196 100644 --- a/scala.html.markdown +++ b/scala.html.markdown @@ -6,7 +6,6 @@ contributors: - ["Dominic Bou-Samra", "http://dbousamra.github.com"] - ["Geoff Liu", "http://geoffliu.me"] - ["Ha-Duong Nguyen", "http://reference-error.org"] -filename: learn.scala --- Scala - the scalable language @@ -244,10 +243,11 @@ i // Show the value of i. Note that while is a loop in the classical sense - // comprehensions above is easier to understand and parallelize // A do while loop +i = 0 do { - println("x is still less than 10") - x += 1 -} while (x < 10) + println("i is still less than 10") + i += 1 +} while (i < 10) // Tail recursion is an idiomatic way of doing recurring things in Scala. // Recursive functions need an explicit return type, the compiler can't infer it. @@ -566,8 +566,8 @@ sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!" // Implicit function parameters enable us to simulate type classes in other // functional languages. It is so often used that it gets its own shorthand. The // following two lines mean the same thing: -def foo[T](implicit c: C[T]) = ... -def foo[T : C] = ... +// def foo[T](implicit c: C[T]) = ... +// def foo[T : C] = ... // Another situation in which the compiler looks for an implicit is if you have |