diff options
| -rw-r--r-- | es-es/visualbasic-es.html.markdown | 286 | ||||
| -rw-r--r-- | fr-fr/scala.html.markdown | 9 | ||||
| -rw-r--r-- | hu-hu/ruby.html.markdown | 555 | ||||
| -rw-r--r-- | julia.html.markdown | 26 | ||||
| -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 | 
9 files changed, 1728 insertions, 58 deletions
| 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/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/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/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/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 | 
