diff options
34 files changed, 4218 insertions, 549 deletions
diff --git a/coffeescript.html.markdown b/coffeescript.html.markdown index 86c875ba..4fdf5903 100644 --- a/coffeescript.html.markdown +++ b/coffeescript.html.markdown @@ -2,7 +2,7 @@ language: coffeescript contributors: - ["Tenor Biel", "http://github.com/L8D"] - - ["Xavier Yao"], "http://github.com/xavieryao"] + - ["Xavier Yao", "http://github.com/xavieryao"] filename: coffeescript.coffee --- @@ -14,7 +14,7 @@ See also [the CoffeeScript website](http://coffeescript.org/), which has a compl ``` coffeescript # CoffeeScript is a hipster language. # It goes with the trends of many modern languages. -# So comments are like Ruby and Python, they use hashes. +# So comments are like Ruby and Python, they use number symbols. ### Block comments are like these, and they translate directly to '/ *'s and '* /'s diff --git a/common-lisp.html.markdown b/common-lisp.html.markdown index dda60797..8de81549 100644 --- a/common-lisp.html.markdown +++ b/common-lisp.html.markdown @@ -8,7 +8,7 @@ contributors: ANSI Common Lisp is a general purpose, multi-paradigm programming language suited for a wide variety of industry applications. It is -frequently referred to a programmable programming language. +frequently referred to as a programmable programming language. The classic starting point is [Practical Common Lisp and freely available.](http://www.gigamonkeys.com/book/) @@ -140,7 +140,7 @@ nil ; for false - and the empty list ;; 2. Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; You can create a global (dynamically scoped) using defparameter -;; a variable name can use any character except: ()[]{}",'`;#|\ +;; a variable name can use any character except: ()",'`;#|\ ;; Dynamically scoped variables should have earmuffs in their name! diff --git a/csharp.html.markdown b/csharp.html.markdown index a689fe97..81eb467d 100644 --- a/csharp.html.markdown +++ b/csharp.html.markdown @@ -558,7 +558,7 @@ on a new line! ""Wow!"", the masses cried"; } set // set - define a method to set a proprety { - _cadence = value; // Value is the value passed in to to the setter + _cadence = value; // Value is the value passed in to the setter } } private int _cadence; @@ -576,7 +576,7 @@ on a new line! ""Wow!"", the masses cried"; } int _speed; // Everything is private by default: Only accessible from within this class. - // can also use keyword privatee + // can also use keyword private public string Name { get; set; } // Enum is a value type that consists of a set of named constants @@ -608,7 +608,7 @@ on a new line! ""Wow!"", the masses cried"; // This is a default constructor public Bicycle() { - this.Gear = 1; // you can access mmebers of the object with the keyword this + this.Gear = 1; // you can access members of the object with the keyword this Cadence = 50; // but you don't always need it _speed = 5; Name = "Bontrager"; diff --git a/css.html.markdown b/css.html.markdown index 76319340..cdef50cc 100644 --- a/css.html.markdown +++ b/css.html.markdown @@ -44,16 +44,16 @@ Given an element like this on the page: <div class='some-class class2' id='someId' attr='value' /> */ -/* you can target it by it's class name */ +/* you can target it by its name */ .some-class { } /*or by both classes! */ .some-class.class2 { } -/* or by it's tag name */ +/* or by its element name */ div { } -/* or it's id */ +/* or its id */ #someId { } /* or by the fact that it has an attribute! */ @@ -77,12 +77,12 @@ any spaaace between different parts because that makes it to have another meaning.*/ div.some-class[attr$='ue'] { } -/* you can also select an element based on how it's parent is.*/ +/* you can also select an element based on its parent.*/ /*an element which is direct child of an element (selected the same way) */ div.some-parent > .class-name {} -/* or any of it's parents in the tree */ +/* or any of its parents in the tree */ /* the following basically means any element that has class "class-name" and is child of a div with class name "some-parent" IN ANY DEPTH */ div.some-parent .class-name {} @@ -91,7 +91,7 @@ div.some-parent .class-name {} can you say what? */ div.some-parent.class-name {} -/* you also might choose to select an element based on it's direct +/* you also might choose to select an element based on its direct previous sibling */ .i-am-before + .this-element { } @@ -99,7 +99,7 @@ previous sibling */ .i-am-any-before ~ .this-element {} /* There are some pseudo classes that allows you to select an element -based on it's page behaviour (rather than page structure) */ +based on its page behaviour (rather than page structure) */ /* for example for when an element is hovered */ :hover {} diff --git a/elisp.html.markdown b/elisp.html.markdown index d3910759..3208ffb8 100644 --- a/elisp.html.markdown +++ b/elisp.html.markdown @@ -280,10 +280,10 @@ filename: learn-emacs-lisp.el ;; should stop searching at some point in the buffer, and whether it ;; should silently fail when nothing is found: -;; (search-forward "Hello" nil t) does the trick: +;; (search-forward "Hello" nil 't) does the trick: ;; The `nil' argument says: the search is not bound to a position. -;; The `t' argument says: silently fail when nothing is found. +;; The `'t' argument says: silently fail when nothing is found. ;; We use this sexp in the function below, which doesn't throw an error: @@ -294,7 +294,7 @@ filename: learn-emacs-lisp.el (mapcar 'hello list-of-names) (goto-char (point-min)) ;; Replace "Hello" by "Bonjour" - (while (search-forward "Hello" nil t) + (while (search-forward "Hello" nil 't) (replace-match "Bonjour")) (other-window 1)) @@ -305,7 +305,7 @@ filename: learn-emacs-lisp.el (defun boldify-names () (switch-to-buffer-other-window "*test*") (goto-char (point-min)) - (while (re-search-forward "Bonjour \\(.+\\)!" nil t) + (while (re-search-forward "Bonjour \\([^!]+\\)!" nil 't) (add-text-properties (match-beginning 1) (match-end 1) (list 'face 'bold))) @@ -317,9 +317,9 @@ filename: learn-emacs-lisp.el ;; The regular expression is "Bonjour \\(.+\\)!" and it reads: ;; the string "Bonjour ", and -;; a group of | this is the \\( ... \\) construct -;; any character | this is the . -;; possibly repeated | this is the + +;; a group of | this is the \\( ... \\) construct +;; any character not ! | this is the [^!] +;; possibly repeated | this is the + ;; and the "!" string. ;; Ready? Test it! diff --git a/elixir.html.markdown b/elixir.html.markdown index 8ea499ff..0892deb7 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -9,9 +9,9 @@ Elixir is a modern functional language built on top of the Erlang VM. It's fully compatible with Erlang, but features a more standard syntax and many more features. -```ruby +```elixir -# Single line comments start with a hashtag. +# Single line comments start with a number symbol. # There's no multi-line comment, # but you can stack multiple comments. diff --git a/es-es/julia-es.html.markdown b/es-es/julia-es.html.markdown new file mode 100644 index 00000000..41a7c68b --- /dev/null +++ b/es-es/julia-es.html.markdown @@ -0,0 +1,759 @@ +--- +language: julia +contributors: + - ["Leah Hanson", "http://leahhanson.us"] + - ["Guillermo Garza" ] +filename: learnjulia-es.jl +lang: es-es +--- + +Julia es un nuevo lenguaje funcional homoiconic enfocado en computación técnica. +Aunque que tiene todo el poder de macros homoiconic, funciones de primera +clase, y control de bajo nivel, Julia es tan fácil de aprender y utilizar como +Python. + +Esto se basa en la versión de desarrollo actual de Julia, del 18 de octubre de +2013. + +```ruby + +# Comentarios de una línea comienzan con una almohadilla (o signo gato) + +#= Commentarios multilinea pueden escribirse + usando '#=' antes de el texto y '=#' + después del texto. También se pueden anidar. +=# + +#################################################### +## 1. Tipos de datos primitivos y operadores. +#################################################### + +# Todo en Julia es una expresión. + +# Hay varios tipos básicos de números. +3 # => 3 (Int64) +3.2 # => 3.2 (Float64) +2 + 1im # => 2 + 1im (Complex{Int64}) +2//3 # => 2//3 (Rational{Int64}) + +# Todos los operadores infijos normales están disponibles. +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 +5/2 # => 2.5 # dividir un Int por un Int siempre resulta en un Float +div (5, 2) # => 2 # para un resultado truncado, usa div +5 \ 35 # => 7.0 +2 ^ 2 # => 4 # exponente, no es xor +12 % 10 # => 2 + +# Refuerza la precedencia con paréntesis +(1 + 3) * 2 # => 8 + +# Operadores a nivel de bit +~2 # => -3 # bitwise not +3 & 5 # => 1 # bitwise and +2 | 4 # => 6 # bitwise or +2 $ 4 # => 6 # bitwise xor +2 >>> 1 # => 1 # logical shift right +2 >> 1 # => 1 # arithmetic shift right +2 << 1 # => 4 # logical/arithmetic shift left + +# Se puede utilizar la función bits para ver la representación binaria de un +# número. +bits(12345) +# => "0000000000000000000000000000000000000000000000000011000000111001" +bits(12345.0) +# => "0100000011001000000111001000000000000000000000000000000000000000" + +# Valores 'boolean' (booleanos) son primitivos +true +false + +# Operadores Boolean (booleanos) +!true # => false +!false # => true +1 == 1 # => true +2 == 1 # => false +1 != 1 # => false +2 != 1 # => true +1 < 10 # => true +1 > 10 # => false +2 <= 2 # => true +2 >= 2 # => true +# ¡Las comparaciones pueden ser concatenadas! +1 < 2 < 3 # => true +2 < 3 < 2 # => false + +# Strings se crean con " +"Esto es un string." + +# Literales de caracteres se escriben con ' +'a' + +# Una string puede ser indexado como una array de caracteres +"Esto es un string."[1] # => 'E' # Índices en Julia empiezen del 1 +# Sin embargo, esto no va a funcionar bien para strings UTF8, +# Lo que se recomienda es la iteración (map, for, etc). + +# $ puede ser utilizado para la interpolación de strings: +"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" +# Se puede poner cualquier expresión de Julia dentro los paréntesis. + +# Otro forma de formatear strings es el macro printf +@printf "%d es menor de %f" 4.5 5.3 # 5 es menor de 5.300000 + +# Imprimir es muy fácil +println("Soy Julia. ¡Encantado de conocerte!") + +#################################################### +## 2. Variables y Colecciones +#################################################### + +# No hay necesidad de declarar las variables antes de asignarlas. +una_variable = 5 # => 5 +una_variable # => 5 + +# Acceder a variables no asignadas previamente es una excepción. +try + otra_variable # => ERROR: some_other_var not defined +catch e + println(e) +end + +# Los nombres de variables comienzan con una letra. +# Después de eso, puedes utilizar letras, dígitos, guiones y signos de +# exclamación. +OtraVariable123! = 6 # => 6 + +# También puede utilizar caracteres unicode +☃ = 8 # => 8 +# Estos son especialmente útiles para la notación matemática +2 * π # => 6.283185307179586 + +# Una nota sobre las convenciones de nomenclatura de Julia: +# +# * Los nombres de las variables aparecen en minúsculas, con separación de +# palabra indicado por underscore ('\ _'). +# +# * Los nombres de los tipos comienzan con una letra mayúscula y separación de +# palabras se muestra con CamelCase en vez de underscore. +# +# * Los nombres de las funciones y los macros están en minúsculas, sin +# underscore. +# +# * Funciones que modifican sus inputs tienen nombres que terminan en!. Estos +# funciones a veces se llaman mutating functions o in-place functions. + +# Los Arrays almacenan una secuencia de valores indexados entre 1 hasta n +a = Int64[] # => 0-element Int64 Array + +# Literales de arrays 1-dimensionales se pueden escribir con valores separados +# por comas. +b = [4, 5, 6] # => 3-element Int64 Array: [4, 5, 6] +b[1] # => 4 +b[end] # => 6 + +# Los arrays 2-dimensionales usan valores separados por espacios y filas +# separados por punto y coma. +matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4] + +# Añadir cosas a la final de una lista con push! y append! +push!(a,1) # => [1] +push!(a,2) # => [1,2] +push!(a,4) # => [1,2,4] +push!(a,3) # => [1,2,4,3] +append!(a,b) # => [1,2,4,3,4,5,6] + +# Eliminar de la final con pop +pop!(b) # => 6 y b ahora es [4,5] + +# Vamos a ponerlo de nuevo +push!(b, 6) # b es ahora [4,5,6] de nuevo. + +a[1] # => 1 # recuerdan que los índices de Julia empiezan desde 1, no desde 0! + +# end es una abreviatura para el último índice. Se puede utilizar en cualquier +# expresión de indexación +a[end] # => 6 + +# tambien hay shift y unshift +shift!(a) # => 1 y a es ahora [2,4,3,4,5,6] +unshift!(a,7) # => [7,2,4,3,4,5,6] + +# Nombres de funciónes que terminan en exclamaciones indican que modifican +# su argumento. +arr = [5,4,6] # => 3-element Int64 Array: [5,4,6] +sort(arr) # => [4,5,6]; arr es todavía [5,4,6] +sort!(arr) # => [4,5,6]; arr es ahora [4,5,6] + +# Buscando fuera de límites es un BoundsError +try + a[0] # => ERROR: BoundsError() in getindex at array.jl:270 + a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270 +catch e + println(e) +end + +# Errors dan la línea y el archivo de su procedencia, aunque sea en el standard +# library. Si construyes Julia de source, puedes buscar en el source para +# encontrar estos archivos. + +# Se puede inicializar arrays de un range +a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5] + +# Puedes mirar en ranges con sintaxis slice. +a[1:3] # => [1, 2, 3] +a[2:end] # => [2, 3, 4, 5] + +# Eliminar elementos de una array por índice con splice! +arr = [3,4,5] +splice!(arr,2) # => 4 ; arr es ahora [3,5] + +# Concatenar listas con append! +b = [1,2,3] +append!(a,b) # ahroa a es [1, 2, 3, 4, 5, 1, 2, 3] + +# Comprueba la existencia en una lista con in +in(1, a) # => true + +# Examina la longitud con length +length(a) # => 8 + +# Tuples son immutable. +tup = (1, 2, 3) # => (1,2,3) # un (Int64,Int64,Int64) tuple. +tup[1] # => 1 +try: + tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) +catch e + println(e) +end + +# Muchas funciones de lista también trabajan en las tuples +length(tup) # => 3 +tup[1:2] # => (1,2) +in(2, tup) # => true + +# Se puede desempacar tuples en variables +a, b, c = (1, 2, 3) # => (1,2,3) # a is now 1, b is now 2 and c is now 3 + +# Los tuples se crean, incluso si se omite el paréntesis +d, e, f = 4, 5, 6 # => (4,5,6) + +# Un tuple 1-elemento es distinto del valor que contiene +(1,) == 1 # => false +(1) == 1 # => true + +# Mira que fácil es cambiar dos valores +e, d = d, e # => (5,4) # d is now 5 and e is now 4 + + +# Dictionaries almanecan mapeos +dict_vacio = Dict() # => Dict{Any,Any}() + +# Se puede crear un dictionary usando un literal +dict_lleno = ["one"=> 1, "two"=> 2, "three"=> 3] +# => Dict{ASCIIString,Int64} + +# Busca valores con [] +dict_lleno["one"] # => 1 + +# Obtén todas las claves +keys(dict_lleno) +# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# Nota - claves del dictionary no están ordenados ni en el orden en que se +# insertan. + +# Obtén todos los valores +values(dict_lleno) +# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# Nota - Igual que el anterior en cuanto a ordenamiento de claves. + +# Compruebe si hay existencia de claves en un dictionary con in y haskey +in(("uno", 1), dict_lleno) # => true +in(("tres", 3), dict_lleno) # => false +haskey(dict_lleno, "one") # => true +haskey(dict_lleno, 1) # => false + +# Tratando de buscar una clave que no existe producirá un error +try + dict_lleno["dos"] # => ERROR: key not found: dos in getindex at dict.jl:489 +catch e + println(e) +end + +# Utilice el método get para evitar ese error proporcionando un valor +# predeterminado +# get(dictionary,key,default_value) +get(dict_lleno,"one",4) # => 1 +get(dict_lleno,"four",4) # => 4 + +# Usa Sets para representar colecciones (conjuntos) de valores únicos, no +# ordenadas +conjunto_vacio = Set() # => Set{Any}() +# Iniciar una set de valores +conjunto_lleno = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4) + +# Añadir más valores a un conjunto +push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1) +push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1) + +# Compruebe si los valores están en el conjunto +in(2, conjunto_lleno) # => true +in(10, conjunto_lleno) # => false + +# Hay funciones de intersección de conjuntos, la unión, y la diferencia. +conjunto_otro= Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3) +intersect(conjunto_lleno, conjunto_otro) # => Set{Int64}(3,4,5) +union(conjunto_lleno, conjunto_otro) # => Set{Int64}(1,2,3,4,5,6) +setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4) + + +#################################################### +## 3. Control de Flujo +#################################################### + +# Hagamos una variable +una_variable = 5 + +# Aquí está una declaración de un 'if'. La indentación no es significativa en +# Julia +if una_variable > 10 + println("una_variable es completamente mas grande que 10.") +elseif una_variable < 10 # Este condición 'elseif' es opcional. + println("una_variable es mas chica que 10.") +else # Esto también es opcional. + println("una_variable es de hecho 10.") +end +# => imprime "una_variable es mas chica que 10." + +# For itera sobre tipos iterables +# Tipos iterables incluyen Range, Array, Set, Dict, y String. +for animal=["perro", "gato", "raton"] + println("$animal es un mamifero") + # Se puede usar $ para interpolar variables o expresiónes en strings +end +# imprime: +# perro es un mamifero +# gato es un mamifero +# raton es un mamifero + +for a in ["perro"=>"mamifero","gato"=>"mamifero","raton"=>"mamifero"] + println("$(a[1]) es un $(a[2])") +end +# imprime: +# perro es un mamifero +# gato es un mamifero +# raton es un mamifero + +for (k,v) in ["perro"=>"mamifero", "gato"=>"mamifero", "raton"=>"mamifero"] + println("$k es un $v") +end +# imprime: +# perro es un mamifero +# gato es un mamifero +# raton es un mamifero + +# While itera hasta que una condición no se cumple. +x = 0 +while x < 4 + println(x) + x += 1 # versión corta de x = x + 1 +end +# imprime: +# 0 +# 1 +# 2 +# 3 + +# Maneja excepciones con un bloque try/catch +try + error("ayuda") +catch e + println("capturando $e") +end +# => capturando ErrorException("ayuda") + + +#################################################### +## 4. Funciones +#################################################### + +# Usa 'function' para crear nuevas funciones + +#function nombre(arglist) +# cuerpo... +#end +function suma(x, y) + println("x es $x e y es $y") + + # Las funciones devuelven el valor de su última declaración + x + y +end + +suma(5, 6) # => 11 # después de imprimir "x es 5 e y es de 6" + +# Puedes definir funciones que toman un número variable de +# argumentos posicionales +function varargs(args...) + return args + # Usa la palabra clave return para devolver en cualquier lugar de la función +end +# => varargs (generic function with 1 method) + +varargs(1,2,3) # => (1,2,3) + +# El ... se llama un splat. +# Acabamos de utilizar lo en una definición de función. +# También se puede utilizar en una llamada de función, +# donde va splat un Array o el contenido de un Tuple en la lista de argumentos. +Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # Produce un Set de Arrays +Set([1,2,3]...) # => Set{Int64}(1,2,3) # esto es equivalente a Set(1,2,3) + +x = (1,2,3) # => (1,2,3) +Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # un Set de Tuples +Set(x...) # => Set{Int64}(2,3,1) + + +# Puede definir funciones con argumentos posicionales opcionales +function defaults(a,b,x=5,y=6) + return "$a $b y $x $y" +end + +defaults('h','g') # => "h g y 5 6" +defaults('h','g','j') # => "h g y j 6" +defaults('h','g','j','k') # => "h g y j k" +try + defaults('h') # => ERROR: no method defaults(Char,) + defaults() # => ERROR: no methods defaults() +catch e + println(e) +end + +# Puedes definir funciones que toman argumentos de palabra clave +function args_clave(;k1=4,nombre2="hola") # note the ; + return ["k1"=>k1,"nombre2"=>nombre2] +end + +args_clave(nombre2="ness") # => ["nombre2"=>"ness","k1"=>4] +args_clave(k1="mine") # => ["k1"=>"mine","nombre2"=>"hola"] +args_clave() # => ["nombre2"=>"hola","k1"=>4] + +# Puedes combinar todo tipo de argumentos en la misma función +function todos_los_args(arg_normal, arg_posicional_opcional=2; arg_clave="foo") + println("argumento normal: $arg_normal") + println("argumento optional: $arg_posicional_opcional") + println("argumento de clave: $arg_clave") +end + +todos_los_args(1, 3, arg_clave=4) +# imprime: +# argumento normal: 1 +# argumento optional: 3 +# argumento de clave: 4 + +# Julia tiene funciones de primera clase +function crear_suma(x) + suma = function (y) + return x + y + end + return suma +end + +# Esta es el sintaxis "stabby lambda" para crear funciones anónimas +(x -> x > 2)(3) # => true + +# Esta función es idéntica a la crear_suma implementación anterior. +function crear_suma(x) + y -> x + y +end + +# También puedes nombrar la función interna, si quieres +function crear_suma(x) + function suma(y) + x + y + end + suma +end + +suma_10 = crear_suma(10) +suma_10(3) # => 13 + + +# Hay funciones integradas de orden superior +map(suma_10, [1,2,3]) # => [11, 12, 13] +filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# Podemos usar listas por comprensión para mapeos +[suma_10(i) for i=[1, 2, 3]] # => [11, 12, 13] +[suma_10(i) for i in [1, 2, 3]] # => [11, 12, 13] + +#################################################### +## 5. Tipos +#################################################### + +# Julia tiene sistema de tipos. +# Cada valor tiene un tipo y las variables no tienen propios tipos. +# Se puede utilizar la función `typeof` para obtener el tipo de un valor. +typeof(5) # => Int64 + +# Los tipos son valores de primera clase +typeof(Int64) # => DataType +typeof(DataType) # => DataType +# DataType es el tipo que representa los tipos, incluyéndose a sí mismo. + +# Los tipos se usan para la documentación, optimizaciones, y envio. +# No están comprobados estáticamente. + +# Los usuarios pueden definir tipos +# Son como registros o estructuras en otros idiomas. +# Nuevos tipos se definen utilizado la palabra clave `type`. + +# type Nombre +# field::OptionalType +# ... +# end +type Tigre + longituddecola::Float64 + colordelpelaje # no incluyendo una anotación de tipo es el mismo que `::Any` +end + +# Los argumentos del constructor por default son las propiedades +# del tipo, en el orden en que están listados en la definición +tigger = Tigre(3.5,"anaranjado") # => Tiger(3.5,"anaranjado") + +# El tipo funciona como la función constructora de valores de ese tipo +sherekhan = typeof(tigger)(5.6,"fuego") # => Tiger(5.6,"fuego") + + +# Este estilo de tipos son llamados tipos concrete +# Se pueden crear instancias, pero no pueden tener subtipos. +# La otra clase de tipos es tipos abstractos (abstract types). + +# abstract Nombre +abstract Gato # sólo un nombre y un punto en la jerarquía de tipos + +# De los tipos Abstract no se pueden crear instancias, pero pueden tener +# subtipos. Por ejemplo, Number es un tipo abstracto. +subtypes(Number) # => 6-element Array{Any,1}: + # Complex{Float16} + # Complex{Float32} + # Complex{Float64} + # Complex{T<:Real} + # Real +subtypes(Gato) # => 0-element Array{Any,1} + +# Cada tipo tiene un supertipo, utilice la función `súper` para conseguirlo. +typeof(5) # => Int64 +super(Int64) # => Signed +super(Signed) # => Real +super(Real) # => Number +super(Number) # => Any +super(super(Signed)) # => Number +super(Any) # => Any +# Todo de estos tipos, a excepción de Int64, son abstractos. + +# <: es el operador de subtipos +type Leon <: Gato # Leon es un subtipo de Gato + color_de_crin + rugido::String +end + +# Se puede definir más constructores para su tipo. +# Sólo defina una función del mismo nombre que el tipo +# y llame a un constructor existente para obtener un valor del tipo correcto +Leon(rugido::String) = Leon("verde",rugido) +# Este es un constructor externo porque es fuera de la definición del tipo + +type Pantera <: Gato # Pantera tambien es un a subtipo de Cat + color_de_ojos + Pantera() = new("verde") + # Panteras sólo tendrán este constructor, y ningún constructor + # predeterminado. +end +# Utilizar constructores internos, como Panther hace, te da control sobre cómo +# se pueden crear valores del tipo. Cuando sea posible, debes utilizar +# constructores exteriores en lugar de los internos. + +#################################################### +## 6. Envio múltiple +#################################################### + +# En Julia, todas las funciones nombradas son funciones genéricas. +# Esto significa que se construyen a partir de muchos métodos pequeños +# Cada constructor de Leon es un método de la función genérica Leon. + +# Por ejemplo, vamos a hacer un maullar función: + +# Definiciones para Leon, Pantera, y Tigre +function maullar(animal::Leon) + animal.rugido # acceso utilizando notación de puntos +end + +function maullar(animal::Pantera) + "grrr" +end + +function maullar(animal::Tigre) + "rawwwr" +end + +# Prueba de la función maullar +maullar(tigger) # => "rawwr" +maullar(Leon("cafe","ROAAR")) # => "ROAAR" +maullar(Pantera()) # => "grrr" + +# Revisar la jerarquía de tipos locales +issubtype(Tigre,Gato) # => false +issubtype(Leon,Gato) # => true +issubtype(Pantera,Gato) # => true + +# Definición de una función que toma Gatos +function mascota(gato::Gato) + println("El gato dice $(maullar(gato))") +end + +mascota(Leon("42")) # => imprime "El gato dice 42" +try + mascota(tigger) # => ERROR: no method mascota(Tigre)) +catch e + println(e) +end + +# En los lenguajes orientados a objetos, expedición única es común. Esto +# significa que el método se recogió basándose en el tipo del primer argumento. +# En Julia, todos los tipos de argumentos contribuyen a seleccionar el mejor +# método. + +# Vamos a definir una función con más argumentos, para que podamos ver la +# diferencia +function pelear(t::Tigre,c::Gato) + println("¡El tigre $(t.colordelpelaje) gana!") +end +# => pelear (generic function with 1 method) + +pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana! +pelear(tigger,Leon("ROAR")) # => ¡El tigre anaranjado gana! + +# Vamos a cambiar el comportamiento cuando el Gato es específicamente un Leon +pelear(t::Tigre,l::Leon) = println("El león con melena $(l.color_de_crin) gana") +# => pelear (generic function with 2 methods) + +pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana! +pelear(tigger,Leon("ROAR")) # => imprime El león con melena verde gana + +# No necesitamos un tigre para poder luchar +pelear(l::Leon,c::Gato) = println("El gato victorioso dice $(maullar(c))") +# => fight (generic function with 3 methods) + +pelear(Leon("balooga!"),Pantera()) # => imprime El gato victorioso dice grrr +try + pelear(Pantera(),Leon("RAWR")) # => ERROR: no method pelear(Pantera, Leon)) +catch +end + +# Un metodo con el gato primero +pelear(c::Gato,l::Leon) = println("El gato le gana al León") +# Warning: New definition +# pelear(Gato,Leon) at none:1 +# is ambiguous with: +# pelear(Leon,Gato) at none:1. +# To fix, define +# pelear(Leon,Leon) +# before the new definition. +# pelear (generic function with 4 methods) + +# Esta advertencia se debe a que no está claro que metodo de pelear será llamado +# en: +pelear(Leon("RAR"),Leon("cafe","rar")) # => imprime El gato victorioso dice rar +# El resultado puede ser diferente en otras versiones de Julia + +pelear(l::Leon,l2::Leon) = println("Los leones llegan a un empate") +pelear(Leon("GR"),Leon("cafe","rar")) # => imprime Los leones llegan a un empate + + +# Un vistazo al nivel bajo +# Se puede echar un vistazo a la LLVM y el código ensamblador generado. + +area_cuadrada(l) = l * l # area_cuadrada (generic function with 1 method) + +area_cuadrada(5) # => 25 + +# ¿Qué sucede cuando damos area_cuadrada diferentes argumentos? +code_native(area_cuadrada, (Int32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 # Prologue + # push RBP + # mov RBP, RSP + # Source line: 1 + # movsxd RAX, EDI # Fetch l from memory? + # imul RAX, RAX # Square l and store the result in RAX + # pop RBP # Restore old base pointer + # ret # Result will still be in RAX + +code_native(area_cuadrada, (Float32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vmulss XMM0, XMM0, XMM0 # Scalar single precision multiply (AVX) + # pop RBP + # ret + +code_native(area_cuadrada, (Float64,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vmulsd XMM0, XMM0, XMM0 # Scalar double precision multiply (AVX) + # pop RBP + # ret + # + +# Ten en cuenta que Julia usará instrucciones de "floating point" si alguno de +# los argumentos son "floats" +# Vamos a calcular el área de un círculo +area_circulo(r) = pi * r * r # circle_area (generic function with 1 method) +area_circulo(5) # 78.53981633974483 + +code_native(area_circulo, (Int32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vcvtsi2sd XMM0, XMM0, EDI # Load integer (r) from memory + # movabs RAX, 4593140240 # Load pi + # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r + # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r + # pop RBP + # ret + # + +code_native(area_circulo, (Float64,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # movabs RAX, 4593140496 + # Source line: 1 + # vmulsd XMM1, XMM0, QWORD PTR [RAX] + # vmulsd XMM0, XMM1, XMM0 + # pop RBP + # ret + # +``` + +## ¿Listo para más? + +Puedes obtener muchos más detalles en [The Julia Manual](http://docs.julialang.org/en/latest/manual/) + +El mejor lugar para obtener ayuda con Julia es el (muy amable) [lista de correos](https://groups.google.com/forum/#!forum/julia-users). + diff --git a/fr-fr/python-fr.html.markdown b/fr-fr/python-fr.html.markdown index 9dbdafe1..58a036ba 100644 --- a/fr-fr/python-fr.html.markdown +++ b/fr-fr/python-fr.html.markdown @@ -75,7 +75,7 @@ not False #=> True # Les chaînes de caractères sont créées avec " ou ' "C'est une chaîne." -'C'est aussi une chaîne.' +'C\'est aussi une chaîne.' # On peut aussi les "additioner" ! "Hello " + "world!" #=> "Hello world!" diff --git a/go.html.markdown b/go.html.markdown index a66e8c4b..fa4c8d0b 100644 --- a/go.html.markdown +++ b/go.html.markdown @@ -171,10 +171,10 @@ func learnFlowControl() { } // Function literals are closures. xBig := func() bool { - return x > 100 // References x declared above switch statement. + return x > 10000 // References x declared above switch statement. } - fmt.Println("xBig:", xBig()) // true (we last assigned 1e6 to x). - x /= m.Exp(9) // This makes x == e. + fmt.Println("xBig:", xBig()) // true (we last assigned e^10 to x). + x = 1.3e3 // This makes x == 1300 fmt.Println("xBig:", xBig()) // false now. // When you need it, you'll love it. @@ -185,13 +185,11 @@ love: learnInterfaces() // Good stuff coming up! } - - func learnDefer() (ok bool) { - // deferred statements are executed just before the function returns. + // Deferred statements are executed just before the function returns. defer fmt.Println("deferred statements execute in reverse (LIFO) order.") defer fmt.Println("\nThis line is being printed first because") - // defer is commonly used to close a file, so the function closing the file + // Defer is commonly used to close a file, so the function closing the file // stays close to the function opening the file return true } @@ -237,7 +235,7 @@ func learnVariadicParams(myStrings ...interface{}) { for _, param := range myStrings { fmt.Println("param:", param) } - + // Pass variadic value as a variadic parameter. fmt.Println("params:", fmt.Sprintln(myStrings...)) @@ -299,7 +297,7 @@ func learnConcurrency() { // At this point a value was taken from either c or cs. One of the two // goroutines started above has completed, the other will remain blocked. - learnWebProgramming() // Go does it. You want to do it too. + learnWebProgramming() // Go does it. You want to do it too. } // A single function from package http starts a web server. diff --git a/id-id/css-id.html.markdown b/id-id/css-id.html.markdown index d0798ec7..456dfafe 100644 --- a/id-id/css-id.html.markdown +++ b/id-id/css-id.html.markdown @@ -1,3 +1,4 @@ +--- language: css contributors: - ["Mohammad Valipour", "https://github.com/mvalipour"] diff --git a/it-it/brainfuck-it.html.markdown b/it-it/brainfuck-it.html.markdown new file mode 100644 index 00000000..4999d7e6 --- /dev/null +++ b/it-it/brainfuck-it.html.markdown @@ -0,0 +1,101 @@ +--- + +language: brainfuck +contributors: + - ["Prajit Ramachandran", "http://prajitr.github.io/"] + - ["Mathias Bynens", "http://mathiasbynens.be/"] +translators: + - ["Ivan Sala", "http://slavni96.github.io/"] +lang: it-it + +--- + +Brainfuck è un linguaggio di programmazione estremamente minimale, +ma è ingrado di rappresentare completamente una macchina di turnig, +e sfrutta solo 8 caratteri. +[Per saperne di più](http://it.wikipedia.org/wiki/Brainfuck) + +``` + +Qualsiasi carattere che non sia "><+-.,[]" (escludendo gli apici) +viene ignorato. +Branfuck è caratterizzato da un array (vettore) di 30,000 celle +inizializzare a zero, e un puntatore che punta alla cella corrente. + +Vi sono solo otto comando: ++ : Incrementa il valore della cella attuale di uno. +- : Decrementa il valore della cella attuale di uno. +> : Sposta il puntatore sulla cella seguente (prossima a destra). +< : Sposta il puntatore sulla cella precendete (precedente a sinistra). +. : Stampa il valore in ASCII della cella corrente. (es: 65 = 'A') +, : Legge un singolo carattere come input per la cella corrente. +[ : Se il valore della cella corrente è zero, conclude il ciclo + andando alla sua corrispondente ]. + Altrimenti, passa alla prossima istruzione. +] : Se il valore della cella corrente è zero, passa alla prossima istruzione. + Altrimenti torna indetro fino alla [ corrispondente. + +[ e ] creano un loop (while). Ovviamente dovranno essere bilanciati. +Per ogni [ dovrà corrispondere una ] + +Alcuni semplici esempi di programmi scritti in Brainfuck: + +++++++ [ > ++++++++++ < - ] > +++++ . + +Questo programma stampa in output la lettera 'A'. Priam incrementa +la cella #1 fino a 6, Quindi la cella #1 viene usata per crare un ciclo. +Poi, entra in un loop ([) e si sposta alla cella #2. +Incrementa la cella #2 10 volte, e torna alla cella #1, e la decrementa. +Questo avviene 6 volte (servono che la cella #1 venga decrementata 6 volte +per raggiungere lo 0. Quindi passa alla corrispondente ] e prosegue). + +A questo punto, siamo sulla cella #1, che ha valore 0, +la cella #2 ha valore 60 (6*10). Ci spostiamo sulla cella #2, incrementiamo +per 5 volte, e otteniamo il valore 65, quindi stampaimo il valore della cella +#2 (.). +65 è 'A' in ASCII, quindi alla fine viene stampata 'A'. + + +, [ > + < - ] > . + +Questo programma legge un carattere come input dall'utente, +quindi salva il carattere dentro la cella #1. +In seguito, incominca a ciclare. +Si sposta alla cella #², e increementa il valore della cella (#2). +Quindi torna alla cella #1, e decrementa il valore della cella (#1). +Questo continua fino a quando la cella #²1 diventa 0, e quindi la cella #2 +avrà il valore iniziale della cella #1. +Infine, visto che ci troviamo sulla cella #1 alla fine del ciclo, si sposta +sulla cella #2 e stampa il valore in ASCII. + +Gli spazi nel codice sovrastante, sono presenti solo a scopo di ottenere +una maggiore leggibilità, si poteva anche scrivere senza: + +,[>+<-]>. + +Proviamo, adesso, a capire cosa fa invece questo programma: + +,>,< [ > [ >+ >+ << -] >> [- << + >>] <<< -] >> + +Prende due numeri in input e quindi li moltiplica. + +Prima prende in input i due numeri (,>,<), quindi inizia un cilclo +basandosi sulla cella #1. +Quindi si sposta sulla cella #2, e inizia un altro ciclo condizionato +dal valore della cella #2, incrementando la cella #3. +Arrivati a questo punto abbiamo un problema: alla fine del ciclo interno +la cella #2 ha valore 0. In questo caso, quando il ciclo esterno rifarà +partire il ciclo interno, non funzionerà più perchè la cella #2 ha valore 0. +Per ovviare a questo problema, oltre alla cella 3, incrementiamo anche la cella +#4, e alla fine di ogni ciclo interno copiala il valore della cella #4 +nella cella #2, in modo che il ciclo interno +possa essere eseguito una altra volta. +Alla fine la cella #3 contiene il risultato. +``` + +E questo è brainfuck...Non è difficele, vero? +Per divertimento adesso puoi scrivere i tuoi programmi in brainfuck, +oppure puoi scrivere un interprete brainfuck in un altro linguaggio. +L'interprete è abbastanza semplice da implementare, ma se sei veramente +masochista prova ad implementare un interprete brainfuck in... +brainfuck. diff --git a/it-it/java-it.html.markdown b/it-it/java-it.html.markdown index fb91aa19..6eabd61f 100644 --- a/it-it/java-it.html.markdown +++ b/it-it/java-it.html.markdown @@ -5,7 +5,7 @@ contributors: - ["Jake Prather", "http://github.com/JakeHP"] - ["Madison Dickson", "http://github.com/mix3d"] translators: - - ["Ivan Sala","http://github.com/dev-sala"] + - ["Ivan Sala","http://github.com/slavni96"] lang: it-it --- diff --git a/javascript.html.markdown b/javascript.html.markdown index 85c5d817..76017c17 100644 --- a/javascript.html.markdown +++ b/javascript.html.markdown @@ -2,6 +2,7 @@ language: javascript contributors: - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Ariel Krakowski", "http://www.learneroo.com"] filename: javascript.js --- @@ -103,7 +104,13 @@ false; "5" === 5; // = false // You can access characters in a string with charAt -"This is a string".charAt(0); +"This is a string".charAt(0); // = 'T' + +// ...or use substring to get larger pieces +"Hello world".substring(0, 5); // = "Hello" + +// length is a property, so don't use () +"Hello".length; // = 5 // There's also null and undefined null; // used to indicate a deliberate non-value @@ -148,6 +155,9 @@ myArray[1]; // = 45 myArray.push("World"); myArray.length; // = 4 +// Add/Modify at specific index +myArray[3] = "Hello"; + // JavaScript's objects are equivalent to 'dictionaries' or 'maps' in other // languages: an unordered collection of key-value pairs. var myObj = {key1: "Hello", key2: "World"}; @@ -171,6 +181,8 @@ myObj.myFourthKey; // = undefined /////////////////////////////////// // 3. Logic and Control Structures +// The syntax for this section is almost identical to Java's. + // The if structure works as you'd expect. var count = 1; if (count == 3){ @@ -209,6 +221,27 @@ if (colour == "red" || colour == "blue"){ // && and || "short circuit", which is useful for setting default values. var name = otherName || "default"; + +// switch statement checks for equality with === +// use 'break' after each case +// or the cases after the correct one will be executed too. +grade = 'B'; +switch (grade) { + case 'A': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} + + /////////////////////////////////// // 4. Functions, Scope and Closures @@ -477,9 +510,13 @@ more about how to use JavaScript in web pages, start by learning about the [Document Object Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) +[Learn Javascript by Example and with Challenges](http://www.learneroo.com/modules/64/nodes/350) is a variant of this reference with built-in challenges. + [JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/) is an in-depth guide of all the counter-intuitive parts of the language. +[JavaScript: The Definitive Guide](http://www.amazon.com/gp/product/0596805527/) is a classic guide / reference book. + In addition to direct contributors to this article, some content is adapted from Louie Dinh's Python tutorial on this site, and the [JS Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) diff --git a/julia.html.markdown b/julia.html.markdown index b8e24b39..15b4be90 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -12,7 +12,11 @@ This is based on the current development version of Julia, as of October 18th, 2 ```ruby -# Single line comments start with a hash. +# Single line comments start with a number symbol. +#= Multiline comments can be written + by putting '#=' before the text and '=#' + after the text. They can also be nested. +=# #################################################### ## 1. Primitive Datatypes and Operators @@ -21,58 +25,58 @@ This is based on the current development version of Julia, as of October 18th, 2 # Everything in Julia is a expression. # There are several basic types of numbers. -3 #=> 3 (Int64) -3.2 #=> 3.2 (Float64) -2 + 1im #=> 2 + 1im (Complex{Int64}) -2//3 #=> 2//3 (Rational{Int64}) +3 # => 3 (Int64) +3.2 # => 3.2 (Float64) +2 + 1im # => 2 + 1im (Complex{Int64}) +2//3 # => 2//3 (Rational{Int64}) # All of the normal infix operators are available. -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7.0 -5 / 2 #=> 2.5 # dividing an Int by an Int always results in a Float -div(5, 2) #=> 2 # for a truncated result, use div -5 \ 35 #=> 7.0 -2 ^ 2 #=> 4 # power, not bitwise xor -12 % 10 #=> 2 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 +5 / 2 # => 2.5 # dividing an Int by an Int always results in a Float +div(5, 2) # => 2 # for a truncated result, use div +5 \ 35 # => 7.0 +2 ^ 2 # => 4 # power, not bitwise xor +12 % 10 # => 2 # Enforce precedence with parentheses -(1 + 3) * 2 #=> 8 +(1 + 3) * 2 # => 8 # Bitwise Operators -~2 #=> -3 # bitwise not -3 & 5 #=> 1 # bitwise and -2 | 4 #=> 6 # bitwise or -2 $ 4 #=> 6 # bitwise xor -2 >>> 1 #=> 1 # logical shift right -2 >> 1 #=> 1 # arithmetic shift right -2 << 1 #=> 4 # logical/arithmetic shift left +~2 # => -3 # bitwise not +3 & 5 # => 1 # bitwise and +2 | 4 # => 6 # bitwise or +2 $ 4 # => 6 # bitwise xor +2 >>> 1 # => 1 # logical shift right +2 >> 1 # => 1 # arithmetic shift right +2 << 1 # => 4 # logical/arithmetic shift left # You can use the bits function to see the binary representation of a number. bits(12345) -#=> "0000000000000000000000000000000000000000000000000011000000111001" +# => "0000000000000000000000000000000000000000000000000011000000111001" bits(12345.0) -#=> "0100000011001000000111001000000000000000000000000000000000000000" +# => "0100000011001000000111001000000000000000000000000000000000000000" # Boolean values are primitives true false # Boolean operators -!true #=> false -!false #=> true -1 == 1 #=> true -2 == 1 #=> false -1 != 1 #=> false -2 != 1 #=> true -1 < 10 #=> true -1 > 10 #=> false -2 <= 2 #=> true -2 >= 2 #=> true +!true # => false +!false # => true +1 == 1 # => true +2 == 1 # => false +1 != 1 # => false +2 != 1 # => true +1 < 10 # => true +1 > 10 # => false +2 <= 2 # => true +2 >= 2 # => true # Comparisons can be chained -1 < 2 < 3 #=> true -2 < 3 < 2 #=> false +1 < 2 < 3 # => true +2 < 3 < 2 # => false # Strings are created with " "This is a string." @@ -81,12 +85,12 @@ false 'a' # A string can be indexed like an array of characters -"This is a string"[1] #=> 'T' # Julia indexes from 1 +"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). # $ can be used for string interpolation: -"2 + 2 = $(2 + 2)" #=> "2 + 2 = 4" +"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" # You can put any Julia expression inside the parenthesis. # Another way to format strings is the printf macro. @@ -100,24 +104,24 @@ println("I'm Julia. Nice to meet you!") #################################################### # You don't declare variables before assigning to them. -some_var = 5 #=> 5 -some_var #=> 5 +some_var = 5 # => 5 +some_var # => 5 # Accessing a previously unassigned variable is an error try - some_other_var #=> ERROR: some_other_var not defined + some_other_var # => ERROR: some_other_var not defined catch e println(e) end # Variable names start with a letter. # After that, you can use letters, digits, underscores, and exclamation points. -SomeOtherVar123! = 6 #=> 6 +SomeOtherVar123! = 6 # => 6 # You can also use unicode characters -☃ = 8 #=> 8 +☃ = 8 # => 8 # These are especially handy for mathematical notation -2 * π #=> 6.283185307179586 +2 * π # => 6.283185307179586 # A note on naming conventions in Julia: # @@ -133,49 +137,49 @@ SomeOtherVar123! = 6 #=> 6 # functions are sometimes called mutating functions or in-place functions. # Arrays store a sequence of values indexed by integers 1 through n: -a = Int64[] #=> 0-element Int64 Array +a = Int64[] # => 0-element Int64 Array # 1-dimensional array literals can be written with comma-separated values. -b = [4, 5, 6] #=> 3-element Int64 Array: [4, 5, 6] -b[1] #=> 4 -b[end] #=> 6 +b = [4, 5, 6] # => 3-element Int64 Array: [4, 5, 6] +b[1] # => 4 +b[end] # => 6 # 2-dimentional arrays use space-separated values and semicolon-separated rows. -matrix = [1 2; 3 4] #=> 2x2 Int64 Array: [1 2; 3 4] +matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4] # Add stuff to the end of a list with push! and append! -push!(a,1) #=> [1] -push!(a,2) #=> [1,2] -push!(a,4) #=> [1,2,4] -push!(a,3) #=> [1,2,4,3] -append!(a,b) #=> [1,2,4,3,4,5,6] +push!(a,1) # => [1] +push!(a,2) # => [1,2] +push!(a,4) # => [1,2,4] +push!(a,3) # => [1,2,4,3] +append!(a,b) # => [1,2,4,3,4,5,6] # Remove from the end with pop -pop!(b) #=> 6 and b is now [4,5] +pop!(b) # => 6 and b is now [4,5] # Let's put it back push!(b,6) # b is now [4,5,6] again. -a[1] #=> 1 # remember that Julia indexes from 1, not 0! +a[1] # => 1 # remember that Julia indexes from 1, not 0! # end is a shorthand for the last index. It can be used in any # indexing expression -a[end] #=> 6 +a[end] # => 6 # we also have shift and unshift -shift!(a) #=> 1 and a is now [2,4,3,4,5,6] -unshift!(a,7) #=> [7,2,4,3,4,5,6] +shift!(a) # => 1 and a is now [2,4,3,4,5,6] +unshift!(a,7) # => [7,2,4,3,4,5,6] # Function names that end in exclamations points indicate that they modify # their argument. -arr = [5,4,6] #=> 3-element Int64 Array: [5,4,6] -sort(arr) #=> [4,5,6]; arr is still [5,4,6] -sort!(arr) #=> [4,5,6]; arr is now [4,5,6] +arr = [5,4,6] # => 3-element Int64 Array: [5,4,6] +sort(arr) # => [4,5,6]; arr is still [5,4,6] +sort!(arr) # => [4,5,6]; arr is now [4,5,6] # Looking out of bounds is a BoundsError try - a[0] #=> ERROR: BoundsError() in getindex at array.jl:270 - a[end+1] #=> ERROR: BoundsError() in getindex at array.jl:270 + a[0] # => ERROR: BoundsError() in getindex at array.jl:270 + a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270 catch e println(e) end @@ -185,110 +189,109 @@ end # inside the julia folder to find these files. # You can initialize arrays from ranges -a = [1:5] #=> 5-element Int64 Array: [1,2,3,4,5] +a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5] # You can look at ranges with slice syntax. -a[1:3] #=> [1, 2, 3] -a[2:] #=> [2, 3, 4, 5] -a[2:end] #=> [2, 3, 4, 5] +a[1:3] # => [1, 2, 3] +a[2:end] # => [2, 3, 4, 5] # Remove elements from an array by index with splice! arr = [3,4,5] -splice!(arr,2) #=> 4 ; arr is now [3,5] +splice!(arr,2) # => 4 ; arr is now [3,5] # Concatenate lists with append! b = [1,2,3] append!(a,b) # Now a is [1, 2, 3, 4, 5, 1, 2, 3] # Check for existence in a list with in -in(1, a) #=> true +in(1, a) # => true # Examine the length with length -length(a) #=> 8 +length(a) # => 8 # Tuples are immutable. -tup = (1, 2, 3) #=> (1,2,3) # an (Int64,Int64,Int64) tuple. -tup[1] #=> 1 +tup = (1, 2, 3) # => (1,2,3) # an (Int64,Int64,Int64) tuple. +tup[1] # => 1 try: - tup[1] = 3 #=> ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) + tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) catch e println(e) end # Many list functions also work on tuples -length(tup) #=> 3 -tup[1:2] #=> (1,2) -in(2, tup) #=> true +length(tup) # => 3 +tup[1:2] # => (1,2) +in(2, tup) # => true # You can unpack tuples into variables -a, b, c = (1, 2, 3) #=> (1,2,3) # a is now 1, b is now 2 and c is now 3 +a, b, c = (1, 2, 3) # => (1,2,3) # a is now 1, b is now 2 and c is now 3 # Tuples are created even if you leave out the parentheses -d, e, f = 4, 5, 6 #=> (4,5,6) +d, e, f = 4, 5, 6 # => (4,5,6) # A 1-element tuple is distinct from the value it contains -(1,) == 1 #=> false -(1) == 1 #=> true +(1,) == 1 # => false +(1) == 1 # => true # Look how easy it is to swap two values -e, d = d, e #=> (5,4) # d is now 5 and e is now 4 +e, d = d, e # => (5,4) # d is now 5 and e is now 4 # Dictionaries store mappings -empty_dict = Dict() #=> Dict{Any,Any}() +empty_dict = Dict() # => Dict{Any,Any}() # You can create a dictionary using a literal filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3] # => Dict{ASCIIString,Int64} # Look up values with [] -filled_dict["one"] #=> 1 +filled_dict["one"] # => 1 # Get all keys keys(filled_dict) -#=> KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) # Note - dictionary keys are not sorted or in the order you inserted them. # Get all values values(filled_dict) -#=> ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) # Note - Same as above regarding key ordering. # Check for existence of keys in a dictionary with in, haskey -in(("one", 1), filled_dict) #=> true -in(("two", 3), filled_dict) #=> false -haskey(filled_dict, "one") #=> true -haskey(filled_dict, 1) #=> false +in(("one", 1), filled_dict) # => true +in(("two", 3), filled_dict) # => false +haskey(filled_dict, "one") # => true +haskey(filled_dict, 1) # => false # Trying to look up a non-existant key will raise an error try - filled_dict["four"] #=> ERROR: key not found: four in getindex at dict.jl:489 + filled_dict["four"] # => ERROR: key not found: four in getindex at dict.jl:489 catch e println(e) end # Use the get method to avoid that error by providing a default value # get(dictionary,key,default_value) -get(filled_dict,"one",4) #=> 1 -get(filled_dict,"four",4) #=> 4 +get(filled_dict,"one",4) # => 1 +get(filled_dict,"four",4) # => 4 # Use Sets to represent collections of unordered, unique values -empty_set = Set() #=> Set{Any}() +empty_set = Set() # => Set{Any}() # Initialize a set with values -filled_set = Set(1,2,2,3,4) #=> Set{Int64}(1,2,3,4) +filled_set = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4) # Add more values to a set -push!(filled_set,5) #=> Set{Int64}(5,4,2,3,1) +push!(filled_set,5) # => Set{Int64}(5,4,2,3,1) # Check if the values are in the set -in(2, filled_set) #=> true -in(10, filled_set) #=> false +in(2, filled_set) # => true +in(10, filled_set) # => false # There are functions for set intersection, union, and difference. -other_set = Set(3, 4, 5, 6) #=> Set{Int64}(6,4,5,3) -intersect(filled_set, other_set) #=> Set{Int64}(3,4,5) -union(filled_set, other_set) #=> Set{Int64}(1,2,3,4,5,6) -setdiff(Set(1,2,3,4),Set(2,3,5)) #=> Set{Int64}(1,4) +other_set = Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3) +intersect(filled_set, other_set) # => Set{Int64}(3,4,5) +union(filled_set, other_set) # => Set{Int64}(1,2,3,4,5,6) +setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4) #################################################### @@ -306,7 +309,7 @@ elseif some_var < 10 # This elseif clause is optional. else # The else clause is optional too. println("some_var is indeed 10.") end -#=> prints "some var is smaller than 10" +# => prints "some var is smaller than 10" # For loops iterate over iterables. @@ -363,7 +366,7 @@ try catch e println("caught it $e") end -#=> caught it ErrorException("help") +# => caught it ErrorException("help") #################################################### @@ -381,7 +384,7 @@ function add(x, y) x + y end -add(5, 6) #=> 11 after printing out "x is 5 and y is 6" +add(5, 6) # => 11 after printing out "x is 5 and y is 6" # You can define functions that take a variable number of # positional arguments @@ -389,20 +392,20 @@ function varargs(args...) return args # use the keyword return to return anywhere in the function end -#=> varargs (generic function with 1 method) +# => varargs (generic function with 1 method) -varargs(1,2,3) #=> (1,2,3) +varargs(1,2,3) # => (1,2,3) # The ... is called a splat. # We just used it in a function definition. # It can also be used in a fuction call, # where it will splat an Array or Tuple's contents into the argument list. -Set([1,2,3]) #=> Set{Array{Int64,1}}([1,2,3]) # produces a Set of Arrays -Set([1,2,3]...) #=> Set{Int64}(1,2,3) # this is equivalent to Set(1,2,3) +Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # produces a Set of Arrays +Set([1,2,3]...) # => Set{Int64}(1,2,3) # this is equivalent to Set(1,2,3) -x = (1,2,3) #=> (1,2,3) -Set(x) #=> Set{(Int64,Int64,Int64)}((1,2,3)) # a Set of Tuples -Set(x...) #=> Set{Int64}(2,3,1) +x = (1,2,3) # => (1,2,3) +Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # a Set of Tuples +Set(x...) # => Set{Int64}(2,3,1) # You can define functions with optional positional arguments @@ -410,12 +413,12 @@ function defaults(a,b,x=5,y=6) return "$a $b and $x $y" end -defaults('h','g') #=> "h g and 5 6" -defaults('h','g','j') #=> "h g and j 6" -defaults('h','g','j','k') #=> "h g and j k" +defaults('h','g') # => "h g and 5 6" +defaults('h','g','j') # => "h g and j 6" +defaults('h','g','j','k') # => "h g and j k" try - defaults('h') #=> ERROR: no method defaults(Char,) - defaults() #=> ERROR: no methods defaults() + defaults('h') # => ERROR: no method defaults(Char,) + defaults() # => ERROR: no methods defaults() catch e println(e) end @@ -425,9 +428,9 @@ function keyword_args(;k1=4,name2="hello") # note the ; return ["k1"=>k1,"name2"=>name2] end -keyword_args(name2="ness") #=> ["name2"=>"ness","k1"=>4] -keyword_args(k1="mine") #=> ["k1"=>"mine","name2"=>"hello"] -keyword_args() #=> ["name2"=>"hello","k1"=>4] +keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4] +keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"] +keyword_args() # => ["name2"=>"hello","k1"=>4] # You can combine all kinds of arguments in the same function function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo") @@ -451,7 +454,7 @@ function create_adder(x) end # This is "stabby lambda syntax" for creating anonymous functions -(x -> x > 2)(3) #=> true +(x -> x > 2)(3) # => true # This function is identical to create_adder implementation above. function create_adder(x) @@ -467,16 +470,16 @@ function create_adder(x) end add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 # There are built-in higher order functions -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(x -> x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +map(add_10, [1,2,3]) # => [11, 12, 13] +filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7] # We can use list comprehensions for nicer maps -[add_10(i) for i=[1, 2, 3]] #=> [11, 12, 13] -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13] +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] #################################################### ## 5. Types @@ -485,11 +488,11 @@ filter(x -> x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] # Julia has a type system. # Every value has a type; variables do not have types themselves. # You can use the `typeof` function to get the type of a value. -typeof(5) #=> Int64 +typeof(5) # => Int64 # Types are first-class values -typeof(Int64) #=> DataType -typeof(DataType) #=> DataType +typeof(Int64) # => DataType +typeof(DataType) # => DataType # DataType is the type that represents types, including itself. # Types are used for documentation, optimizations, and dispatch. @@ -510,10 +513,10 @@ end # The default constructor's arguments are the properties # of the type, in the order they are listed in the definition -tigger = Tiger(3.5,"orange") #=> Tiger(3.5,"orange") +tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange") # The type doubles as the constructor function for values of that type -sherekhan = typeof(tigger)(5.6,"fire") #=> Tiger(5.6,"fire") +sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire") # These struct-style types are called concrete types # They can be instantiated, but cannot have subtypes. @@ -524,23 +527,23 @@ abstract Cat # just a name and point in the type hierarchy # Abstract types cannot be instantiated, but can have subtypes. # For example, Number is an abstract type -subtypes(Number) #=> 6-element Array{Any,1}: +subtypes(Number) # => 6-element Array{Any,1}: # Complex{Float16} # Complex{Float32} # Complex{Float64} # Complex{T<:Real} # ImaginaryUnit # Real -subtypes(Cat) #=> 0-element Array{Any,1} +subtypes(Cat) # => 0-element Array{Any,1} # Every type has a super type; use the `super` function to get it. -typeof(5) #=> Int64 -super(Int64) #=> Signed -super(Signed) #=> Real -super(Real) #=> Number -super(Number) #=> Any -super(super(Signed)) #=> Number -super(Any) #=> Any +typeof(5) # => Int64 +super(Int64) # => Signed +super(Signed) # => Real +super(Real) # => Number +super(Number) # => Any +super(super(Signed)) # => Number +super(Any) # => Any # All of these type, except for Int64, are abstract. # <: is the subtyping operator @@ -588,23 +591,23 @@ function meow(animal::Tiger) end # Testing the meow function -meow(tigger) #=> "rawwr" -meow(Lion("brown","ROAAR")) #=> "ROAAR" -meow(Panther()) #=> "grrr" +meow(tigger) # => "rawwr" +meow(Lion("brown","ROAAR")) # => "ROAAR" +meow(Panther()) # => "grrr" # Review the local type hierarchy -issubtype(Tiger,Cat) #=> false -issubtype(Lion,Cat) #=> true -issubtype(Panther,Cat) #=> true +issubtype(Tiger,Cat) # => false +issubtype(Lion,Cat) # => true +issubtype(Panther,Cat) # => true # Defining a function that takes Cats function pet_cat(cat::Cat) println("The cat says $(meow(cat))") end -pet_cat(Lion("42")) #=> prints "The cat says 42" +pet_cat(Lion("42")) # => prints "The cat says 42" try - pet_cat(tigger) #=> ERROR: no method pet_cat(Tiger,) + pet_cat(tigger) # => ERROR: no method pet_cat(Tiger,) catch e println(e) end @@ -617,31 +620,31 @@ end function fight(t::Tiger,c::Cat) println("The $(t.coatcolor) tiger wins!") end -#=> fight (generic function with 1 method) +# => fight (generic function with 1 method) -fight(tigger,Panther()) #=> prints The orange tiger wins! -fight(tigger,Lion("ROAR")) #=> prints The orange tiger wins! +fight(tigger,Panther()) # => prints The orange tiger wins! +fight(tigger,Lion("ROAR")) # => prints The orange tiger wins! # Let's change the behavior when the Cat is specifically a Lion fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!") -#=> fight (generic function with 2 methods) +# => fight (generic function with 2 methods) -fight(tigger,Panther()) #=> prints The orange tiger wins! -fight(tigger,Lion("ROAR")) #=> prints The green-maned lion wins! +fight(tigger,Panther()) # => prints The orange tiger wins! +fight(tigger,Lion("ROAR")) # => prints The green-maned lion wins! # We don't need a Tiger in order to fight fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))") -#=> fight (generic function with 3 methods) +# => fight (generic function with 3 methods) -fight(Lion("balooga!"),Panther()) #=> prints The victorious cat says grrr +fight(Lion("balooga!"),Panther()) # => prints The victorious cat says grrr try - fight(Panther(),Lion("RAWR")) #=> ERROR: no method fight(Panther,Lion) + fight(Panther(),Lion("RAWR")) # => ERROR: no method fight(Panther,Lion) catch end # Also let the cat go first fight(c::Cat,l::Lion) = println("The cat beats the Lion") -#=> Warning: New definition +# => Warning: New definition # fight(Cat,Lion) at none:1 # is ambiguous with # fight(Lion,Cat) at none:2. @@ -651,11 +654,11 @@ fight(c::Cat,l::Lion) = println("The cat beats the Lion") #fight (generic function with 4 methods) # This warning is because it's unclear which fight will be called in: -fight(Lion("RAR"),Lion("brown","rarrr")) #=> prints The victorious cat says rarrr +fight(Lion("RAR"),Lion("brown","rarrr")) # => prints The victorious cat says rarrr # The result may be different in other versions of Julia fight(l::Lion,l2::Lion) = println("The lions come to a tie") -fight(Lion("RAR"),Lion("brown","rarrr")) #=> prints The lions come to a tie +fight(Lion("RAR"),Lion("brown","rarrr")) # => prints The lions come to a tie # Under the hood diff --git a/livescript.html.markdown b/livescript.html.markdown index 5fd61f49..429b91cb 100644 --- a/livescript.html.markdown +++ b/livescript.html.markdown @@ -23,7 +23,7 @@ Feedback is always welcome, so feel free to reach me over at ```coffeescript -# Just like its CoffeeScript cousin, LiveScript uses hash symbols for +# Just like its CoffeeScript cousin, LiveScript uses number symbols for # single-line comments. /* diff --git a/matlab.html.markdown b/matlab.html.markdown index 15ff2303..9baefe68 100644 --- a/matlab.html.markdown +++ b/matlab.html.markdown @@ -181,7 +181,7 @@ size(A) % ans = 3 3 A(1, :) =[] % Delete the first row of the matrix -A' % Hermitian transpose the matrix +ctranspose(A) % Hermitian transpose the matrix % (the transpose, followed by taking complex conjugate of each element) transpose(A) % Transpose the matrix, without taking complex conjugate diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 0f0165ec..772e72ca 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -249,14 +249,17 @@ int main (int argc, const char * argv[]) // Your statements here @throw [NSException exceptionWithName:@"FileNotFoundException" reason:@"File Not Found on System" userInfo:nil]; - } @catch (NSException * e) + } @catch (NSException * e) // use: @catch (id exceptionName) to catch all objects. { NSLog(@"Exception: %@", e); } @finally { - NSLog(@"Finally"); + NSLog(@"Finally. Time to clean up."); } // => prints "Exception: File Not Found on System" - // "Finally" + // "Finally. Time to clean up." + + // NSError objects are useful for function arguments to populate on user mistakes. + NSError *error = [NSError errorWithDomain:@"Invalid email." code:4 userInfo:nil]; /////////////////////////////////////// // Objects @@ -594,7 +597,7 @@ int main (int argc, const char * argv[]) { // A protocol declares methods that can be implemented by any class. // Protocols are not classes themselves. They simply define an interface // that other objects are responsible for implementing. - // @protocol filename: "CarUtilities.h" +// @protocol filename: "CarUtilities.h" @protocol CarUtilities <NSObject> // <NSObject> => Name of another protocol this protocol includes. @property BOOL engineOn; // Adopting class must @synthesize all defined @properties and - (void)turnOnEngine; // all defined methods. @@ -647,6 +650,7 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { - (void)beNiceToBrother:(id <Brother>)brother; @end + // See the problem is that Sister relies on Brother, and Brother relies on Sister. #import "Sister.h" @@ -658,6 +662,36 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { @end + +/////////////////////////////////////// +// Blocks +/////////////////////////////////////// +// Blocks are statements of code, just like a function, that are able to be used as data. +// Below is a simple block with an integer argument that returns the argument plus 4. +int (^addUp)(int n); // Declare a variable to store the block. +void (^noParameterBlockVar)(void); // Example variable declaration of block with no arguments. +// Blocks have access to variables in the same scope. But the variables are readonly and the +// value passed to the block is the value of the variable when the block is created. +int outsideVar = 17; // If we edit outsideVar after declaring addUp, outsideVar is STILL 17. +__block long mutableVar = 3; // __block makes variables writable to blocks, unlike outsideVar. +addUp = ^(int n) { // Remove (int n) to have a block that doesn't take in any parameters. + NSLog(@"You may have as many lines in a block as you would like."); + NSSet *blockSet; // Also, you can declare local variables. + mutableVar = 32; // Assigning new value to __block variable. + return n + outsideVar; // Return statements are optional. +} +int addUp = add(10 + 16); // Calls block code with arguments. +// Blocks are often used as arguments to functions to be called later, or for callbacks. +@implementation BlockExample : NSObject + + - (void)runBlock:(void (^)(NSString))block { + NSLog(@"Block argument returns nothing and takes in a NSString object."); + block(@"Argument given to block to execute."); // Calling block. + } + + @end + + /////////////////////////////////////// // Memory Management /////////////////////////////////////// diff --git a/perl.html.markdown b/perl.html.markdown index ad9155e4..da2e0cdf 100644 --- a/perl.html.markdown +++ b/perl.html.markdown @@ -12,7 +12,7 @@ Perl 5 is a highly capable, feature-rich programming language with over 25 years Perl 5 runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects. ```perl -# Single line comments start with a hash. +# Single line comments start with a number symbol. #### Perl variable types diff --git a/python.html.markdown b/python.html.markdown index 908a0638..210c9619 100644 --- a/python.html.markdown +++ b/python.html.markdown @@ -16,7 +16,9 @@ Note: This article applies to Python 2.7 specifically, but should be applicable to Python 2.x. Look for another tour of Python 3 soon! ```python -# Single line comments start with a hash. + +# Single line comments start with a number symbol. + """ Multiline strings can be written using three "'s, and are often used as comments @@ -27,60 +29,60 @@ to Python 2.x. Look for another tour of Python 3 soon! #################################################### # You have numbers -3 #=> 3 +3 # => 3 # Math is what you would expect -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7 # Division is a bit tricky. It is integer division and floors the results # automatically. -5 / 2 #=> 2 +5 / 2 # => 2 # To fix division we need to learn about floats. 2.0 # This is a float -11.0 / 4.0 #=> 2.75 ahhh...much better +11.0 / 4.0 # => 2.75 ahhh...much better # Enforce precedence with parentheses -(1 + 3) * 2 #=> 8 +(1 + 3) * 2 # => 8 # Boolean values are primitives True False # negate with not -not True #=> False -not False #=> True +not True # => False +not False # => True # Equality is == -1 == 1 #=> True -2 == 1 #=> False +1 == 1 # => True +2 == 1 # => False # Inequality is != -1 != 1 #=> False -2 != 1 #=> True +1 != 1 # => False +2 != 1 # => True # More comparisons -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True # Comparisons can be chained! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +1 < 2 < 3 # => True +2 < 3 < 2 # => False # Strings are created with " or ' "This is a string." 'This is also a string.' # Strings can be added too! -"Hello " + "world!" #=> "Hello world!" +"Hello " + "world!" # => "Hello world!" # A string can be treated like a list of characters -"This is a string"[0] #=> 'T' +"This is a string"[0] # => 'T' # % can be used to format strings, like this: "%s can be %s" % ("strings", "interpolated") @@ -92,12 +94,12 @@ not False #=> True "{name} wants to eat {food}".format(name="Bob", food="lasagna") # None is an object -None #=> None +None # => None # Don't use the equality "==" symbol to compare objects to None # Use "is" instead -"etc" is None #=> False -None is None #=> True +"etc" is None # => False +None is None # => True # The 'is' operator tests for object identity. This isn't # very useful when dealing with primitive values, but is @@ -105,8 +107,8 @@ None is None #=> True # None, 0, and empty strings/lists all evaluate to False. # All other values are True -bool(0) #=> False -bool("") #=> False +bool(0) # => False +bool("") # => False #################################################### @@ -121,14 +123,14 @@ print "I'm also Python!" # No need to declare variables before assigning to them. some_var = 5 # Convention is to use lower_case_with_underscores -some_var #=> 5 +some_var # => 5 # Accessing a previously unassigned variable is an exception. # See Control Flow to learn more about exception handling. some_other_var # Raises a name error # if can be used as an expression -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +"yahoo!" if 3 > 2 else 2 # => "yahoo!" # Lists store sequences li = [] @@ -136,63 +138,63 @@ li = [] other_li = [4, 5, 6] # Add stuff to the end of a list with append -li.append(1) #li is now [1] -li.append(2) #li is now [1, 2] -li.append(4) #li is now [1, 2, 4] -li.append(3) #li is now [1, 2, 4, 3] +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] # Remove from the end with pop -li.pop() #=> 3 and li is now [1, 2, 4] +li.pop() # => 3 and li is now [1, 2, 4] # Let's put it back li.append(3) # li is now [1, 2, 4, 3] again. # Access a list like you would any array -li[0] #=> 1 +li[0] # => 1 # Look at the last element -li[-1] #=> 3 +li[-1] # => 3 # Looking out of bounds is an IndexError -li[4] # Raises an IndexError +li[4] # Raises an IndexError # You can look at ranges with slice syntax. # (It's a closed/open range for you mathy types.) -li[1:3] #=> [2, 4] +li[1:3] # => [2, 4] # Omit the beginning -li[2:] #=> [4, 3] +li[2:] # => [4, 3] # Omit the end -li[:3] #=> [1, 2, 4] +li[:3] # => [1, 2, 4] # Select every second entry -li[::2] #=>[1,4] +li[::2] # =>[1, 4] # Revert the list -li[::-1] #=> [3, 4, 2, 1] +li[::-1] # => [3, 4, 2, 1] # Use any combination of these to make advanced slices # li[start:end:step] # Remove arbitrary elements from a list with "del" -del li[2] # li is now [1, 2, 3] +del li[2] # li is now [1, 2, 3] # You can add lists -li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li and other_li is left alone +li + other_li # => [1, 2, 3, 4, 5, 6] - Note: values for li and for other_li are not modified. # Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] # Check for existence in a list with "in" -1 in li #=> True +1 in li # => True # Examine the length with "len()" -len(li) #=> 6 +len(li) # => 6 # Tuples are like lists but are immutable. tup = (1, 2, 3) -tup[0] #=> 1 +tup[0] # => 1 tup[0] = 3 # Raises a TypeError # You can do all those list thingies on tuples too -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True # You can unpack tuples (or lists) into variables a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 @@ -208,60 +210,60 @@ empty_dict = {} filled_dict = {"one": 1, "two": 2, "three": 3} # Look up values with [] -filled_dict["one"] #=> 1 +filled_dict["one"] # => 1 # Get all keys as a list with "keys()" -filled_dict.keys() #=> ["three", "two", "one"] +filled_dict.keys() # => ["three", "two", "one"] # Note - Dictionary key ordering is not guaranteed. # Your results might not match this exactly. # Get all values as a list with "values()" -filled_dict.values() #=> [3, 2, 1] +filled_dict.values() # => [3, 2, 1] # Note - Same as above regarding key ordering. # Check for existence of keys in a dictionary with "in" -"one" in filled_dict #=> True -1 in filled_dict #=> False +"one" in filled_dict # => True +1 in filled_dict # => False # Looking up a non-existing key is a KeyError -filled_dict["four"] # KeyError +filled_dict["four"] # KeyError # Use "get()" method to avoid the KeyError -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None # The get method supports a default argument when the value is missing -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 # "setdefault()" inserts into a dictionary only if the given key isn't present -filled_dict.setdefault("five", 5) #filled_dict["five"] is set to 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5 +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 # Sets store ... well sets empty_set = set() # Initialize a "set()" with a bunch of values -some_set = set([1,2,2,3,4]) # some_set is now set([1, 2, 3, 4]) +some_set = set([1, 2, 2, 3, 4]) # some_set is now set([1, 2, 3, 4]) # Since Python 2.7, {} can be used to declare a set -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} # Add more items to a set -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} # Do set intersection with & other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +filled_set & other_set # => {3, 4, 5} # Do set union with | -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +filled_set | other_set # => {1, 2, 3, 4, 5, 6} # Do set difference with - -{1,2,3,4} - {2,3,5} #=> {1, 4} +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} # Check for existence in a set with in -2 in filled_set #=> True -10 in filled_set #=> False +2 in filled_set # => True +10 in filled_set # => False #################################################### @@ -337,17 +339,18 @@ def add(x, y): return x + y # Return values with a return statement # Calling functions with parameters -add(5, 6) #=> prints out "x is 5 and y is 6" and returns 11 +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 # Another way to call functions is with keyword arguments add(y=6, x=5) # Keyword arguments can arrive in any order. + # You can define functions that take a variable number of # positional arguments def varargs(*args): return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3) # => (1, 2, 3) # You can define functions that take a variable number of @@ -356,7 +359,8 @@ def keyword_args(**kwargs): return kwargs # Let's call it to see what happens -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + # You can do both at once, if you like def all_the_args(*args, **kwargs): @@ -372,9 +376,10 @@ all_the_args(1, 2, a=3, b=4) prints: # Use * to expand tuples and use ** to expand kwargs. args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) +all_the_args(*args) # equivalent to foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) + # Python has first class functions def create_adder(x): @@ -383,23 +388,24 @@ def create_adder(x): return adder add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 # There are also anonymous functions -(lambda x: x > 2)(3) #=> True +(lambda x: x > 2)(3) # => True # There are built-in higher order functions -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +map(add_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] # We can use list comprehensions for nice maps and filters -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### ## 5. Classes #################################################### + # We subclass from object to get a class. class Human(object): @@ -413,7 +419,7 @@ class Human(object): # An instance method. All methods take "self" as the first argument def say(self, msg): - return "%s: %s" % (self.name, msg) + return "%s: %s" % (self.name, msg) # A class method is shared among all instances # They are called with the calling class as the first argument @@ -432,18 +438,18 @@ i = Human(name="Ian") print(i.say("hi")) # prints out "Ian: hi" j = Human("Joel") -print(j.say("hello")) #prints out "Joel: hello" +print(j.say("hello")) # prints out "Joel: hello" # Call our class method -i.get_species() #=> "H. sapiens" +i.get_species() # => "H. sapiens" # Change the shared attribute Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" # Call the static method -Human.grunt() #=> "*grunt*" +Human.grunt() # => "*grunt*" #################################################### @@ -452,12 +458,12 @@ Human.grunt() #=> "*grunt*" # You can import modules import math -print(math.sqrt(16) )#=> 4 +print(math.sqrt(16)) # => 4 # You can get specific functions from a module from math import ceil, floor -print(ceil(3.7)) #=> 4.0 -print(floor(3.7)) #=> 3.0 +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 # You can import all functions from a module. # Warning: this is not recommended @@ -465,7 +471,7 @@ from math import * # You can shorten module names import math as m -math.sqrt(16) == m.sqrt(16) #=> True +math.sqrt(16) == m.sqrt(16) # => True # Python modules are just ordinary python files. You # can write your own, and import them. The name of the @@ -486,10 +492,12 @@ def double_numbers(iterable): for i in iterable: yield i + i -# generator creates the value on the fly -# instead of generating and returning all values at once it creates one in each iteration -# this means values bigger than 15 wont be processed in double_numbers -# note range is a generator too, creating a list 1-900000000 would take lot of time to be made +# A generator creates values on the fly. +# Instead of generating and returning all values at once it creates one in each +# iteration. This means values bigger than 15 wont be processed in +# double_numbers. +# Note range is a generator too. Creating a list 1-900000000 would take lot of +# time to be made _range = range(1, 900000000) # will double all numbers until a result >=30 found for i in double_numbers(_range): @@ -500,7 +508,8 @@ for i in double_numbers(_range): # Decorators # in this example beg wraps say -# Beg will call say. If say_please is True then it will change the returned message +# Beg will call say. If say_please is True then it will change the returned +# message from functools import wraps @@ -523,8 +532,6 @@ def say(say_please=False): print(say()) # Can you buy me a beer? print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( - - ``` ## Ready For More? diff --git a/python3.html.markdown b/python3.html.markdown new file mode 100644 index 00000000..54f425ed --- /dev/null +++ b/python3.html.markdown @@ -0,0 +1,578 @@ +--- +language: python3 +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] +filename: learnpython3.py +--- + +Python was created by Guido Van Rossum in the early 90's. It is now one of the most popular +languages in existence. I fell in love with Python for its syntactic clarity. It's basically +executable pseudocode. + +Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service] + +Note: This article applies to Python 3 specifically. Check out the other tutorial if you want to learn the old Python 2.7 + +```python + +# Single line comments start with a number symbol. + +""" Multiline strings can be written + using three "'s, and are often used + as comments +""" + +#################################################### +## 1. Primitive Datatypes and Operators +#################################################### + +# You have numbers +3 # => 3 + +# Math is what you would expect +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 + +# Except division which returns floats by default +35 / 5 # => 7.0 + +# When you use a float, results are floats +3 * 2.0 # => 6.0 + +# Enforce precedence with parentheses +(1 + 3) * 2 # => 8 + + +# Boolean values are primitives +True +False + +# negate with not +not True # => False +not False # => True + + +# Equality is == +1 == 1 # => True +2 == 1 # => False + +# Inequality is != +1 != 1 # => False +2 != 1 # => True + +# More comparisons +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Comparisons can be chained! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + + +# Strings are created with " or ' +"This is a string." +'This is also a string.' + +# Strings can be added too! But try not to do this. +"Hello " + "world!" # => "Hello world!" + +# A string can be treated like a list of characters +"This is a string"[0] # => 'T' + +# .format can be used to format strings, like this: +"{} can be {}".format("strings", "interpolated") + +# You can repeat the formatting arguments to save some typing. +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") #=> "Jack be nimble, Jack be quick, Jack jump over the candle stick" +# You can use keywords if you don't want to count. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna" + + +# None is an object +None # => None + +# Don't use the equality "==" symbol to compare objects to None +# Use "is" instead. This checks for equality of object identity. +"etc" is None # => False +None is None # => True + +# None, 0, and empty strings/lists/dicts all evaluate to False. +# All other values are True +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False + + +#################################################### +## 2. Variables and Collections +#################################################### + +# Python has a print function +print("I'm Python. Nice to meet you!") + +# No need to declare variables before assigning to them. Convention is to use lower_case_with_underscores +some_var = 5 +some_var # => 5 + +# Accessing a previously unassigned variable is an exception. +# See Control Flow to learn more about exception handling. +some_unknown_var # Raises a NameError + +# Lists store sequences +li = [] +# You can start with a prefilled list +other_li = [4, 5, 6] + +# Add stuff to the end of a list with append +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] +# Remove from the end with pop +li.pop() # => 3 and li is now [1, 2, 4] +# Let's put it back +li.append(3) # li is now [1, 2, 4, 3] again. + +# Access a list like you would any array +li[0] # => 1 +# Look at the last element +li[-1] # => 3 + +# Looking out of bounds is an IndexError +li[4] # Raises an IndexError + +# You can look at ranges with slice syntax. +# (It's a closed/open range for you mathy types.) +li[1:3] # => [2, 4] +# Omit the beginning +li[2:] # => [4, 3] +# Omit the end +li[:3] # => [1, 2, 4] +# Select every second entry +li[::2] # =>[1, 4] +# Revert the list +li[::-1] # => [3, 4, 2, 1] +# Use any combination of these to make advanced slices +# li[start:end:step] + +# Remove arbitrary elements from a list with "del" +del li[2] # li is now [1, 2, 3] + +# You can add lists +li + other_li # => [1, 2, 3, 4, 5, 6] - Note: values for li and for other_li are not modified. + +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# Check for existence in a list with "in" +1 in li # => True + +# Examine the length with "len()" +len(li) # => 6 + + +# Tuples are like lists but are immutable. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Raises a TypeError + +# You can do all those list thingies on tuples too +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# You can unpack tuples (or lists) into variables +a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 +# Tuples are created by default if you leave out the parentheses +d, e, f = 4, 5, 6 +# Now look how easy it is to swap two values +e, d = d, e # d is now 5 and e is now 4 + + +# Dictionaries store mappings +empty_dict = {} +# Here is a prefilled dictionary +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Look up values with [] +filled_dict["one"] # => 1 + +# Get all keys as a list with "keys()". We need to wrap the call in list() because we are getting back an iterable. We'll talk about those later. +list(filled_dict.keys()) # => ["three", "two", "one"] +# Note - Dictionary key ordering is not guaranteed. +# Your results might not match this exactly. + +# Get all values as a list with "values()". Once again we need to wrap it in list() to get it out of the iterable. +list(filled_dict.values()) # => [3, 2, 1] +# Note - Same as above regarding key ordering. + +# Check for existence of keys in a dictionary with "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# Looking up a non-existing key is a KeyError +filled_dict["four"] # KeyError + +# Use "get()" method to avoid the KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# The get method supports a default argument when the value is missing +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# "setdefault()" inserts into a dictionary only if the given key isn't present +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 + +# Remove keys from a dictionary with del +del filled_dict["one"] # Removes the key "one" from filled dict + + +# Sets store ... well sets +empty_set = set() +# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry. +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} + +# Add more items to a set +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} + +# Do set intersection with & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# Do set union with | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Do set difference with - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Check for existence in a set with in +2 in filled_set # => True +10 in filled_set # => False + + +#################################################### +## 3. Control Flow and Iterables +#################################################### + +# Let's just make a variable +some_var = 5 + +# Here is an if statement. Indentation is significant in python! +# prints "some_var is smaller than 10" +if some_var > 10: + print("some_var is totally bigger than 10.") +elif some_var < 10: # This elif clause is optional. + print("some_var is smaller than 10.") +else: # This is optional too. + print("some_var is indeed 10.") + + +""" +For loops iterate over lists +prints: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # You can use % to interpolate formatted strings + print("{} is a mammal".format(animal)) + +""" +"range(number)" returns a list of numbers +from zero to the given number +prints: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +While loops go until a condition is no longer met. +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Shorthand for x = x + 1 + +# Handle exceptions with a try/except block +try: + # Use "raise" to raise an error + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass is just a no-op. Usually you would do recovery here. + + +# Python's offers a fundamental abstraction called the Iterable. +# An iterable is an object that can be treated as a sequence. +# The object returned the range function, is an iterable. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) #=> range(1,10). This is an object that implements our Iterable interface + +i We can loop over it. +for i in our_iterable: + print(i) # Prints one, two, three + +# However we cannot address elements by index. +our_iterable[1] # Raises a TypeError + +# An iterable is an object that knows how to create an iterator. +our_iterator = iter(our_iterable) + +# Our iterator is an object that can remember the state as we traverse through it. +# We get the next object by calling the __next__ function. +our_iterator.__next__() #=> "one" + +# It maintains state as we call __next__. +our_iterator.__next__() #=> "two" +our_iterator.__next__() #=> "three" + +# After the iterator has returned all of its data, it gives you a StopIterator Exception +our_iterator.__next__() # Raises StopIteration + +# You can grab all the elements of an iterator by calling list() on it. +list(filled_dict.keys()) #=> Returns ["one", "two", "three"] + + + +#################################################### +## 4. Functions +#################################################### + +# Use "def" to create new functions +def add(x, y): + print("x is %s and y is %s" % (x, y)) + return x + y # Return values with a return statement + +# Calling functions with parameters +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 + +# Another way to call functions is with keyword arguments +add(y=6, x=5) # Keyword arguments can arrive in any order. + + +# You can define functions that take a variable number of +# positional arguments +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + + +# You can define functions that take a variable number of +# keyword arguments, as well +def keyword_args(**kwargs): + return kwargs + +# Let's call it to see what happens +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# You can do both at once, if you like +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# When calling functions, you can do the opposite of args/kwargs! +# Use * to expand tuples and use ** to expand kwargs. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalent to foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) + + +# Python has first class functions +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# There are also anonymous functions +(lambda x: x > 2)(3) # => True + +# TODO - Fix for iterables +# There are built-in higher order functions +map(add_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# We can use list comprehensions for nice maps and filters +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +#################################################### +## 5. Classes +#################################################### + + +# We subclass from object to get a class. +class Human(object): + + # A class attribute. It is shared by all instances of this class + species = "H. sapiens" + + # Basic initializer + def __init__(self, name): + # Assign the argument to the instance's name attribute + self.name = name + + # An instance method. All methods take "self" as the first argument + def say(self, msg): + return "{name}: {message}" % (name=self.name, message=msg) + + # A class method is shared among all instances + # They are called with the calling class as the first argument + @classmethod + def get_species(cls): + return cls.species + + # A static method is called without a class or instance reference + @staticmethod + def grunt(): + return "*grunt*" + + +# Instantiate a class +i = Human(name="Ian") +print(i.say("hi")) # prints out "Ian: hi" + +j = Human("Joel") +print(j.say("hello")) # prints out "Joel: hello" + +# Call our class method +i.get_species() # => "H. sapiens" + +# Change the shared attribute +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" + +# Call the static method +Human.grunt() # => "*grunt*" + + +#################################################### +## 6. Modules +#################################################### + +# You can import modules +import math +print(math.sqrt(16)) # => 4 + +# You can get specific functions from a module +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# You can import all functions from a module. +# Warning: this is not recommended +from math import * + +# You can shorten module names +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Python modules are just ordinary python files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# defines a module. +import math +dir(math) + + +#################################################### +## 7. Advanced +#################################################### + +# Generators help you make lazy code +def double_numbers(iterable): + for i in iterable: + yield i + i + +# A generator creates values on the fly. +# Instead of generating and returning all values at once it creates one in each +# iteration. This means values bigger than 15 wont be processed in +# double_numbers. +# Note range is a generator too. Creating a list 1-900000000 would take lot of +# time to be made +_range = range(1, 900000000) +# will double all numbers until a result >=30 found +for i in double_numbers(_range): + print(i) + if i >= 30: + break + + +# Decorators +# in this example beg wraps say +# Beg will call say. If say_please is True then it will change the returned +# message +from functools import wraps + + +def beg(_say): + @wraps(_say) + def wrapper(*args, **kwargs): + msg, say_please = _say(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( +``` + +## Ready For More? + +### Free Online + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) + +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) + +### Dead Tree + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/r.html.markdown b/r.html.markdown index 9c17e8ca..ea94ae42 100644 --- a/r.html.markdown +++ b/r.html.markdown @@ -10,7 +10,7 @@ R is a statistical computing language. It has lots of libraries for uploading an ```python -# Comments start with hashtags. +# Comments start with number symbols. # You can't make a multi-line comment per se, # but you can stack multiple comments like so. diff --git a/racket.html.markdown b/racket.html.markdown index eddc00bf..6abc8759 100644 --- a/racket.html.markdown +++ b/racket.html.markdown @@ -196,7 +196,7 @@ my-pet ; => #<dog> (hash-ref m 'd 0) ; => 0 ;; Use `hash-set' to extend an immutable hash table -;; (Returns the extended hash instdead of mutating it) +;; (Returns the extended hash instead of mutating it) (define m2 (hash-set m 'd 4)) m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3)) @@ -224,7 +224,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (define hello-world (lambda () "Hello World")) (hello-world) ; => "Hello World" -;; You can shorten this using the function definition syntatcic sugae: +;; You can shorten this using the function definition syntactic sugar: (define (hello-world2) "Hello World") ;; The () in the above is the list of arguments for the function @@ -496,7 +496,7 @@ vec ; => #(1 2 3 4) ;; 8. Classes and Objects ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Create a class fish% (-% is idomatic for class bindings) +;; Create a class fish% (-% is idiomatic for class bindings) (define fish% (class object% (init size) ; initialization argument @@ -552,7 +552,7 @@ vec ; => #(1 2 3 4) (set! i (add1 i)))) ;; Macros are hygienic, you cannot clobber existing variables! -(define-syntax-rule (swap! x y) ; -! is idomatic for mutation +(define-syntax-rule (swap! x y) ; -! is idiomatic for mutation (let ([tmp x]) (set! x y) (set! y tmp))) diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown index e9892952..ffda01b7 100644 --- a/ru-ru/go-ru.html.markdown +++ b/ru-ru/go-ru.html.markdown @@ -3,8 +3,12 @@ language: Go filename: learngo-ru.go contributors: - ["Sonia Keys", "https://github.com/soniakeys"] + - ["Christopher Bess", "https://github.com/cbess"] + - ["Jesse Johnson", "https://github.com/holocronweaver"] + - ["Quint Guvernator", "https://github.com/qguv"] translators: - ["Artem Medeusheyev", "https://github.com/armed"] + - ["Valery Cherepanov", "https://github.com/qumeric"] lang: ru-ru --- @@ -31,8 +35,9 @@ package main // Import предназначен для указания зависимостей этого файла. import ( "fmt" // Пакет в стандартной библиотеке Go - "net/http" // Да, это web server! + "net/http" // Да, это веб-сервер! "strconv" // Конвертирование типов в строки и обратно + m "math" // Импортировать math под локальным именем m. ) // Объявление функции. Main это специальная функция, служащая точкой входа для @@ -40,7 +45,7 @@ import ( // скобки. func main() { // Println выводит строку в stdout. - // В данном случае фигурирует вызов функции из пакета fmt. + // Данная функция находится в пакете fmt. fmt.Println("Hello world!") // Вызов другой функции из текущего пакета. @@ -55,57 +60,57 @@ func beyondHello() { // Краткое определение := позволяет объявить перменную с автоматической // подстановкой типа из значения. y := 4 - sum, prod := learnMultiple(x, y) // функция возвращает два значения - fmt.Println("sum:", sum, "prod:", prod) // простой вывод + sum, prod := learnMultiple(x, y) // Функция возвращает два значения. + fmt.Println("sum:", sum, "prod:", prod) // Простой вывод. learnTypes() // < y minutes, learn more! } // Функция имеющая входные параметры и возврат нескольких значений. func learnMultiple(x, y int) (sum, prod int) { - return x + y, x * y // возврат двух результатов + return x + y, x * y // Возврат двух значений. } // Некотрые встроенные типы и литералы. func learnTypes() { // Краткое определение переменной говорит само за себя. - s := "Learn Go!" // тип string + s := "Learn Go!" // Тип string. s2 := `"Чистый" строковой литерал -может содержать переносы строк` // тоже тип данных string +может содержать переносы строк` // Тоже тип данных string - // символ не из ASCII. Исходный код Go в кодировке UTF-8. - g := 'Σ' // тип rune, это алиас для типа uint32, содержит юникод символ + // Символ не из ASCII. Исходный код Go в кодировке UTF-8. + g := 'Σ' // тип rune, это алиас для типа uint32, содержит символ юникода. - f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754) - c := 3 + 4i // complex128, внутри себя содержит два float64 + f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754). + c := 3 + 4i // complex128, внутри себя содержит два float64. - // Синтаксис var с инициализациями - var u uint = 7 // беззнаковое, но размер зависит от реализации, как и у int + // Синтаксис var с инициализациями. + var u uint = 7 // Беззнаковое, но размер зависит от реализации, как и у int. var pi float32 = 22. / 7 // Синтаксис приведения типа с кратким определением - n := byte('\n') // byte алиас для uint8 + n := byte('\n') // byte – это алиас для uint8. - // Массивы (Array) имеют фиксированный размер на момент компиляции. - var a4 [4]int // массив из 4-х int, проинициализирован нулями - a3 := [...]int{3, 1, 5} // массив из 3-х int, ручная инициализация + // Массивы имеют фиксированный размер на момент компиляции. + var a4 [4]int // массив из 4-х int, инициализирован нулями. + a3 := [...]int{3, 1, 5} // массив из 3-х int, ручная инициализация. - // Slice имеют динамическую длину. И массивы и slice-ы имеют каждый свои - // преимущества, но slice-ы используются гораздо чаще. - s3 := []int{4, 5, 9} // по сравнению с a3 тут нет троеточия - s4 := make([]int, 4) // выделение памяти для slice из 4-х int (нули) - var d2 [][]float64 // только объявление, память не выделяется - bs := []byte("a slice") // конвертирование строки в slice байтов + // Слайсы (slices) имеют динамическую длину. И массивы, и слайсы имеют свои + // преимущества, но слайсы используются гораздо чаще. + s3 := []int{4, 5, 9} // Сравните с a3. Тут нет троеточия. + s4 := make([]int, 4) // Выделение памяти для слайса из 4-х int (нули). + var d2 [][]float64 // Только объявление, память не выделяется. + bs := []byte("a slice") // Синтаксис приведения типов. - p, q := learnMemory() // объявление p и q как указателей на int. + p, q := learnMemory() // Объявление p и q как указателей на int. fmt.Println(*p, *q) // * извлекает указатель. Печатает два int-а. - // Map как словарь или хеш теблица из других языков является ассоциативным - // массивом с динамически изменяемым размером. + // Map, также как и словарь или хеш из некоторых других языков, является + // ассоциативным массивом с динамически изменяемым размером. m := map[string]int{"three": 3, "four": 4} m["one"] = 1 - delete(m, "three") // встроенная функция, удаляет элемент из map-а. + delete(m, "three") // Встроенная функция, удаляет элемент из map-а. // Неиспользуемые переменные в Go являются ошибкой. // Нижнее подчеркивание позволяет игнорировать такие переменные. @@ -113,79 +118,91 @@ func learnTypes() { // Вывод считается использованием переменной. fmt.Println(s, c, a4, s3, d2, m) - learnFlowControl() // идем далее + learnFlowControl() // Идем дальше. } // У Go есть полноценный сборщик мусора. В нем есть указатели но нет арифметики -// указатеей. Вы можете допустить ошибку с указателем на nil, но не с его -// инкрементацией. +// указателей. Вы можете допустить ошибку с указателем на nil, но не с +// инкрементацией указателя. func learnMemory() (p, q *int) { // Именованные возвращаемые значения p и q являются указателями на int. - p = new(int) // встроенная функция new выделяет память. + p = new(int) // Встроенная функция new выделяет память. // Выделенный int проинициализирован нулем, p больше не содержит nil. - s := make([]int, 20) // Выделение единого блока памяти под 20 int-ов, - s[3] = 7 // назначение одному из них, - r := -2 // опредление еще одной локальной переменной, - return &s[3], &r // амперсанд обозначает получение адреса переменной. + s := make([]int, 20) // Выделение единого блока памяти под 20 int-ов. + s[3] = 7 // Присвоить значение одному из них. + r := -2 // Определить еще одну локальную переменную. + return &s[3], &r // Амперсанд(&) обозначает получение адреса переменной. } -func expensiveComputation() int { - return 1e6 +func expensiveComputation() float64 { + return m.Exp(10) } func learnFlowControl() { - // If-ы всегда требуют наличине фигурных скобок, но круглые скобки - // необязательны. + // If-ы всегда требуют наличине фигурных скобок, но не круглых. if true { fmt.Println("told ya") } // Форматирование кода стандартизировано утилитой "go fmt". if false { - // все тлен + // Будущего нет. } else { - // жизнь прекрасна + // Жизнь прекрасна. } - // Использоване switch на замену нескольким if-else - x := 1 + // Используйте switch вместо нескольких if-else. + x := 42.0 switch x { case 0: case 1: - // case-ы в Go не проваливаются, т.е. break по умолчанию - case 2: - // не выполнится + case 42: + // Case-ы в Go не "проваливаются" (неявный break). + case 43: + // Не выполнится. } // For, как и if не требует круглых скобок - for x := 0; x < 3; x++ { // ++ это операция + // Переменные, объявленные в for и if являются локальными. + for x := 0; x < 3; x++ { // ++ – это операция. fmt.Println("итерация", x) } - // тут x == 1. + // Здесь x == 42. - // For это единственный цикл в Go, но у него несколько форм. - for { // бесконечный цикл - break // не такой уж и бесконечный - continue // не выполнится + // For – это единственный цикл в Go, но у него есть альтернативные формы. + for { // Бесконечный цикл. + break // Не такой уж и бесконечный. + continue // Не выполнится. } // Как и в for, := в if-е означает объявление и присвоение значения y, - // затем проверка y > x. + // проверка y > x происходит после. if y := expensiveComputation(); y > x { x = y } // Функции являются замыканиями. xBig := func() bool { - return x > 100 // ссылается на x, объявленый выше switch. + return x > 10000 // Ссылается на x, объявленый выше switch. } - fmt.Println("xBig:", xBig()) // true (т.к. мы присвоили x = 1e6) - x /= 1e5 // тут х == 10 - fmt.Println("xBig:", xBig()) // теперь false + fmt.Println("xBig:", xBig()) // true (т.к. мы присвоили x = e^10). + x = 1.3e3 // Тут х == 1300 + fmt.Println("xBig:", xBig()) // Теперь false. // Метки, куда же без них, их все любят. goto love love: + learnDefer() // Быстрый обзор важного ключевого слова. learnInterfaces() // О! Интерфейсы, идем далее. } -// Объявление Stringer как интерфейса с одним мметодом, String. +func learnDefer() (ok bool) { + // Отложенные(deferred) выражения выполняются сразу перед тем, как функция + // возвратит значение. + defer fmt.Println("deferred statements execute in reverse (LIFO) order.") + defer fmt.Println("\nThis line is being printed first because") + // defer широко используется для закрытия файлов, чтобы закрывающая файл + // функция находилась близко к открывающей. + return true +} + +// Объявление Stringer как интерфейса с одним методом, String. type Stringer interface { String() string } @@ -196,35 +213,48 @@ type pair struct { } // Объявление метода для типа pair. Теперь pair реализует интерфейс Stringer. -func (p pair) String() string { // p в данном случае называют receiver-ом - // Sprintf - еще одна функция из пакета fmt. +func (p pair) String() string { // p в данном случае называют receiver-ом. + // Sprintf – еще одна функция из пакета fmt. // Обращение к полям p через точку. return fmt.Sprintf("(%d, %d)", p.x, p.y) } func learnInterfaces() { // Синтаксис с фигурными скобками это "литерал структуры". Он возвращает - // проинициализированную структуру, а оператор := присваивает ее в p. + // проинициализированную структуру, а оператор := присваивает её p. p := pair{3, 4} - fmt.Println(p.String()) // вызов метода String у p, типа pair. - var i Stringer // объявление i как типа с интерфейсом Stringer. - i = p // валидно, т.к. pair реализует Stringer. - // Вызов метода String у i, типа Stringer. Вывод такой же что и выше. + fmt.Println(p.String()) // Вызов метода String у переменной p типа pair. + var i Stringer // Объявление i как типа с интерфейсом Stringer. + i = p // Валидно, т.к. pair реализует Stringer. + // Вызов метода String у i типа Stringer. Вывод такой же, что и выше. fmt.Println(i.String()) // Функции в пакете fmt сами всегда вызывают метод String у объектов для // получения строкового представления о них. - fmt.Println(p) // Вывод такой же что и выше. Println вызывает метод String. - fmt.Println(i) // тоже самое + fmt.Println(p) // Вывод такой же, что и выше. Println вызывает метод String. + fmt.Println(i) // Вывод такой же, что и выше. + + learnVariadicParams("Учиться", "учиться", "и еще раз учиться!") +} + +// Функции могут иметь варьируемое количество параметров. +func learnVariadicParams(myStrings ...interface{}) { + // Вывести все параметры с помощью итерации. + for _, param := range myStrings { + fmt.Println("param:", param) + } + + // Передать все варьируемые параметры. + fmt.Println("params:", fmt.Sprintln(myStrings...)) learnErrorHandling() } func learnErrorHandling() { - // Идиома ", ok" служит для обозначения сработало что-то или нет. + // Идиома ", ok" служит для обозначения корректного срабатывания чего-либо. m := map[int]string{3: "three", 4: "four"} if x, ok := m[1]; !ok { // ok будет false, потому что 1 нет в map-е. - fmt.Println("тут никого") + fmt.Println("тут никого нет") } else { fmt.Print(x) // x содержал бы значение, если бы 1 был в map-е. } @@ -237,7 +267,7 @@ func learnErrorHandling() { learnConcurrency() } -// c это тип данных channel (канал), объект для конкуррентного взаимодействия. +// c – это тип данных channel (канал), объект для конкуррентного взаимодействия. func inc(i int, c chan int) { c <- i + 1 // когда channel слева, <- являтся оператором "отправки". } diff --git a/ru-ru/haskell-ru.html.markdown b/ru-ru/haskell-ru.html.markdown new file mode 100644 index 00000000..03e66d05 --- /dev/null +++ b/ru-ru/haskell-ru.html.markdown @@ -0,0 +1,546 @@ +--- +language: haskell +contributors: + - ["Adit Bhargava", "http://adit.io"] +translators: + - ["Aleksey Pirogov", "http://astynax.github.io"] +lang: ru-ru +--- + +Haskell разрабатывался, как чистый функциональный язык программирования, применимый на практике. Язык известен благодаря своей системе типов, и "знаменит" благодаря монадам. [Меня][autor] же Haskell заставляет возвращаться к себе снова и снова именно своей элегантностью и [я][autor] получаю истинное удовольствие, программируя на Haskell. + +```haskell +-- Однострочные комментарии начинаются с двух дефисов +{- Многострочный комментарий +заключается в пару фигурных скобок с дефисами с внутренней стороны. +-} + +------------------------------------------------------- +-- 1. Примитивные типы и простейшие операции над ними +------------------------------------------------------- + +-- Числа объявляются просто +3 -- 3 + +-- Арифметика тоже выглядит вполне ожидаемо +1 + 1 -- 2 +8 - 1 -- 7 +10 * 2 -- 20 +35 / 5 -- 7.0 + +-- Операция деления всегда возвращает действительное число +35 / 4 -- 8.75 + +-- Делим нацело так +35 `div` 4 -- 8 + +-- Булевы значения - тоже примитивные значения +True +False + +-- Булева алгебра +not True -- False +not False -- True +1 == 1 -- True +1 /= 1 -- False +1 < 10 -- True + +-- В примере выше `not`, это функция, принимающая один аргумент. +-- При вызове функции в Haskell список аргументов +-- не нужно заключать в скобки - аргументы просто +-- перечисляются через пробелы сразу после имени функции. +-- Т.о. типичный вызов выглядит так: +-- func arg1 arg2 arg3... +-- Ниже же будет показано, как определять свои функции. + +-- Строки и символы +"Это строка." +'ы' -- а это символ +'Нельзя заключать длинные строки в одинарные кавычки.' -- ошибка! + +-- Строки можно конкатенировать +"Привет" ++ ", Мир!" -- "Привет, Мир!" + +-- При этом строки - это просто списки символов! +"Я - строка!" !! 0 -- 'Я' + + +---------------------------------------------------- +-- Списки и Кортежи +---------------------------------------------------- + +-- Все элементы списка в Haskell +-- должны иметь один и тот же тип. + +-- Эти два списка - эквивалентны: +[1, 2, 3, 4, 5] +[1..5] + +-- Haskell позволяет определять даже бесконечные списки! +[1..] -- список всех натуральных чисел! + +-- Бесконечные списки возможно в Haskell потому, что он "ленив". +-- В Haskell все вычисления производятся тогда и только тогда, +-- когда их результат потребуется. +-- Эта стратегия так и называется - "lazy evaluation". +-- Скажем, если вам нужен тысячный элемент из +-- списка натуральных чисел (бесконечного) и вы напишете так: + +[1..] !! 999 -- 1000 + +-- То Haskell вычислит элементы этого списка от 1 до 1000... +-- ... и остановится, ведь последующие элементы пока не нужны. +-- Это значит, что остальные элементы нашего +-- "бесконечного" списка не будут вычисляться! По крайней мере, +-- пока не понадобятся и они. + +-- Списки можно объединять +[1..5] ++ [6..10] + +-- И добавлять значения в начало +0:[1..5] -- [0, 1, 2, 3, 4, 5] + +-- А можно обратиться по индексу +[0..] !! 5 -- 5 + +-- Вот ещё несколько функций, часто используемых со списками +head [1..5] -- 1 +tail [1..5] -- [2, 3, 4, 5] +init [1..5] -- [1, 2, 3, 4] +last [1..5] -- 5 + +-- list comprehensions - "формулы" для описания списков +[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] + +-- можно указать условие попадания элементов в список +[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10] + +-- Списки могут даже состоять из других списков +[[1,2,3],[4,5,6]] !! 1 !! 2 -- 6 (вторая строка, третий столбец) + +-- Кортежи позволяют своим элементам иметь различные типы, +-- но при этом кортежи имеют фиксированную длину. +-- Кортеж: +("haskell", 1) + +-- Часто кортежи из двух элементов называются "парами". +-- Элементы пары можно получать так: +fst ("haskell", 1) -- "haskell" +snd ("haskell", 1) -- 1 + +---------------------------------------------------- +-- 3. Функции +---------------------------------------------------- +-- Простая функция, принимающая два аргумента +add a b = a + b + +-- Внимание! +-- Если вы используете ghci (интерактивный интерпретатор Haskell), +-- вам нужно использовать ключевое слово `let`, примерно так: +-- let add a b = a + b + +-- Вызовем нашу функцию +add 1 2 -- 3 + +-- Функцию можно поместить между первым и вторым аргументами, +-- если заключить её имя в обратные кавычки +1 `add` 2 -- 3 + +{- Вы можете также определять функции, имя которых +вообще не содержит букв! Таки функции и называются "операторами", +и, да, вы можете определять свои операторы! +Скажем, оператор целочисленного деления можно определить так -} +(//) a b = a `div` b +35 // 4 -- 8 +{- Здесь оператор заключен в скобки - как говорят, +поставлен в префиксную позицию. +В префиксной позиции оператор можно не только определять, +но и вызывать -} +(+) 1 2 -- 3 + +-- Охранные выражения (guards) порой удобны, +-- если наша функция ветвится +fib x + | x < 2 = x + | otherwise = fib (x - 1) + fib (x - 2) + +{- Сопоставление с образцом (pattern matching) +чем-то напоминает охранные выражения. +Здесь мы видим три определения функции fib. +При вызове функции по имени Haskell использует +первое определение, к образцу которого +"подойдет" набор аргументов -} +fib 1 = 1 +fib 2 = 2 +fib x = fib (x - 1) + fib (x - 2) + +-- Pattern matching для кортежей выглядит так +foo (x, y) = (x + 1, y + 2) + +{- Pattern matching для списков устроен чуть сложнее. +Пусть `x` - первый элемент списка, а `xs` - остальные элементы. +Тогда операции `head` и `tail` могут быть определены так -} +myHead (x:xs) = x +myTail (x:xs) = xs + +-- Функцию отображения мы можем написать так +myMap func [] = [] +myMap func (x:xs) = func x:(myMap func xs) + +-- При сопоставлении происходит привязка +-- элементов значения с именами в образце +fstPlusThird (a : _ : b : _) = a + b +fstPlusThird [1,2,3,4,5] -- 4 +-- Значения, для которых вместо имени указано `_`, +-- игнорируются. Это удобно, когда важен сам факт +-- совпадения образца +oneElem [_] = True +oneElem _ = False + +startsWith x (y:_) = x == y +startsWith _ _ = False + +startsWith 'H' "Hello!" -- True +startsWith 'H' "hello!" -- False + +{- Обратите внимание на тот факт, +что первый аргумент нашей функции `myMap` - тоже функция! +Функции, подобно `myMap`, принимающие другие функции +в качестве параметров, или, скажем, возвращающие функции +в качестве результата, называются +Функциями Высших Порядков (ФВП, High Order Functions, HOF) +-} + +-- Вместе с ФВП часто используются анонимные функции +myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] +-- Такие функции описываются в виде +-- \arg1 arg1 .. -> expression + +-- Популярные в других языках ФВП присутствуют и в Haskell +map (\x -> x * 10) [1..5] -- [10, 20, 30, 40, 50] +filter (\x -> x > 2) [1..5] -- [3, 4, 5] + +{- Функция свертки +(она же `reduce` или `inject` в других языках) +в Haskell представлены функциями `foldr` и `foldl`. +Суть свертки можно представить так: + +foldl f x0 [x1,x2,x3] -> (f (f (f x0 x1) x2) x3) +foldr f x0 [x1,x2,x3] -> (f x1 (f x2 (f x3 x0))) + +Здесь x0 - начальное значения так называемого "аккумулятора" +-} +-- Эти два вызова дают одинаковый результат +foldr (\x acc -> acc + x) 0 [1..5] -- 15 +foldl (\acc x -> acc + x) 0 [1..5] -- 15 +-- Тут можно даже заменить анонимную функцию на оператор +foldr (+) 0 [1..5] -- 15 +foldl (+) 0 [1..5] -- 15 + +-- Зато здесь разница видна +foldr (\x acc -> (x + 10) : acc) [] [1..3] -- [11, 12, 13] +foldl (\acc x -> (x + 10) : acc) [] [1..3] -- [13, 12, 11] + +{- Часто в качестве начального значения +удобно брать крайнее значение списка (крайнее слева или справа). +Для этого есть пара функций - `foldr1` и `foldl1` -} +foldr1 (+) [1..5] -- 15 +foldl1 (+) [1..5] -- 15 + +---------------------------------------------------- +-- 4. Больше о функциях +---------------------------------------------------- + +{- Каррирование (currying) +Если в Haskell при вызове функции передать не все аргументы, +Функция становится "каррированой" - результатом вызова станет +новая функция, которая при вызове и примет оставшиеся аргументы -} + +add a b = a + b +foo = add 10 -- теперь foo будет принимать число + -- и добавлять к нему 10 +foo 5 -- 15 + +-- Для операторов можно "опустить" любой из двух аргументов +-- Используя этот факт можно определить +-- функцию `foo` из кода выше несколько иначе +foo = (+10) +foo 5 -- 15 + +-- Поупражняемся +map (10-) [1..3] -- [9, 8, 7] +filter (<5) [1..10] -- [1, 2, 3, 4] + +{- Композиция функций +Функция (.) соединяет пару функций в цепочку. +К примеру, можно соединить функцию, добавляющую 10, +с функцией, умножающей на 5 -} +foo = (*5) . (+10) + +-- (5 + 10) * 5 = 75 +foo 5 -- 75 + +{- Управление приоритетом вычисления +В Haskell есть функция `$`, которая применяет +свой первый аргумент ко второму с наименьшим приоритетом +(обычное применение функций имеет наивысший приоритет) +Эта функция часто позволяет избежать использования +"лишних" скобок -} +head (tail (tail "abcd")) -- 'c' +head $ tail $ tail "abcd" -- 'c' +-- того же эффекта иногда можно достичь использованием композиции +(head . tail . tail) "abcd" -- 'c' +head . tail . tail $ "abcd" -- 'c' +{- Тут стоит сразу запомнить, что композиция функций +возвращает именно новую функцию, как в последнем примере. +Т.е. можно делать так -} +third = head . tail . tail +-- но не так +third = head $ tail $ tail -- (head (tail (tail))) - ошибка! + +---------------------------------------------------- +-- 5. Сигнатуры типов +---------------------------------------------------- + +{- Haskell обладает очень сильной системой типов. +И типизация в Haskell - строгая. Каждое выражение имеет тип, +который может быть описан сигнатурой. +Сигнатура записывается в форме +expression :: type signature +-} + +-- Типы примитивов +5 :: Integer +"hello" :: String +True :: Bool + +{- Функции тоже имеют тип +`not` принимает булево значение и возвращает булев результат +not :: Bool -> Bool + +Вот функция двух аргументов +add :: Integer -> Integer -> Integer + +Тут то мы и видим предпосылки к каррированию: тип +на самом деле выглядит так (скобки просто обычно опускаются) +add :: (Integer -> Integer) -> Integer +т.е. функция принимает аргумент, +и возвращает функцию от второго аргумента! -} + +-- Считается хорошим тоном указывать сигнатуру определений, +-- которые доступны другим разработчикам (публичны). Пример: +double :: Integer -> Integer +double x = x * 2 + +---------------------------------------------------- +-- 6. Управление потоком исполнения +---------------------------------------------------- + +-- Выражение `if` +haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome" + +-- Выражение `if` можно записать и в несколько строк. +-- Соблюдайте отступы! +haskell = if 1 == 1 + then "awesome" + else "awful" + +-- Так как `if` - выражение, ветка `else` обязательна! +-- И более того, результаты выражений в ветках `then` и `else` +-- должны иметь одинаковый тип! + +-- `case`-выражение выглядит так +case args of -- парсим аргументы командной строки + "help" -> printHelp + "start" -> startProgram + _ -> putStrLn "bad args" + +-- При вычислении результата `case`-выражения производится +-- сопоставление с образцом: +fib x = case x of + 1 -> 1 + 2 -> 1 + _ -> fib (x - 1) + fib (x - 2) + +-- В Haskell нет циклов - вместо них используются рекурсия, +-- отображение, фильтрация и свертка (map/filter/fold) +map (*2) [1..5] -- [2, 4, 6, 8, 10] + +for array func = map func array +for [0..3] $ \i -> show i -- ["0", "1", "2", "3"] +for [0..3] show -- ["0", "1", "2", "3"] + +---------------------------------------------------- +-- 7. Пользовательские типы данных +---------------------------------------------------- + +-- Создадим свой Haskell-тип данных + +data Color = Red | Blue | Green + +-- Попробуем использовать + +say :: Color -> String +say Red = "You are Red!" +say Blue = "You are Blue!" +say Green = "You are Green!" + +-- Типы могут иметь параметры (параметры типов) + +data Maybe a = Nothing | Just a + +-- Все эти выражения имеют тип `Maybe` +Just "hello" -- :: `Maybe String` +Just 1 -- :: `Maybe Int` +Nothing -- :: `Maybe a` для любого `a` + +-- Типы могут быть достаточно сложными +data Figure = Rectangle (Int, Int) Int Int + | Square (Int, Int) Int + | Point (Int, Int) + +area :: Figure -> Int +area (Point _) = 0 +area (Square _ s) = s * s +area (Rectangle _ w h) = w * h + +---------------------------------------------------- +-- 8. Ввод-вывод в Haskell +---------------------------------------------------- + +-- Полноценно объяснить тему ввода-вывода невозможно +-- без объяснения монад, но для использования в простых случаях +-- вводного описания будет достаточно. + +-- Когда программа на Haskell выполняется, +-- вызывается функция с именем `main`. +-- Эта функция должна вернуть значение типа `IO ()` +-- Например + +main :: IO () +main = putStrLn $ "Hello, sky! " ++ (say Blue) +-- `putStrLn` имеет тип `String -> IO ()` + +-- Проще всего реализовать программу с вводом-выводом (IO), +-- если вы реализуете функцию с типом `String -> String`. +-- Далее ФВП +-- interact :: (String -> String) -> IO () +-- сделает всё за нас! + +countLines :: String -> String +countLines = show . length . lines +-- здесь `lines` разделяет строку на список строк +-- по символу перевода строки + +main' :: IO () +main' = interact countLines + +{- Вы можете думать о типе `IO ()`, +как о некотором представлении последовательности +действий, которые должен совершить компьютер. +Такое представление напоминает программу +на императивном языке программирования. Для описания +такой последовательности используется `do`-нотация -} + +sayHello :: IO () +sayHello = do + putStrLn "What is your name?" + name <- getLine -- запрашиваем строку и связываем с "name" + putStrLn $ "Hello, " ++ name + +-- Упражнение: +-- напишите свою реализацию функции `interact`, +-- которая запрашивает и обрабатывает только одну строку + +{- Код функции `sayHello` не будет исполняться +при её определении. Единственное место, где IO-действия +могут быть произведены - функция `main`! +Чтобы эта программа выполнила действия в функции `sayHello`, +закомментируйте предыдущее определение функции `main` +и добавьте новое определение: + +main = sayHello -} + +{- Давайте подробнее рассмотрим, как работает функция `getLine` +Её тип: + getLine :: IO String +Вы можете думать, что значение типа `IO a` представляет +собой компьютерную программу, в результате выполнения которой +генерируется значение типа `a`, в дополнение +к остальным эффектам, производимым при выполнении - таким как +печать текста на экран. Это значение типа `a` мы можем +сохранить с помощью оператора `<-`. Мы даже можем реализовать +свое действие, возвращающее значение: -} + +action :: IO String +action = do + putStrLn "This is a line. Duh" + input1 <- getLine + input2 <- getLine + -- Тип блока `do` будет соответствовать типу последнего + -- выполненного в блоке выражения. + -- Заметим, что `return` - не ключевое слово, а функция + -- типа `a -> IO a` + return (input1 ++ "\n" ++ input2) -- return :: String -> IO String + +-- Теперь это действие можно использовать вместо `getLine`: + +main'' = do + putStrLn "I will echo two lines!" + result <- action + putStrLn result + putStrLn "This was all, folks!" + +{- Тип `IO` - пример "монады". Языку Haskell нужны монады, +чтобы оставаться преимущественно чистым функциональным языком. +Любые функции, взаимодействующие с внешним миром +(производящие ввод-вывод) имеют `IO` в своих сигнатурах. +Это позволяет судить о функции как о "чистой" - такая не будет +производить ввод-вывод. В ином случая функция - не "чистая". + +Такой подход позволяет очень просто разрабатывать многопоточные +программы - чистые функции, запущенные параллельно +не будут конфликтовать между собой в борьбе за ресурсы. -} + +---------------------------------------------------- +-- 9. Haskell REPL +---------------------------------------------------- + +{- Интерактивная консоль Haskell запускается командой `ghci`. +Теперь можно вводить строки кода на Haskell. +Связывание значений с именами производится +с помощью выражения `let`: -} + +let foo = 5 + +-- Тип значения или выражения можно узнать +-- с помощью команды `:t`: + +>:t foo +foo :: Integer + +-- Также можно выполнять действия с типом `IO ()` + +> sayHello +What is your name? +Friend! +Hello, Friend! + +``` + +Многое о Haskell, например классы типов и монады невозможно уместить в столь короткую статью. Огромное количество очень интересных идей лежит в основе языка, и именно благодаря этому фундаменту на языке так приятно писать код. Позволю себе привести ещё один маленький пример кода на Haskell - реализацию быстрой сортировки: + +```haskell +qsort [] = [] +qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater + where lesser = filter (< p) xs + greater = filter (>= p) xs +``` + +Haskell прост в установке, забирайте [здесь](http://www.haskell.org/platform/) и пробуйте! Это же так интересно!. + +Более глубокое погрузиться в язык позволят прекрасные книги +[Learn you a Haskell](http://learnyouahaskell.com/) и +[Real World Haskell](http://book.realworldhaskell.org/). + +[autor]: http://adit.io имеется в виду автор оригинального текста Adit Bhargava *(примечание переводчика)* diff --git a/ru-ru/julia-ru.html.markdown b/ru-ru/julia-ru.html.markdown index c9213a42..cd55e116 100644 --- a/ru-ru/julia-ru.html.markdown +++ b/ru-ru/julia-ru.html.markdown @@ -24,58 +24,58 @@ Julia — гомоиконный функциональный язык прог # Всё в Julia — выражение. # Простые численные типы -3 #=> 3 (Int64) -3.2 #=> 3.2 (Float64) -2 + 1im #=> 2 + 1im (Complex{Int64}) -2//3 #=> 2//3 (Rational{Int64}) +3 # => 3 (Int64) +3.2 # => 3.2 (Float64) +2 + 1im # => 2 + 1im (Complex{Int64}) +2//3 # => 2//3 (Rational{Int64}) # Доступны все привычные инфиксные операторы -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7.0 -5 / 2 #=> 2.5 # деление Int на Int всегда возвращает Float -div(5, 2) #=> 2 # для округления к нулю используется div -5 \ 35 #=> 7.0 -2 ^ 2 #=> 4 # возведение в степень -12 % 10 #=> 2 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 +5 / 2 # => 2.5 # деление Int на Int всегда возвращает Float +div(5, 2) # => 2 # для округления к нулю используется div +5 \ 35 # => 7.0 +2 ^ 2 # => 4 # возведение в степень +12 % 10 # => 2 # С помощью скобок можно изменить приоритет операций -(1 + 3) * 2 #=> 8 +(1 + 3) * 2 # => 8 # Побитовые операторы -~2 #=> -3 # НЕ (NOT) -3 & 5 #=> 1 # И (AND) -2 | 4 #=> 6 # ИЛИ (OR) -2 $ 4 #=> 6 # сложение по модулю 2 (XOR) -2 >>> 1 #=> 1 # логический сдвиг вправо -2 >> 1 #=> 1 # арифметический сдвиг вправо -2 << 1 #=> 4 # логический/арифметический сдвиг влево +~2 # => -3 # НЕ (NOT) +3 & 5 # => 1 # И (AND) +2 | 4 # => 6 # ИЛИ (OR) +2 $ 4 # => 6 # сложение по модулю 2 (XOR) +2 >>> 1 # => 1 # логический сдвиг вправо +2 >> 1 # => 1 # арифметический сдвиг вправо +2 << 1 # => 4 # логический/арифметический сдвиг влево # Функция bits возвращает бинарное представление числа bits(12345) -#=> "0000000000000000000000000000000000000000000000000011000000111001" +# => "0000000000000000000000000000000000000000000000000011000000111001" bits(12345.0) -#=> "0100000011001000000111001000000000000000000000000000000000000000" +# => "0100000011001000000111001000000000000000000000000000000000000000" # Логические значения являются примитивами true false # Булевы операторы -!true #=> false -!false #=> true -1 == 1 #=> true -2 == 1 #=> false -1 != 1 #=> false -2 != 1 #=> true -1 < 10 #=> true -1 > 10 #=> false -2 <= 2 #=> true -2 >= 2 #=> true +!true # => false +!false # => true +1 == 1 # => true +2 == 1 # => false +1 != 1 # => false +2 != 1 # => true +1 < 10 # => true +1 > 10 # => false +2 <= 2 # => true +2 >= 2 # => true # Сравнения можно объединять цепочкой -1 < 2 < 3 #=> true -2 < 3 < 2 #=> false +1 < 2 < 3 # => true +2 < 3 < 2 # => false # Строки объявляются с помощью двойных кавычек — " "This is a string." @@ -84,12 +84,12 @@ false 'a' # Строки индексируются как массивы символов -"This is a string"[1] #=> 'T' # Индексы начинаются с единицы +"This is a string"[1] # => 'T' # Индексы начинаются с единицы # Индексирование не всегда правильно работает для UTF8-строк, # поэтому рекомендуется использовать итерирование (map, for-циклы и т.п.). # Для строковой интерполяции используется знак доллара ($): -"2 + 2 = $(2 + 2)" #=> "2 + 2 = 4" +"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" # В скобках можно использовать любое выражение языка. # Другой способ форматирования строк — макрос printf @@ -103,12 +103,12 @@ false println("I'm Julia. Nice to meet you!") # Переменные инициализируются без предварительного объявления -some_var = 5 #=> 5 -some_var #=> 5 +some_var = 5 # => 5 +some_var # => 5 # Попытка доступа к переменной до инициализации вызывает ошибку try - some_other_var #=> ERROR: some_other_var not defined + some_other_var # => ERROR: some_other_var not defined catch e println(e) end @@ -116,12 +116,12 @@ end # Имена переменных начинаются с букв. # После первого символа можно использовать буквы, цифры, # символы подчёркивания и восклицательные знаки. -SomeOtherVar123! = 6 #=> 6 +SomeOtherVar123! = 6 # => 6 # Допустимо использование unicode-символов -☃ = 8 #=> 8 +☃ = 8 # => 8 # Это особенно удобно для математических обозначений -2 * π #=> 6.283185307179586 +2 * π # => 6.283185307179586 # Рекомендации по именованию: # * имена переменных в нижнем регистре, слова разделяются символом @@ -136,49 +136,49 @@ SomeOtherVar123! = 6 #=> 6 # оканчивается восклицательным знаком. # Массив хранит последовательность значений, индексируемых с единицы до n: -a = Int64[] #=> пустой массив Int64-элементов +a = Int64[] # => пустой массив Int64-элементов # Одномерный массив объявляется разделёнными запятой значениями. -b = [4, 5, 6] #=> массив из трёх Int64-элементов: [4, 5, 6] -b[1] #=> 4 -b[end] #=> 6 +b = [4, 5, 6] # => массив из трёх Int64-элементов: [4, 5, 6] +b[1] # => 4 +b[end] # => 6 # Строки двумерного массива разделяются точкой с запятой. # Элементы строк разделяются пробелами. -matrix = [1 2; 3 4] #=> 2x2 Int64 Array: [1 2; 3 4] +matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4] # push! и append! добавляют в список новые элементы -push!(a,1) #=> [1] -push!(a,2) #=> [1,2] -push!(a,4) #=> [1,2,4] -push!(a,3) #=> [1,2,4,3] -append!(a,b) #=> [1,2,4,3,4,5,6] +push!(a,1) # => [1] +push!(a,2) # => [1,2] +push!(a,4) # => [1,2,4] +push!(a,3) # => [1,2,4,3] +append!(a,b) # => [1,2,4,3,4,5,6] # pop! удаляет из списка последний элемент -pop!(b) #=> возвращает 6; массив b снова равен [4,5] +pop!(b) # => возвращает 6; массив b снова равен [4,5] # Вернём 6 обратно push!(b,6) # b снова [4,5,6]. -a[1] #=> 1 # индексы начинаются с единицы! +a[1] # => 1 # индексы начинаются с единицы! # Последний элемент можно получить с помощью end -a[end] #=> 6 +a[end] # => 6 # Операции сдвига -shift!(a) #=> 1 and a is now [2,4,3,4,5,6] -unshift!(a,7) #=> [7,2,4,3,4,5,6] +shift!(a) # => 1 and a is now [2,4,3,4,5,6] +unshift!(a,7) # => [7,2,4,3,4,5,6] # Восклицательный знак на конце названия функции означает, # что функция изменяет переданные ей аргументы. -arr = [5,4,6] #=> массив из 3 Int64-элементов: [5,4,6] -sort(arr) #=> [4,5,6]; но arr равен [5,4,6] -sort!(arr) #=> [4,5,6]; а теперь arr — [4,5,6] +arr = [5,4,6] # => массив из 3 Int64-элементов: [5,4,6] +sort(arr) # => [4,5,6]; но arr равен [5,4,6] +sort!(arr) # => [4,5,6]; а теперь arr — [4,5,6] # Попытка доступа за пределами массива выбрасывает BoundsError try - a[0] #=> ERROR: BoundsError() in getindex at array.jl:270 - a[end+1] #=> ERROR: BoundsError() in getindex at array.jl:270 + a[0] # => ERROR: BoundsError() in getindex at array.jl:270 + a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270 catch e println(e) end @@ -189,111 +189,111 @@ end # то найти эти файлы можно в директории base. # Создавать массивы можно из последовательности -a = [1:5] #=> массив из 5 Int64-элементов: [1,2,3,4,5] +a = [1:5] # => массив из 5 Int64-элементов: [1,2,3,4,5] # Срезы -a[1:3] #=> [1, 2, 3] -a[2:] #=> [2, 3, 4, 5] -a[2:end] #=> [2, 3, 4, 5] +a[1:3] # => [1, 2, 3] +a[2:] # => [2, 3, 4, 5] +a[2:end] # => [2, 3, 4, 5] # splice! удаляет элемент из массива # Remove elements from an array by index with splice! arr = [3,4,5] -splice!(arr,2) #=> 4 ; arr теперь равен [3,5] +splice!(arr,2) # => 4 ; arr теперь равен [3,5] # append! объединяет списки b = [1,2,3] append!(a,b) # теперь a равен [1, 2, 3, 4, 5, 1, 2, 3] # Проверка на вхождение -in(1, a) #=> true +in(1, a) # => true # Длина списка -length(a) #=> 8 +length(a) # => 8 # Кортеж — неизменяемая структура. -tup = (1, 2, 3) #=> (1,2,3) # кортеж (Int64,Int64,Int64). -tup[1] #=> 1 +tup = (1, 2, 3) # => (1,2,3) # кортеж (Int64,Int64,Int64). +tup[1] # => 1 try: - tup[1] = 3 #=> ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) + tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) catch e println(e) end # Многие функции над списками работают и для кортежей -length(tup) #=> 3 -tup[1:2] #=> (1,2) -in(2, tup) #=> true +length(tup) # => 3 +tup[1:2] # => (1,2) +in(2, tup) # => true # Кортежи можно распаковывать в переменные -a, b, c = (1, 2, 3) #=> (1,2,3) # a = 1, b = 2 и c = 3 +a, b, c = (1, 2, 3) # => (1,2,3) # a = 1, b = 2 и c = 3 # Скобки из предыдущего примера можно опустить -d, e, f = 4, 5, 6 #=> (4,5,6) +d, e, f = 4, 5, 6 # => (4,5,6) # Кортеж из одного элемента не равен значению этого элемента -(1,) == 1 #=> false -(1) == 1 #=> true +(1,) == 1 # => false +(1) == 1 # => true # Обмен значений -e, d = d, e #=> (5,4) # d = 5, e = 4 +e, d = d, e # => (5,4) # d = 5, e = 4 # Словари содержат ассоциативные массивы -empty_dict = Dict() #=> Dict{Any,Any}() +empty_dict = Dict() # => Dict{Any,Any}() # Для создания словаря можно использовать литерал filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3] # => Dict{ASCIIString,Int64} # Значения ищутся по ключу с помощью оператора [] -filled_dict["one"] #=> 1 +filled_dict["one"] # => 1 # Получить все ключи keys(filled_dict) -#=> KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) # Заметьте, словарь не запоминает порядок, в котором добавляются ключи. # Получить все значения. values(filled_dict) -#=> ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) # То же касается и порядка значений. # Проверка вхождения ключа в словарь -in(("one", 1), filled_dict) #=> true -in(("two", 3), filled_dict) #=> false -haskey(filled_dict, "one") #=> true -haskey(filled_dict, 1) #=> false +in(("one", 1), filled_dict) # => true +in(("two", 3), filled_dict) # => false +haskey(filled_dict, "one") # => true +haskey(filled_dict, 1) # => false # Попытка обратиться к несуществующему ключу выбросит ошибку try - filled_dict["four"] #=> ERROR: key not found: four in getindex at dict.jl:489 + filled_dict["four"] # => ERROR: key not found: four in getindex at dict.jl:489 catch e println(e) end # Используйте метод get со значением по умолчанию, чтобы избежать этой ошибки # get(dictionary,key,default_value) -get(filled_dict,"one",4) #=> 1 -get(filled_dict,"four",4) #=> 4 +get(filled_dict,"one",4) # => 1 +get(filled_dict,"four",4) # => 4 # Для коллекций неотсортированных уникальных элементов используйте Set -empty_set = Set() #=> Set{Any}() +empty_set = Set() # => Set{Any}() # Инициализация множества -filled_set = Set(1,2,2,3,4) #=> Set{Int64}(1,2,3,4) +filled_set = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4) # Добавление элементов -push!(filled_set,5) #=> Set{Int64}(5,4,2,3,1) +push!(filled_set,5) # => Set{Int64}(5,4,2,3,1) # Проверка вхождения элементов во множество -in(2, filled_set) #=> true -in(10, filled_set) #=> false +in(2, filled_set) # => true +in(10, filled_set) # => false # Функции для получения пересечения, объединения и разницы. -other_set = Set(3, 4, 5, 6) #=> Set{Int64}(6,4,5,3) -intersect(filled_set, other_set) #=> Set{Int64}(3,4,5) -union(filled_set, other_set) #=> Set{Int64}(1,2,3,4,5,6) -setdiff(Set(1,2,3,4),Set(2,3,5)) #=> Set{Int64}(1,4) +other_set = Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3) +intersect(filled_set, other_set) # => Set{Int64}(3,4,5) +union(filled_set, other_set) # => Set{Int64}(1,2,3,4,5,6) +setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4) #################################################### @@ -311,7 +311,7 @@ elseif some_var < 10 # Необязательная ветка elseif. else # else-ветка также опциональна. println("some_var is indeed 10.") end -#=> prints "some var is smaller than 10" +# => prints "some var is smaller than 10" # Цикл for проходит по итерируемым объектам @@ -368,7 +368,7 @@ try catch e println("caught it $e") end -#=> caught it ErrorException("help") +# => caught it ErrorException("help") #################################################### @@ -386,27 +386,27 @@ function add(x, y) x + y end -add(5, 6) #=> Вернёт 11, напечатав "x is 5 and y is 6" +add(5, 6) # => Вернёт 11, напечатав "x is 5 and y is 6" # Функция может принимать переменное количество позиционных аргументов. function varargs(args...) return args # для возвращения из функции в любом месте используется 'return' end -#=> varargs (generic function with 1 method) +# => varargs (generic function with 1 method) -varargs(1,2,3) #=> (1,2,3) +varargs(1,2,3) # => (1,2,3) # Многоточие (...) — это splat. # Мы только что воспользовались им в определении функции. # Также его можно использовать при вызове функции, # где он преобразует содержимое массива или кортежа в список аргументов. -Set([1,2,3]) #=> Set{Array{Int64,1}}([1,2,3]) # формирует множество массивов -Set([1,2,3]...) #=> Set{Int64}(1,2,3) # эквивалентно Set(1,2,3) +Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # формирует множество массивов +Set([1,2,3]...) # => Set{Int64}(1,2,3) # эквивалентно Set(1,2,3) -x = (1,2,3) #=> (1,2,3) -Set(x) #=> Set{(Int64,Int64,Int64)}((1,2,3)) # множество кортежей -Set(x...) #=> Set{Int64}(2,3,1) +x = (1,2,3) # => (1,2,3) +Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # множество кортежей +Set(x...) # => Set{Int64}(2,3,1) # Опциональные позиционные аргументы @@ -414,12 +414,12 @@ function defaults(a,b,x=5,y=6) return "$a $b and $x $y" end -defaults('h','g') #=> "h g and 5 6" -defaults('h','g','j') #=> "h g and j 6" -defaults('h','g','j','k') #=> "h g and j k" +defaults('h','g') # => "h g and 5 6" +defaults('h','g','j') # => "h g and j 6" +defaults('h','g','j','k') # => "h g and j k" try - defaults('h') #=> ERROR: no method defaults(Char,) - defaults() #=> ERROR: no methods defaults() + defaults('h') # => ERROR: no method defaults(Char,) + defaults() # => ERROR: no methods defaults() catch e println(e) end @@ -429,9 +429,9 @@ function keyword_args(;k1=4,name2="hello") # обратите внимание return ["k1"=>k1,"name2"=>name2] end -keyword_args(name2="ness") #=> ["name2"=>"ness","k1"=>4] -keyword_args(k1="mine") #=> ["k1"=>"mine","name2"=>"hello"] -keyword_args() #=> ["name2"=>"hello","k2"=>4] +keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4] +keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"] +keyword_args() # => ["name2"=>"hello","k2"=>4] # В одной функции можно совмещать все виды аргументов function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo") @@ -455,7 +455,7 @@ function create_adder(x) end # Анонимная функция -(x -> x > 2)(3) #=> true +(x -> x > 2)(3) # => true # Эта функция идентичная предыдущей версии create_adder function create_adder(x) @@ -471,16 +471,16 @@ function create_adder(x) end add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 # Встроенные функции высшего порядка -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(x -> x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +map(add_10, [1,2,3]) # => [11, 12, 13] +filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7] # Списковые сборки -[add_10(i) for i=[1, 2, 3]] #=> [11, 12, 13] -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13] +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] #################################################### ## 5. Типы @@ -489,12 +489,12 @@ filter(x -> x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] # Julia has a type system. # Каждое значение имеет тип, но переменные не определяют тип значения. # Функция `typeof` возвращает тип значения. -typeof(5) #=> Int64 +typeof(5) # => Int64 # Types are first-class values # Типы являются значениями первого класса -typeof(Int64) #=> DataType -typeof(DataType) #=> DataType +typeof(Int64) # => DataType +typeof(DataType) # => DataType # Тип DataType представляет типы, включая себя самого. # Типы используются в качестве документации, для оптимизации и организации. @@ -515,10 +515,10 @@ end # Аргументы конструктора по умолчанию — свойства типа # в порядке их определения. -tigger = Tiger(3.5,"orange") #=> Tiger(3.5,"orange") +tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange") # Тип объекта по сути является конструктором значений такого типа -sherekhan = typeof(tigger)(5.6,"fire") #=> Tiger(5.6,"fire") +sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire") # Эти типы, похожие на структуры, называются конкретными. # Можно создавать объекты таких типов, но не их подтипы. @@ -530,23 +530,23 @@ abstract Cat # просто имя и точка в иерархии типов # Объекты абстрактных типов создавать нельзя, # но зато от них можно наследовать подтипы. # Например, Number — это абстрактный тип. -subtypes(Number) #=> 6 элементов в массиве Array{Any,1}: +subtypes(Number) # => 6 элементов в массиве Array{Any,1}: # Complex{Float16} # Complex{Float32} # Complex{Float64} # Complex{T<:Real} # ImaginaryUnit # Real -subtypes(Cat) #=> пустой массив Array{Any,1} +subtypes(Cat) # => пустой массив Array{Any,1} # У всех типов есть супертип. Для его определения есть функция `super`. -typeof(5) #=> Int64 -super(Int64) #=> Signed -super(Signed) #=> Real -super(Real) #=> Number -super(Number) #=> Any -super(super(Signed)) #=> Number -super(Any) #=> Any +typeof(5) # => Int64 +super(Int64) # => Signed +super(Signed) # => Real +super(Real) # => Number +super(Number) # => Any +super(super(Signed)) # => Number +super(Any) # => Any # Все эти типы, за исключением Int64, абстрактные. # Для создания подтипа используется оператор <: @@ -595,23 +595,23 @@ function meow(animal::Tiger) end # Проверка -meow(tigger) #=> "rawwr" -meow(Lion("brown","ROAAR")) #=> "ROAAR" -meow(Panther()) #=> "grrr" +meow(tigger) # => "rawwr" +meow(Lion("brown","ROAAR")) # => "ROAAR" +meow(Panther()) # => "grrr" # Вспомним иерархию типов -issubtype(Tiger,Cat) #=> false -issubtype(Lion,Cat) #=> true -issubtype(Panther,Cat) #=> true +issubtype(Tiger,Cat) # => false +issubtype(Lion,Cat) # => true +issubtype(Panther,Cat) # => true # Определим функцию, принимающую на вход объекты типа Cat function pet_cat(cat::Cat) println("The cat says $(meow(cat))") end -pet_cat(Lion("42")) #=> выведет "The cat says 42" +pet_cat(Lion("42")) # => выведет "The cat says 42" try - pet_cat(tigger) #=> ERROR: no method pet_cat(Tiger,) + pet_cat(tigger) # => ERROR: no method pet_cat(Tiger,) catch e println(e) end @@ -624,31 +624,31 @@ end function fight(t::Tiger,c::Cat) println("The $(t.coatcolor) tiger wins!") end -#=> fight (generic function with 1 method) +# => fight (generic function with 1 method) -fight(tigger,Panther()) #=> выведет The orange tiger wins! -fight(tigger,Lion("ROAR")) #=> выведет The orange tiger wins! +fight(tigger,Panther()) # => выведет The orange tiger wins! +fight(tigger,Lion("ROAR")) # => выведет The orange tiger wins! # Переопределим поведение функции, если Cat-объект является Lion-объектом fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!") -#=> fight (generic function with 2 methods) +# => fight (generic function with 2 methods) -fight(tigger,Panther()) #=> выведет The orange tiger wins! -fight(tigger,Lion("ROAR")) #=> выведет The green-maned lion wins! +fight(tigger,Panther()) # => выведет The orange tiger wins! +fight(tigger,Lion("ROAR")) # => выведет The green-maned lion wins! # Драться можно не только с тиграми! fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))") -#=> fight (generic function with 3 methods) +# => fight (generic function with 3 methods) -fight(Lion("balooga!"),Panther()) #=> выведет The victorious cat says grrr +fight(Lion("balooga!"),Panther()) # => выведет The victorious cat says grrr try - fight(Panther(),Lion("RAWR")) #=> ERROR: no method fight(Panther,Lion) + fight(Panther(),Lion("RAWR")) # => ERROR: no method fight(Panther,Lion) catch end # Вообще, пускай кошачьи могут первыми проявлять агрессию fight(c::Cat,l::Lion) = println("The cat beats the Lion") -#=> Warning: New definition +# => Warning: New definition # fight(Cat,Lion) at none:1 # is ambiguous with # fight(Lion,Cat) at none:2. @@ -658,11 +658,11 @@ fight(c::Cat,l::Lion) = println("The cat beats the Lion") #fight (generic function with 4 methods) # Предупреждение говорит, что неясно, какой из методов вызывать: -fight(Lion("RAR"),Lion("brown","rarrr")) #=> выведет The victorious cat says rarrr +fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The victorious cat says rarrr # Результат может оказаться разным в разных версиях Julia fight(l::Lion,l2::Lion) = println("The lions come to a tie") -fight(Lion("RAR"),Lion("brown","rarrr")) #=> выведет The lions come to a tie +fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The lions come to a tie # Под капотом diff --git a/ruby.html.markdown b/ruby.html.markdown index a4c74a4f..962853a2 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -8,6 +8,8 @@ contributors: - ["Tristan Hume", "http://thume.ca/"] - ["Nick LaMuro", "https://github.com/NickLaMuro"] - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"] + - ["Ariel Krakowski", "http://www.learneroo.com"] + --- ```ruby @@ -33,6 +35,7 @@ You shouldn't either 8 - 1 #=> 7 10 * 2 #=> 20 35 / 5 #=> 7 +2 ** 5 #=> 32 # Arithmetic is just syntactic sugar # for calling a method on an object @@ -79,6 +82,10 @@ placeholder = "use string interpolation" "I can #{placeholder} when using double quoted strings" #=> "I can use string interpolation when using double quoted strings" +# Combine strings, but not with numbers +"hello " + "world" #=> "hello world" +"hello " + 3 #=> TypeError: can't convert Fixnum into String +"hello " + 3.to_s #=> "hello 3" # print to the output puts "I'm printing!" @@ -247,6 +254,22 @@ else puts "Alternative grading system, eh?" end +#=> "Better luck next time" + +# cases can also use ranges +grade = 82 +case grade + when 90..100 + puts "Hooray!" + when 80...90 + puts "OK job" + else + puts "You failed!" +end + +#=> "OK job" + + # Functions def double(x) @@ -474,3 +497,12 @@ Something.qux # => NoMethodError: undefined method `qux' Something.new.bar # => NoMethodError: undefined method `bar' Something.new.qux # => 'qux' ``` + +## Additional resources + +- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - A variant of this reference with in-browser challenges. +- [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/) - An older [free addition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. + + diff --git a/scala.html.markdown b/scala.html.markdown index 5dfaefe0..2666746e 100644 --- a/scala.html.markdown +++ b/scala.html.markdown @@ -104,10 +104,13 @@ val sq = (x:Int) => x * x sq(10) // Gives you this: res33: Int = 100. +// The colon explicitly defines the type of a value, in this case a function +// taking an Int and returning an Int. +val add10: Int => Int = _ + 10 + // Scala allows methods and functions to return, or take as parameters, other // functions or methods. -val add10: Int => Int = _ + 10 // A function taking an Int and returning an Int List(1, 2, 3) map add10 // List(11, 12, 13) - add10 is applied to each element // Anonymous functions can be used instead of named functions: diff --git a/xml.html.markdown b/xml.html.markdown new file mode 100644 index 00000000..349d4763 --- /dev/null +++ b/xml.html.markdown @@ -0,0 +1,131 @@ +--- +language: xml +filename: learnxml.xml +contributors: + - ["João Farias", "https://github.com/JoaoGFarias"] +--- + +XML is a markup language designed to store and transport data. + +Unlike HTML, XML does not specifies how to display or to format data, just carry it. + +* XML Syntax + +```XML +<!-- Comments in XML are like this --> + +<?xml version="1.0" encoding="UTF-8"?> +<bookstore> + <book category="COOKING"> + <title lang="en">Everyday Italian</title> + <author>Giada De Laurentiis</author> + <year>2005</year> + <price>30.00</price> + </book> + <book category="CHILDREN"> + <title lang="en">Harry Potter</title> + <author>J K. Rowling</author> + <year>2005</year> + <price>29.99</price> + </book> + <book category="WEB"> + <title lang="en">Learning XML</title> + <author>Erik T. Ray</author> + <year>2003</year> + <price>39.95</price> + </book> +</bookstore> + +<!-- Above is a typical XML file. + It starts with a declaration, informing some metadata (optional) + + XML uses a tree structure. Above, the root node is 'bookstore', which has + three child nodes, all 'books'. Those nodes has more child nodes, and so on... + + Nodes are created using open/close tags, and childs are just nodes between + the open and close tags.--> + + +<!-- XML carries two kind of data: + 1 - Attributes -> That's metadata about a node. + Usually, the XML parser uses this information to store the data properly. + It is characterized by appearing in parenthesis within the opening tag + 2 - Elements -> That's pure data. + That's what the parser will retrive from the XML file. + Elements appear between the open and close tags, without paranthesis. --> + + +<!-- Below, an element with two attributes --> +<file type="gif" id="4293">computer.gif</file> + + +``` + +* Well-Formated Document x Validation + +A XML document is well-formated if it is syntactically correct. +However, is possible to inject more constraints in the document, +using document definitions, such as DTD and XML Schema. + +A XML document which follows a document definition is called valid, +regarding that document. + +With this tool, you can check the XML data outside the application logic. + +```XML + +<!-- Below, you can see an simplified version of bookstore document, + with the addition of DTD definition.--> + +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE note SYSTEM "Bookstore.dtd"> +<bookstore> + <book category="COOKING"> + <title >Everyday Italian</title> + <price>30.00</price> + </book> +</bookstore> + +<!-- This DTD could be something like:--> + +<!DOCTYPE note +[ +<!ELEMENT bookstore (book+)> +<!ELEMENT book (title,price)> +<!ATTLIST book category CDATA "Literature"> +<!ELEMENT title (#PCDATA)> +<!ELEMENT price (#PCDATA)> +]> + + +<!-- The DTD starts with a declaration. + Following, the root node is declared, requiring 1 or more child nodes 'book'. + Eeach 'book' should contain exactly one 'title' and 'price' and an attribute + called 'category', with "Literature" as its default value. + The 'title' and 'price' nodes contain a parsed character data.--> + +<!-- The DTD could be declared inside the XML file itself.--> + +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE note +[ +<!ELEMENT bookstore (book+)> +<!ELEMENT book (title,price)> +<!ATTLIST book category CDATA "Literature"> +<!ELEMENT title (#PCDATA)> +<!ELEMENT price (#PCDATA)> +]> + +<bookstore> + <book category="COOKING"> + <title >Everyday Italian</title> + <price>30.00</price> + </book> +</bookstore> + + +``` + + + diff --git a/zh-cn/coffeescript-cn.html.markdown b/zh-cn/coffeescript-cn.html.markdown index 8fb96749..44561541 100644 --- a/zh-cn/coffeescript-cn.html.markdown +++ b/zh-cn/coffeescript-cn.html.markdown @@ -2,9 +2,9 @@ language: coffeescript contributors: - ["Tenor Biel", "http://github.com/L8D"] - - ["Xavier Yao"], "http://github.com/xavieryao"] + - ["Xavier Yao", "http://github.com/xavieryao"] translators: - - ["Xavier Yao"], "http://github.com/xavieryao"] + - ["Xavier Yao", "http://github.com/xavieryao"] filename: coffeescript-cn.coffee lang: zh-cn --- diff --git a/zh-cn/common-lisp-cn.html.markdown b/zh-cn/common-lisp-cn.html.markdown index f005dd58..c4dc3274 100644 --- a/zh-cn/common-lisp-cn.html.markdown +++ b/zh-cn/common-lisp-cn.html.markdown @@ -56,11 +56,11 @@ t ;还是一个原子,代表逻辑真值。 ;; 有很多不同的Common Lisp的实现;并且大部分的实现是一致(可移植)的。 ;; 对于入门学习来说,CLISP是个不错的选择。 -;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 +;; 可以通过QuickLisp.org的Quicklisp系统管理你的库。 -;; 通常,使用一个文本编辑器和一个的“REPL”来开发Common Lisp; +;; 通常,使用文本编辑器和“REPL”来开发Common Lisp; ;; (译者注:“REPL”指读取-求值-打印循环)。 -;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 +;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统“现场”操作。 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -329,7 +329,7 @@ nil ; 逻辑假,或者空列表 ;; 或者使用`apply` (apply (lambda () "Hello World") nil) ; => "Hello World" -;; 显示地定义一个函数(译者注:即非匿名的) +;; 显式地定义一个函数(译者注:即非匿名的) (defun hello-world () "Hello World") (hello-world) ; => "Hello World" @@ -537,7 +537,7 @@ nil ; 逻辑假,或者空列表 ;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 ;; 若要定义一个方法; -;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi +;; 注意,我们计算自行车轮子周长时使用了这样一个公式:C = d * pi (defmethod circumference ((object bicycle)) (* pi (wheel-size object))) @@ -593,7 +593,7 @@ nil ; 逻辑假,或者空列表 ;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; ;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 -;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; +;; 注意反引号'`',逗号','以及'@'这三个符号; ;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 ;; 逗号“,”意味着解除引用(unquote,即开始求值); ;; “@”符号则表示将当前的参数插入到当前整个列表中。 diff --git a/zh-cn/csharp-cn.html.markdown b/zh-cn/csharp-cn.html.markdown new file mode 100644 index 00000000..a3cda5b3 --- /dev/null +++ b/zh-cn/csharp-cn.html.markdown @@ -0,0 +1,798 @@ +--- +language: c# +contributors: + - ["Irfan Charania", "https://github.com/irfancharania"] + - ["Max Yankov", "https://github.com/golergka"] + - ["Melvyn Laïly", "http://x2a.yt"] + - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] +translators: + - ["Jakukyo Friel", "http://weakish.github.io"] +filename: LearnCSharp-cn.cs +lang: zh-cn +--- + + +C#是一个优雅的、类型安全的面向对象语言。使用C#,开发者可以在.NET框架下构建安全、健壮的应用程序。 + +[更多关于C#的介绍](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx) + +```c# +// 单行注释以 // 开始 +/* +多行注释是这样的 +*/ +/// <summary> +/// XML文档注释 +/// </summary> + +// 声明应用用到的命名空间 +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Net; +using System.Threading.Tasks; +using System.IO; + +// 定义作用域,将代码组织成包 +namespace Learning +{ + // 每个 .cs 文件至少需要包含一个和文件名相同的类 + // 你可以不这么干,但是这样不好。 + public class LearnCSharp + { + // 基本语法 - 如果你以前用过 Java 或 C++ 的话,可以直接跳到后文「有趣的特性」 + public static void Syntax() + { + // 使用 Console.WriteLine 打印信息 + Console.WriteLine("Hello World"); + Console.WriteLine( + "Integer: " + 10 + + " Double: " + 3.14 + + " Boolean: " + true); + + // 使用 Console.Write 打印,不带换行符号 + Console.Write("Hello "); + Console.Write("World"); + + /////////////////////////////////////////////////// + // 类型和变量 + // + // 使用 <type> <name> 定义变量 + /////////////////////////////////////////////////// + + // Sbyte - 有符号 8-bit 整数 + // (-128 <= sbyte <= 127) + sbyte fooSbyte = 100; + + // Byte - 无符号 8-bit 整数 + // (0 <= byte <= 255) + byte fooByte = 100; + + // Short - 16-bit 整数 + // 有符号 - (-32,768 <= short <= 32,767) + // 无符号 - (0 <= ushort <= 65,535) + short fooShort = 10000; + ushort fooUshort = 10000; + + // Integer - 32-bit 整数 + int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647) + uint fooUint = 1; // (0 <= uint <= 4,294,967,295) + + // Long - 64-bit 整数 + long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) + ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615) + // 数字默认为 int 或 uint (取决于尺寸) + // 使用 L 标明变量值类型为long 或 ulong + + // Double - 双精度 64-bit IEEE 754 浮点数 + double fooDouble = 123.4; // 精度: 15-16 位 + + // Float - 单精度 32-bit IEEE 754 浮点数 + float fooFloat = 234.5f; // 精度: 7 位 + // 使用 f 标明变量值类型为float + + // Decimal - 128-bits 数据类型,比其他浮点类型精度更高 + // 适合财务、金融 + decimal fooDecimal = 150.3m; + + // 布尔值 - true & false + bool fooBoolean = true; // 或 false + + // Char - 单个 16-bit Unicode 字符 + char fooChar = 'A'; + + // 字符串 -- 和前面的基本类型不同,字符串不是值,而是引用。 + // 这意味着你可以将字符串设为null。 + string fooString = "\"escape\" quotes and add \n (new lines) and \t (tabs)"; + Console.WriteLine(fooString); + + // 你可以通过索引访问字符串的每个字符: + char charFromString = fooString[1]; // => 'e' + // 字符串不可修改: fooString[1] = 'X' 是行不通的; + + // 根据当前的locale设定比较字符串,大小写不敏感 + string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase); + + // 基于sprintf的字符串格式化 + string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2); + + // 日期和格式 + DateTime fooDate = DateTime.Now; + Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); + + // 使用 @ 符号可以创建跨行的字符串。使用 "" 来表示 " + string bazString = @"Here's some stuff +on a new line! ""Wow!"", the masses cried"; + + // 使用const或read-only定义常量 + // 常量在编译期演算 + const int HOURS_I_WORK_PER_WEEK = 9001; + + /////////////////////////////////////////////////// + // 数据结构 + /////////////////////////////////////////////////// + + // 数组 - 从0开始计数 + // 声明数组时需要确定数组长度 + // 声明数组的格式如下: + // <datatype>[] <var name> = new <datatype>[<array size>]; + int[] intArray = new int[10]; + + // 声明并初始化数组的其他方式: + int[] y = { 9000, 1000, 1337 }; + + // 访问数组的元素 + Console.WriteLine("intArray @ 0: " + intArray[0]); + // 数组可以修改 + intArray[1] = 1; + + // 列表 + // 列表比数组更常用,因为列表更灵活。 + // 声明列表的格式如下: + // List<datatype> <var name> = new List<datatype>(); + List<int> intList = new List<int>(); + List<string> stringList = new List<string>(); + List<int> z = new List<int> { 9000, 1000, 1337 }; // i + // <>用于泛型 - 参考下文 + + // 列表无默认值 + // 访问列表元素时必须首先添加元素 + intList.Add(1); + Console.WriteLine("intList @ 0: " + intList[0]); + + // 其他数据结构: + // 堆栈/队列 + // 字典 (哈希表的实现) + // 哈希集合 + // 只读集合 + // 元组 (.Net 4+) + + /////////////////////////////////////// + // 操作符 + /////////////////////////////////////// + Console.WriteLine("\n->Operators"); + + int i1 = 1, i2 = 2; // 多重声明的简写形式 + + // 算术直截了当 + Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3 + + // 取余 + Console.WriteLine("11%3 = " + (11 % 3)); // => 2 + + // 比较操作符 + Console.WriteLine("3 == 2? " + (3 == 2)); // => false + Console.WriteLine("3 != 2? " + (3 != 2)); // => true + Console.WriteLine("3 > 2? " + (3 > 2)); // => true + Console.WriteLine("3 < 2? " + (3 < 2)); // => false + Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true + Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true + + // 位操作符 + /* + ~ 取反 + << 左移(有符号) + >> 右移(有符号) + & 与 + ^ 异或 + | 或 + */ + + // 自增、自减 + int i = 0; + Console.WriteLine("\n->Inc/Dec-rementation"); + Console.WriteLine(i++); //i = 1. 事后自增 + Console.WriteLine(++i); //i = 2. 事先自增 + Console.WriteLine(i--); //i = 1. 事后自减 + Console.WriteLine(--i); //i = 0. 事先自减 + + /////////////////////////////////////// + // 控制结构 + /////////////////////////////////////// + Console.WriteLine("\n->Control Structures"); + + // 类似C的if语句 + int j = 10; + if (j == 10) + { + Console.WriteLine("I get printed"); + } + else if (j > 10) + { + Console.WriteLine("I don't"); + } + else + { + Console.WriteLine("I also don't"); + } + + // 三元表达式 + // 简单的 if/else 语句可以写成: + // <条件> ? <真> : <假> + string isTrue = (true) ? "True" : "False"; + + // While 循环 + int fooWhile = 0; + while (fooWhile < 100) + { + //迭代 100 次, fooWhile 0->99 + fooWhile++; + } + + // Do While 循环 + int fooDoWhile = 0; + do + { + //迭代 100 次, fooDoWhile 0->99 + fooDoWhile++; + } while (fooDoWhile < 100); + + //for 循环结构 => for(<初始条件>; <条件>; <步>) + for (int fooFor = 0; fooFor < 10; fooFor++) + { + //迭代10次, fooFor 0->9 + } + + // foreach循环 + // foreach 循环结构 => foreach(<迭代器类型> <迭代器> in <可枚举结构>) + // foreach 循环适用于任何实现了 IEnumerable 或 IEnumerable<T> 的对象。 + // .Net 框架下的集合类型(数组, 列表, 字典...) + // 都实现了这些接口 + // (下面的代码中,ToCharArray()可以删除,因为字符串同样实现了IEnumerable) + foreach (char character in "Hello World".ToCharArray()) + { + //迭代字符串中的所有字符 + } + + // Switch 语句 + // switch 适用于 byte、short、char和int 数据类型。 + // 同样适用于可枚举的类型 + // 包括字符串类, 以及一些封装了原始值的类: + // Character、Byte、Short和Integer。 + int month = 3; + string monthString; + switch (month) + { + case 1: + monthString = "January"; + break; + case 2: + monthString = "February"; + break; + case 3: + monthString = "March"; + break; + // 你可以一次匹配多个case语句 + // 但是你在添加case语句后需要使用break + // (否则你需要显式地使用goto case x语句) + case 6: + case 7: + case 8: + monthString = "Summer time!!"; + break; + default: + monthString = "Some other month"; + break; + } + + /////////////////////////////////////// + // 转换、指定数据类型 + /////////////////////////////////////// + + // 转换类型 + + // 转换字符串为整数 + // 转换失败会抛出异常 + int.Parse("123");//返回整数类型的"123" + + // TryParse会尝试转换类型,失败时会返回缺省类型 + // 例如 0 + int tryInt; + if (int.TryParse("123", out tryInt)) // Funciton is boolean + Console.WriteLine(tryInt); // 123 + + // 转换整数为字符串 + // Convert类提供了一系列便利转换的方法 + Convert.ToString(123); + // or + tryInt.ToString(); + } + + /////////////////////////////////////// + // 类 + /////////////////////////////////////// + public static void Classes() + { + // 参看文件尾部的对象声明 + + // 使用new初始化对象 + Bicycle trek = new Bicycle(); + + // 调用对象的方法 + trek.SpeedUp(3); // 你应该一直使用setter和getter方法 + trek.Cadence = 100; + + // 查看对象的信息. + Console.WriteLine("trek info: " + trek.Info()); + + // 实例化一个新的Penny Farthing + PennyFarthing funbike = new PennyFarthing(1, 10); + Console.WriteLine("funbike info: " + funbike.Info()); + + Console.Read(); + } // 结束main方法 + + // 终端程序 终端程序必须有一个main方法作为入口 + public static void Main(string[] args) + { + OtherInterestingFeatures(); + } + + // + // 有趣的特性 + // + + // 默认方法签名 + + public // 可见性 + static // 允许直接调用类,无需先创建实例 + int, //返回值 + MethodSignatures( + int maxCount, // 第一个变量,类型为整型 + int count = 0, // 如果没有传入值,则缺省值为0 + int another = 3, + params string[] otherParams // 捕获其他参数 + ) + { + return -1; + } + + // 方法可以重名,只要签名不一样 + public static void MethodSignature(string maxCount) + { + } + + //泛型 + // TKey和TValue类由用用户调用函数时指定。 + // 以下函数模拟了Python的SetDefault + public static TValue SetDefault<TKey, TValue>( + IDictionary<TKey, TValue> dictionary, + TKey key, + TValue defaultItem) + { + TValue result; + if (!dictionary.TryGetValue(key, out result)) + return dictionary[key] = defaultItem; + return result; + } + + // 你可以限定传入值的范围 + public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int> + { + // 我们可以进行迭代,因为T是可枚举的 + foreach (var item in toPrint) + // ittm为整数 + Console.WriteLine(item.ToString()); + } + + public static void OtherInterestingFeatures() + { + // 可选参数 + MethodSignatures(3, 1, 3, "Some", "Extra", "Strings"); + MethodSignatures(3, another: 3); // 显式指定参数,忽略可选参数 + + // 扩展方法 + int i = 3; + i.Print(); // 参见下面的定义 + + // 可为null的类型 对数据库交互、返回值很有用 + // 任何值类型 (i.e. 不为类) 添加后缀 ? 后会变为可为null的值 + // <类型>? <变量名> = <值> + int? nullable = null; // Nullable<int> 的简写形式 + Console.WriteLine("Nullable variable: " + nullable); + bool hasValue = nullable.HasValue; // 不为null时返回真 + // ?? 是用于指定默认值的语法糖 + // 以防变量为null的情况 + int notNullable = nullable ?? 0; // 0 + + // 变量类型推断 - 你可以让编译器推断变量类型: + var magic = "编译器确定magic是一个字符串,所以仍然是类型安全的"; + // magic = 9; // 不工作,因为magic是字符串,而不是整数。 + + // 泛型 + // + var phonebook = new Dictionary<string, string>() { + {"Sarah", "212 555 5555"} // 在电话簿中加入新条目 + }; + + // 调用上面定义为泛型的SETDEFAULT + Console.WriteLine(SetDefault<string,string>(phonebook, "Shaun", "No Phone")); // 没有电话 + // 你不用指定TKey、TValue,因为它们会被隐式地推导出来 + Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555 + + // lambda表达式 - 允许你用一行代码搞定函数 + Func<int, int> square = (x) => x * x; // 最后一项为返回值 + Console.WriteLine(square(3)); // 9 + + // 可抛弃的资源管理 - 让你很容易地处理未管理的资源 + // 大多数访问未管理资源 (文件操作符、设备上下文, etc.)的对象 + // 都实现了IDisposable接口。 + // using语句会为你清理IDisposable对象。 + using (StreamWriter writer = new StreamWriter("log.txt")) + { + writer.WriteLine("这里没有什么可疑的东西"); + // 在作用域的结尾,资源会被回收 + // (即使有异常抛出,也一样会回收) + } + + // 并行框架 + // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx + var websites = new string[] { + "http://www.google.com", "http://www.reddit.com", + "http://www.shaunmccarthy.com" + }; + var responses = new Dictionary<string, string>(); + + // 为每个请求新开一个线程 + // 在运行下一步前合并结果 + Parallel.ForEach(websites, + new ParallelOptions() {MaxDegreeOfParallelism = 3}, // max of 3 threads + website => + { + // Do something that takes a long time on the file + using (var r = WebRequest.Create(new Uri(website)).GetResponse()) + { + responses[website] = r.ContentType; + } + }); + + // 直到所有的请求完成后才会运行下面的代码 + foreach (var key in responses.Keys) + Console.WriteLine("{0}:{1}", key, responses[key]); + + // 动态对象(配合其他语言使用很方便) + dynamic student = new ExpandoObject(); + student.FirstName = "First Name"; // 不需要先定义类! + + // 你甚至可以添加方法(接受一个字符串,输出一个字符串) + student.Introduce = new Func<string, string>( + (introduceTo) => string.Format("Hey {0}, this is {1}", student.FirstName, introduceTo)); + Console.WriteLine(student.Introduce("Beth")); + + // IQUERYABLE<T> - 几乎所有的集合都实现了它, + // 带给你 Map / Filter / Reduce 风格的方法 + var bikes = new List<Bicycle>(); + bikes.Sort(); // Sorts the array + bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // 根据车轮数排序 + var result = bikes + .Where(b => b.Wheels > 3) // 筛选 - 可以连锁使用 (返回IQueryable) + .Where(b => b.IsBroken && b.HasTassles) + .Select(b => b.ToString()); // Map - 这里我们使用了select,所以结果是IQueryable<string> + + var sum = bikes.Sum(b => b.Wheels); // Reduce - 计算集合中的轮子总数 + + // 创建一个包含基于自行车的一些参数生成的隐式对象的列表 + var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles }); + // 很难演示,但是编译器在代码编译完成前就能推导出以上对象的类型 + foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome)) + Console.WriteLine(bikeSummary.Name); + + // ASPARALLEL + // 邪恶的特性 —— 组合了linq和并行操作 + var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); + // 以上代码会并发地运行。会自动新开线程,分别计算结果。 + // 适用于多核、大数据量的场景。 + + // LINQ - 将IQueryable<T>映射到存储,延缓执行 + // 例如 LinqToSql 映射数据库, LinqToXml 映射XML文档 + var db = new BikeRespository(); + + // 执行被延迟了,这对于查询数据库来说很好 + var filter = db.Bikes.Where(b => b.HasTassles); // 不运行查询 + if (42 > 6) // 你可以不断地增加筛选,包括有条件的筛选,例如用于“高级搜索”功能 + filter = filter.Where(b => b.IsBroken); // 不运行查询 + + var query = filter + .OrderBy(b => b.Wheels) + .ThenBy(b => b.Name) + .Select(b => b.Name); // 仍然不运行查询 + + // 现在运行查询,运行查询的时候会打开一个读取器,所以你迭代的是一个副本 + foreach (string bike in query) + Console.WriteLine(result); + + + + } + + } // 结束LearnCSharp类 + + // 你可以在同一个 .cs 文件中包含其他类 + + public static class Extensions + { + // 扩展函数 + public static void Print(this object obj) + { + Console.WriteLine(obj.ToString()); + } + } + // 声明类的语法: + // <public/private/protected/internal> class <类名>{ + // //数据字段, 构造器, 内部函数. + / // 在Java中函数被称为方法。 + // } + + public class Bicycle + { + // 自行车的字段、变量 + public int Cadence // Public: 任何地方都可以访问 + { + get // get - 定义获取属性的方法 + { + return _cadence; + } + set // set - 定义设置属性的方法 + { + _cadence = value; // value是被传递给setter的值 + } + } + private int _cadence; + + protected virtual int Gear // 类和子类可以访问 + { + get; // 创建一个自动属性,无需成员字段 + set; + } + + internal int Wheels // Internal:在同一程序集内可以访问 + { + get; + private set; // 可以给get/set方法添加修饰符 + } + + int _speed; // 默认为private: 只可以在这个类内访问,你也可以使用`private`关键词 + public string Name { get; set; } + + // enum类型包含一组常量 + // 它将名称映射到值(除非特别说明,是一个整型) + // enmu元素的类型可以是byte、sbyte、short、ushort、int、uint、long、ulong。 + // enum不能包含相同的值。 + public enum BikeBrand + { + AIST, + BMC, + Electra = 42, //你可以显式地赋值 + Gitane // 43 + } + // 我们在Bicycle类中定义的这个类型,所以它是一个内嵌类型。 + // 这个类以外的代码应当使用`Bicycle.Brand`来引用。 + + public BikeBrand Brand; // 声明一个enum类型之后,我们可以声明这个类型的字段 + + // 静态方法的类型为自身,不属于特定的对象。 + // 你无需引用对象就可以访问他们。 + // Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated); + static public int BicyclesCreated = 0; + + // 只读值在运行时确定 + // 它们只能在声明或构造器内被赋值 + readonly bool _hasCardsInSpokes = false; // read-only private + + // 构造器是创建类的一种方式 + // 下面是一个默认的构造器 + public Bicycle() + { + this.Gear = 1; // 你可以使用关键词this访问对象的成员 + Cadence = 50; // 不过你并不总是需要它 + _speed = 5; + Name = "Bontrager"; + Brand = BikeBrand.AIST; + BicyclesCreated++; + } + + // 另一个构造器的例子(包含参数) + public Bicycle(int startCadence, int startSpeed, int startGear, + string name, bool hasCardsInSpokes, BikeBrand brand) + : base() // 首先调用base + { + Gear = startGear; + Cadence = startCadence; + _speed = startSpeed; + Name = name; + _hasCardsInSpokes = hasCardsInSpokes; + Brand = brand; + } + + // 构造器可以连锁使用 + public Bicycle(int startCadence, int startSpeed, BikeBrand brand) : + this(startCadence, startSpeed, 0, "big wheels", true, brand) + { + } + + // 函数语法 + // <public/private/protected> <返回值> <函数名称>(<参数>) + + // 类可以为字段实现 getters 和 setters 方法 for their fields + // 或者可以实现属性(C#推荐使用这个) + // 方法的参数可以有默认值 + // 在有默认值的情况下,调用方法的时候可以省略相应的参数 + public void SpeedUp(int increment = 1) + { + _speed += increment; + } + + public void SlowDown(int decrement = 1) + { + _speed -= decrement; + } + + // 属性可以访问和设置值 + // 当只需要访问数据的时候,考虑使用属性。 + // 属性可以定义get和set,或者是同时定义两者 + private bool _hasTassles; // private variable + public bool HasTassles // public accessor + { + get { return _hasTassles; } + set { _hasTassles = value; } + } + + // 你可以在一行之内定义自动属性 + // 这个语法会自动创建后备字段 + // 你可以给getter或setter设置访问修饰符 + // 以便限制它们的访问 + public bool IsBroken { get; private set; } + + // 属性的实现可以是自动的 + public int FrameSize + { + get; + // 你可以给get或set指定访问修饰符 + // 以下代码意味着只有Bicycle类可以调用Framesize的set + private set; + } + + //显示对象属性的方法 + public virtual string Info() + { + return "Gear: " + Gear + + " Cadence: " + Cadence + + " Speed: " + _speed + + " Name: " + Name + + " Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") + + "\n------------------------------\n" + ; + } + + // 方法可以是静态的。通常用于辅助方法。 + public static bool DidWeCreateEnoughBycles() + { + // 在静态方法中,你只能引用类的静态成员 + return BicyclesCreated > 9000; + } // 如果你的类只需要静态成员,考虑将整个类作为静态类。 + + + } // Bicycle类结束 + + // PennyFarthing是Bicycle的一个子类 + class PennyFarthing : Bicycle + { + // (Penny Farthings是一种前轮很大的自行车。没有齿轮。) + + // 调用父构造器 + public PennyFarthing(int startCadence, int startSpeed) : + base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra) + { + } + + protected override int Gear + { + get + { + return 0; + } + set + { + throw new ArgumentException("你不可能在PennyFarthing上切换齿轮"); + } + } + + public override string Info() + { + string result = "PennyFarthing bicycle "; + result += base.ToString(); // 调用父方法 + return result; + } + } + + // 接口只包含成员的签名,而没有实现。 + interface IJumpable + { + void Jump(int meters); // 所有接口成员是隐式地公开的 + } + + interface IBreakable + { + bool Broken { get; } // 接口可以包含属性、方法和事件 + } + + // 类只能继承一个类,但是可以实现任意数量的接口 + { + int damage = 0; + + public void Jump(int meters) + { + damage += meters; + } + + public bool Broken + { + get + { + return damage > 100; + } + } + } + + /// <summary> + /// 连接数据库,一个 LinqToSql的示例。 + /// EntityFramework Code First 很棒 (类似 Ruby的 ActiveRecord, 不过是双向的) + /// http://msdn.microsoft.com/en-us/data/jj193542.aspx + /// </summary> + public class BikeRespository : DbSet + { + public BikeRespository() + : base() + { + } + + public DbSet<Bicycle> Bikes { get; set; } + } +} // 结束 Namespace +``` + +## 没有涉及到的主题 + + * Flags + * Attributes + * 静态属性 + * Exceptions, Abstraction + * ASP.NET (Web Forms/MVC/WebMatrix) + * Winforms + * Windows Presentation Foundation (WPF) + +## 扩展阅读 + + * [DotNetPerls](http://www.dotnetperls.com) + * [C# in Depth](http://manning.com/skeet2) + * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ](http://shop.oreilly.com/product/9780596519254.do) + * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) + * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) + * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) + * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) + * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) diff --git a/zh-cn/css-cn.html.markdown b/zh-cn/css-cn.html.markdown new file mode 100644 index 00000000..dc6dcc4f --- /dev/null +++ b/zh-cn/css-cn.html.markdown @@ -0,0 +1,212 @@ +--- +language: css +contributors: + - ["Mohammad Valipour", "https://github.com/mvalipour"] + - ["Marco Scannadinari", "https://github.com/marcoms"] +translators: + - ["Jakukyo Friel", "https://weakish.github.io"] +lang: zh-cn +filename: learncss-cn.css +--- + +早期的web没有样式,只是单纯的文本。通过CSS,可以实现网页样式和内容的分离。 + +简单来说,CSS可以指定HTML页面上的元素所使用的样式。 + +和其他语言一样,CSS有很多版本。最新的版本是CSS 3. CSS 2.0兼容性最好。 + +你可以使用[dabblet](http://dabblet.com/)来在线测试CSS的效果。 + +```css +/* 注释 */ + +/* #################### + ## 选择器 + ####################*/ + +/* 一般而言,CSS的声明语句非常简单。 */ +选择器 { 属性: 值; /* 更多属性...*/ } + +/* 选择器用于指定页面上的元素。 + +针对页面上的所有元素。 */ +* { color:red; } + +/* +假定页面上有这样一个元素 + +<div class='some-class class2' id='someId' attr='value' /> +*/ + +/* 你可以通过类名来指定它 */ +.some-class { } + +/* 给出所有类名 */ +.some-class.class2 { } + +/* 标签名 */ +div { } + +/* id */ +#someId { } + +/* 由于元素包含attr属性,因此也可以通过这个来指定 */ +[attr] { font-size:smaller; } + +/* 以及有特定值的属性 */ +[attr='value'] { font-size:smaller; } + +/* 通过属性的值的开头指定 */ +[attr^='val'] { font-size:smaller; } + +/* 通过属性的值的结尾来指定 */ +[attr$='ue'] { font-size:smaller; } + +/* 通过属性的值的部分来指定 */ +[attr~='lu'] { font-size:smaller; } + + +/* 你可以把这些全部结合起来,注意不同部分间不应该有空格,否则会改变语义 */ +div.some-class[attr$='ue'] { } + +/* 你也可以通过父元素来指定。*/ + +/* 某个元素是另一个元素的直接子元素 */ +div.some-parent > .class-name {} + +/* 或者通过该元素的祖先元素 */ +div.some-parent .class-name {} + +/* 注意,去掉空格后语义就不同了。 +你能说出哪里不同么? */ +div.some-parent.class-name {} + +/* 你可以选择某元素前的相邻元素 */ +.i-am-before + .this-element { } + +/* 某元素之前的同级元素(相邻或不相邻) */ +.i-am-any-before ~ .this-element {} + +/* 伪类允许你基于页面的行为指定元素(而不是基于页面结构) */ + +/* 例如,当鼠标悬停在某个元素上时 */ +:hover {} + +/* 已访问过的链接*/ +:visited {} + +/* 未访问过的链接*/ +:link {} + +/* 当前焦点的input元素 */ +:focus {} + + +/* #################### + ## 属性 + ####################*/ + +选择器 { + + /* 单位 */ + width: 50%; /* 百分比 */ + font-size: 2em; /* 当前字体大小的两倍 */ + width: 200px; /* 像素 */ + font-size: 20pt; /* 点 */ + width: 5cm; /* 厘米 */ + width: 50mm; /* 毫米 */ + width: 5in; /* 英尺 */ + + /* 颜色 */ + background-color: #F6E; /* 短16位 */ + background-color: #F262E2; /* 长16位 */ + background-color: tomato; /* 颜色名称 */ + background-color: rgb(255, 255, 255); /* rgb */ + background-color: rgb(10%, 20%, 50%); /* rgb 百分比 */ + background-color: rgba(255, 0, 0, 0.3); /* rgb 加透明度 */ + + /* 图片 */ + background-image: url(/path-to-image/image.jpg); + + /* 字体 */ + font-family: Arial; + font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */ + font-family: "Courier New", Trebuchet, Arial; /* 如果第一个 + 字体没找到,浏览器会使用第二个字体,一次类推 */ +} + +``` + +## 使用 + +CSS文件使用 `.css` 后缀。 + +```xml +<!-- 你需要在文件的 <head> 引用CSS文件 --> +<link rel='stylesheet' type='text/css' href='filepath/filename.css' /> + +<!-- 你也可以在标记中内嵌CSS。不过强烈建议不要这么干。 --> +<style> + 选择器 { 属性:值; } +</style> + +<!-- 也可以直接使用元素的style属性。 +这是你最不该干的事情。 --> +<div style='property:value;'> +</div> + +``` + +## 优先级 + +同一个元素可能被多个不同的选择器指定,因此可能会有冲突。 + +假定CSS是这样的: + +```css +/*A*/ +p.class1[attr='value'] + +/*B*/ +p.class1 {} + +/*C*/ +p.class2 {} + +/*D*/ +p {} + +/*E*/ +p { property: value !important; } + +``` + +然后标记语言为: + +```xml +<p style='/*F*/ property:value;' class='class1 class2' attr='value'> +</p> +``` + +那么将会按照下面的顺序应用风格: + + +* `E` 优先级最高,因为它使用了 `!important`,除非很有必要,尽量避免使用这个。 +* `F` 其次,因为它是嵌入的风格。 +* `A` 其次,因为它比其他指令更具体。 +* `C` 其次,虽然它的具体程度和`B`一样,但是它在`B`之后。 +* 接下来是 `B`。 +* 最后是 `D`。 + +## 兼容性 + +CSS2 的绝大部分特性兼容各种浏览器和设备。现在 CSS3 的兼容性也越来越好了。 +但是兼容性问题仍然是需要留意的一个问题。 + +[QuirksMode CSS](http://www.quirksmode.org/css/)是关于这方面最好的资源。 + +## 扩展阅读 + +* [理解CSS的风格优先级: 特定性, 继承和层叠](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) +* [QuirksMode CSS](http://www.quirksmode.org/css/) +* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown index d303c2e8..06f38d77 100644 --- a/zh-cn/elisp-cn.html.markdown +++ b/zh-cn/elisp-cn.html.markdown @@ -132,7 +132,7 @@ lang: zh-cn ;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
;; 用鼠标单击上面的buffer就会使光标移回。
-;; 或者你可以使用 `C-xo' 是的光标跳到另一个窗口中
+;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
;; 你可以用 `progn'命令将s式结合起来:
(progn
@@ -219,7 +219,7 @@ lang: zh-cn ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; 我们将一些名字存到列表中;
+;; 我们将一些名字存到列表中:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; 用 `car'来取得第一个名字:
diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown new file mode 100644 index 00000000..daee8d3c --- /dev/null +++ b/zh-cn/elixir-cn.html.markdown @@ -0,0 +1,399 @@ +--- +language: elixir +contributors: + - ["Joao Marques", "http://github.com/mrshankly"] +translators: + - ["lidashuang", "http://github.com/lidashuang"] +filename: learnelixir-cn.ex +lang: zh-cn +--- + +Elixir 是一门构建在Erlang VM 之上的函数式编程语言。Elixir 完全兼容 Erlang, +另外还提供了更标准的语法,特性。 + +```elixir + +# 这是单行注释, 注释以井号开头 + +# 没有多行注释 +# 但你可以堆叠多个注释。 + +# elixir shell 使用命令 `iex` 进入。 +# 编译模块使用 `elixirc` 命令。 + +# 如果安装正确,这些命令都会在环境变量里 + +## --------------------------- +## -- 基本类型 +## --------------------------- + +# 数字 +3 # 整型 +0x1F # 整型 +3.0 # 浮点类型 + +# 原子(Atoms),以 `:`开头 +:hello # atom + +# 元组(Tuple) 在内存中的存储是连续的 +{1,2,3} # tuple + +# 使用`elem`函数访问元组(tuple)里的元素: +elem({1, 2, 3}, 0) #=> 1 + +# 列表(list) +[1,2,3] # list + +# 可以用下面的方法访问列表的头尾元素: +[head | tail] = [1,2,3] +head #=> 1 +tail #=> [2,3] + +# 在elixir,就像在Erlang, `=` 表示模式匹配 (pattern matching) +# 不是赋值。 +# +# 这表示会用左边的模式(pattern)匹配右侧 +# +# 上面的例子中访问列表的头部和尾部就是这样工作的。 + +# 当左右两边不匹配时,会返回error, 在这个 +# 例子中,元组大小不一样。 +# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2} + +# 还有二进制类型 (binaries) +<<1,2,3>> # binary + +# 字符串(Strings) 和 字符列表(char lists) +"hello" # string +'hello' # char list + +# 多行字符串 +""" +I'm a multi-line +string. +""" +#=> "I'm a multi-line\nstring.\n" + +# 所有的字符串(Strings)以UTF-8编码: +"héllò" #=> "héllò" + +# 字符串(Strings)本质就是二进制类型(binaries), 字符列表(char lists)本质是列表(lists) +<<?a, ?b, ?c>> #=> "abc" +[?a, ?b, ?c] #=> 'abc' + +# 在 elixir中,`?a`返回 `a` 的 ASCII 整型值 +?a #=> 97 + +# 合并列表使用 `++`, 对于二进制类型则使用 `<>` +[1,2,3] ++ [4,5] #=> [1,2,3,4,5] +'hello ' ++ 'world' #=> 'hello world' + +<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>> +"hello " <> "world" #=> "hello world" + +## --------------------------- +## -- 操作符(Operators) +## --------------------------- + +# 一些数学运算 +1 + 1 #=> 2 +10 - 5 #=> 5 +5 * 2 #=> 10 +10 / 2 #=> 5.0 + +# 在 elixir 中,操作符 `/` 返回值总是浮点数。 + +# 做整数除法使用 `div` +div(10, 2) #=> 5 + +# 为了得到余数使用 `rem` +rem(10, 3) #=> 1 + +# 还有 boolean 操作符: `or`, `and` and `not`. +# 第一个参数必须是boolean 类型 +true and true #=> true +false or true #=> true +# 1 and true #=> ** (ArgumentError) argument error + +# Elixir 也提供了 `||`, `&&` 和 `!` 可以接受任意的类型 +# 除了`false` 和 `nil` 其它都会被当作true. +1 || true #=> 1 +false && 1 #=> false +nil && 20 #=> nil + +!true #=> false + +# 比较有: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` 和 `>` +1 == 1 #=> true +1 != 1 #=> false +1 < 2 #=> true + +# `===` 和 `!==` 在比较整型和浮点类型时更为严格: +1 == 1.0 #=> true +1 === 1.0 #=> false + +# 我们也可以比较两种不同的类型: +1 < :hello #=> true + +# 总的排序顺序定义如下: +# number < atom < reference < functions < port < pid < tuple < list < bit string + +# 引用Joe Armstrong :“实际的顺序并不重要, +# 但是,一个整体排序是否经明确界定是非常重要的。” + +## --------------------------- +## -- 控制结构(Control Flow) +## --------------------------- + +# `if` 表达式 +if false do + "This will never be seen" +else + "This will" +end + +# 还有 `unless` +unless true do + "This will never be seen" +else + "This will" +end + +# 在Elixir中,很多控制结构都依赖于模式匹配 + +# `case` 允许我们把一个值与多种模式进行比较: +case {:one, :two} do + {:four, :five} -> + "This won't match" + {:one, x} -> + "This will match and assign `x` to `:two`" + _ -> + "This will match any value" +end + +# 模式匹配时,如果不需要某个值,通用的做法是把值 匹配到 `_` +# 例如,我们只需要要列表的头元素: +[head | _] = [1,2,3] +head #=> 1 + +# 下面的方式效果一样,但可读性更好 +[head | _tail] = [:a, :b, :c] +head #=> :a + +# `cond` 可以检测多种不同的分支 +# 使用 `cond` 代替多个`if` 表达式嵌套 +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + 1 + 2 == 3 -> + "But I will" +end + +# 经常可以看到最后一个条件等于'true',这将总是匹配。 +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + true -> + "But I will (this is essentially an else)" +end + +# `try/catch` 用于捕获被抛出的值, 它也支持 `after` 子句, +# 无论是否值被捕获,after 子句都会被调用 +# `try/catch` +try do + throw(:hello) +catch + message -> "Got #{message}." +after + IO.puts("I'm the after clause.") +end +#=> I'm the after clause +# "Got :hello" + +## --------------------------- +## -- 模块和函数(Modules and Functions) +## --------------------------- + +# 匿名函数 (注意点) +square = fn(x) -> x * x end +square.(5) #=> 25 + + +# 也支持接收多个子句和卫士(guards). +# Guards 可以进行模式匹配 +# Guards 使用 `when` 关键字指明: +f = fn + x, y when x > 0 -> x + y + x, y -> x * y +end + +f.(1, 3) #=> 4 +f.(-1, 3) #=> -3 + +# Elixir 提供了很多内建函数 +# 在默认作用域都是可用的 +is_number(10) #=> true +is_list("hello") #=> false +elem({1,2,3}, 0) #=> 1 + +# 你可以在一个模块里定义多个函数,定义函数使用 `def` +defmodule Math do + def sum(a, b) do + a + b + end + + def square(x) do + x * x + end +end + +Math.sum(1, 2) #=> 3 +Math.square(3) #=> 9 + +# 保存到 `math.ex`,使用 `elixirc` 编译你的 Math 模块 +# 在终端里: elixirc math.ex + +# 在模块中可以使用`def`定义函数,使用 `defp` 定义私有函数 +# 使用`def` 定义的函数可以被其它模块调用 +# 私有函数只能在本模块内调用 +defmodule PrivateMath do + def sum(a, b) do + do_sum(a, b) + end + + defp do_sum(a, b) do + a + b + end +end + +PrivateMath.sum(1, 2) #=> 3 +# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) + + +# 函数定义同样支持 guards 和 多重子句: +defmodule Geometry do + def area({:rectangle, w, h}) do + w * h + end + + def area({:circle, r}) when is_number(r) do + 3.14 * r * r + end +end + +Geometry.area({:rectangle, 2, 3}) #=> 6 +Geometry.area({:circle, 3}) #=> 28.25999999999999801048 +# Geometry.area({:circle, "not_a_number"}) +#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1 + +#由于不变性,递归是Elixir的重要组成部分 +defmodule Recursion do + def sum_list([head | tail], acc) do + sum_list(tail, acc + head) + end + + def sum_list([], acc) do + acc + end +end + +Recursion.sum_list([1,2,3], 0) #=> 6 + +# Elixir 模块支持属性,模块内建了一些属性,你也可以自定义属性 +defmodule MyMod do + @moduledoc """ + 内置的属性,模块文档 + """ + + @my_data 100 # 自定义属性 + IO.inspect(@my_data) #=> 100 +end + +## --------------------------- +## -- 记录和异常(Records and Exceptions) +## --------------------------- + +# 记录就是把特定值关联到某个名字的结构体 +defrecord Person, name: nil, age: 0, height: 0 + +joe_info = Person.new(name: "Joe", age: 30, height: 180) +#=> Person[name: "Joe", age: 30, height: 180] + +# 访问name的值 +joe_info.name #=> "Joe" + +# 更新age的值 +joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] + +# 使用 `try` `rescue` 进行异常处理 +try do + raise "some error" +rescue + RuntimeError -> "rescued a runtime error" + _error -> "this will rescue any error" +end + +# 所有的异常都有一个message +try do + raise "some error" +rescue + x in [RuntimeError] -> + x.message +end + +## --------------------------- +## -- 并发(Concurrency) +## --------------------------- + +# Elixir 依赖于 actor并发模型。在Elixir编写并发程序的三要素: +# 创建进程,发送消息,接收消息 + +# 启动一个新的进程使用`spawn`函数,接收一个函数作为参数 + +f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245> +spawn(f) #=> #PID<0.40.0> + + +# `spawn` 函数返回一个pid(进程标识符),你可以使用pid向进程发送消息。 +# 使用 `<-` 操作符发送消息。 +# 我们需要在进程内接收消息,要用到 `receive` 机制。 + +defmodule Geometry do + def area_loop do + receive do + {:rectangle, w, h} -> + IO.puts("Area = #{w * h}") + area_loop() + {:circle, r} -> + IO.puts("Area = #{3.14 * r * r}") + area_loop() + end + end +end + +# 编译这个模块,在shell中创建一个进程,并执行 `area_looop` 函数。 +pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0> + +# 发送一个消息给 `pid`, 会在receive语句进行模式匹配 +pid <- {:rectangle, 2, 3} +#=> Area = 6 +# {:rectangle,2,3} + +pid <- {:circle, 2} +#=> Area = 12.56000000000000049738 +# {:circle,2} + +# shell也是一个进程(process), 你可以使用`self`获取当前 pid +self() #=> #PID<0.27.0> +``` + +## 参考文献 + +* [Getting started guide](http://elixir-lang.org/getting_started/1.html) from [elixir webpage](http://elixir-lang.org) +* [Elixir Documentation](http://elixir-lang.org/docs/master/) +* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert +* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong |