diff options
-rw-r--r-- | c.html.markdown | 4 | ||||
-rw-r--r-- | clojure-macros.html.markdown | 152 | ||||
-rw-r--r-- | de-de/css-de.html.markdown | 230 | ||||
-rw-r--r-- | es-es/git-es.html.markdown | 2 | ||||
-rw-r--r-- | fr-fr/lua-fr.html.markdown | 449 | ||||
-rw-r--r-- | fr-fr/objective-c-fr.html.markdown | 527 | ||||
-rw-r--r-- | hy.html.markdown | 174 | ||||
-rw-r--r-- | javascript.html.markdown | 14 | ||||
-rw-r--r-- | julia.html.markdown | 81 | ||||
-rw-r--r-- | ko-kr/go-kr.html.markdown | 314 | ||||
-rw-r--r-- | objective-c.html.markdown | 239 | ||||
-rw-r--r-- | php.html.markdown | 2 | ||||
-rw-r--r-- | racket.html.markdown | 40 | ||||
-rw-r--r-- | zh-cn/clojure-cn.html.markdown | 366 | ||||
-rw-r--r-- | zh-cn/go-cn.html.markdown | 16 | ||||
-rw-r--r-- | zh-cn/javascript-cn.html.markdown | 2 | ||||
-rw-r--r-- | zh-cn/php-cn.html.markdown | 6 | ||||
-rw-r--r-- | zh-cn/ruby-cn.html.markdown | 3 |
18 files changed, 2539 insertions, 82 deletions
diff --git a/c.html.markdown b/c.html.markdown index 84856b32..e55ff148 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -92,7 +92,7 @@ int main() { printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) - // If the argument of the `sizeof` operator an expression, then its argument + // If the argument of the `sizeof` operator is an expression, then its argument // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; @@ -376,7 +376,7 @@ int main() { // or when it's the argument of the `sizeof` or `alignof` operator: int arr[10]; int *ptr = arr; // equivalent with int *ptr = &arr[0]; - printf("%zu %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" + printf("%zu, %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" // Pointers are incremented and decremented based on their type diff --git a/clojure-macros.html.markdown b/clojure-macros.html.markdown new file mode 100644 index 00000000..8e671936 --- /dev/null +++ b/clojure-macros.html.markdown @@ -0,0 +1,152 @@ +--- +language: "clojure macros" +filename: learnclojuremacros.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +--- + +As with all Lisps, Clojure's inherent [homoiconicity](https://en.wikipedia.org/wiki/Homoiconic) +gives you access to the full extent of the language to write code-generation routines +called "macros". Macros provide a powerful way to tailor the language to your needs. + +Be careful though. It's considered bad form to write a macro when a function will do. +Use a macro only when you need control over when or if the arguments to a form will +be evaluated. + +You'll want to be familiar with Clojure. Make sure you understand everything in +[Clojure in Y Minutes](/docs/clojure/). + +```clojure +;; Define a macro using defmacro. Your macro should output a list that can +;; be evaluated as clojure code. +;; +;; This macro is the same as if you wrote (reverse "Hello World") +(defmacro my-first-macro [] + (list reverse "Hello World")) + +;; Inspect the result of a macro using macroexpand or macroexpand-1. +;; +;; Note that the call must be quoted. +(macroexpand '(my-first-macro)) +;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World") + +;; You can eval the result of macroexpand directly: +(eval (macroexpand '(my-first-macro))) +; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; But you should use this more succinct, function-like syntax: +(my-first-macro) ; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; You can make things easier on yourself by using the more succinct quote syntax +;; to create lists in your macros: +(defmacro my-first-quoted-macro [] + '(reverse "Hello World")) + +(macroexpand '(my-first-quoted-macro)) +;; -> (reverse "Hello World") +;; Notice that reverse is no longer function object, but a symbol. + +;; Macros can take arguments. +(defmacro inc2 [arg] + (list + 2 arg)) + +(inc2 2) ; -> 4 + +;; But, if you try to do this with a quoted list, you'll get an error, because +;; the argument will be quoted too. To get around this, clojure provides a +;; way of quoting macros: `. Inside `, you can use ~ to get at the outer scope +(defmacro inc2-quoted [arg] + `(+ 2 ~arg)) + +(inc2-quoted 2) + +;; You can use the usual destructuring args. Expand list variables using ~@ +(defmacro unless [arg & body] + `(if (not ~arg) + (do ~@body))) ; Remember the do! + +(macroexpand '(unless true (reverse "Hello World"))) +;; -> +;; (if (clojure.core/not true) (do (reverse "Hello World"))) + +;; (unless) evaluates and returns its body if the first argument is false. +;; Otherwise, it returns nil + +(unless true "Hello") ; -> nil +(unless false "Hello") ; -> "Hello" + +;; Used without care, macros can do great evil by clobbering your vars +(defmacro define-x [] + '(do + (def x 2) + (list x))) + +(def x 4) +(define-x) ; -> (2) +(list x) ; -> (2) + +;; To avoid this, use gensym to get a unique identifier +(gensym 'x) ; -> x1281 (or some such thing) + +(defmacro define-x-safely [] + (let [sym (gensym 'x)] + `(do + (def ~sym 2) + (list ~sym)))) + +(def x 4) +(define-x-safely) ; -> (2) +(list x) ; -> (4) + +;; You can use # within ` to produce a gensym for each symbol automatically +(defmacro define-x-hygenically [] + `(do + (def x# 2) + (list x#))) + +(def x 4) +(define-x-hygenically) ; -> (2) +(list x) ; -> (4) + +;; It's typical to use helper functions with macros. Let's create a few to +;; help us support a (dumb) inline arithmatic syntax +(declare inline-2-helper) +(defn clean-arg [arg] + (if (seq? arg) + (inline-2-helper arg) + arg)) + +(defn apply-arg + "Given args [x (+ y)], return (+ x y)" + [val [op arg]] + (list op val (clean-arg arg))) + +(defn inline-2-helper + [[arg1 & ops-and-args]] + (let [ops (partition 2 ops-and-args)] + (reduce apply-arg (clean-arg arg1) ops))) + +;; We can test it immediately, without creating a macro +(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5)) + +; However, we'll need to make it a macro if we want it to be run at compile time +(defmacro inline-2 [form] + (inline-2-helper form))) + +(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) +; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) + +(inline-2 (1 + (3 / 2) - (1 / 2) + 1)) +; -> 3 (actually, 3N, since the number got cast to a rational fraction with /) +``` + +### Further Reading + +Writing Macros from [Clojure for the Brave and True](http://www.braveclojure.com/) +[http://www.braveclojure.com/writing-macros/](http://www.braveclojure.com/writing-macros/) + +Official docs +[http://clojure.org/macros](http://clojure.org/macros) + +When to use macros? +[http://dunsmor.com/lisp/onlisp/onlisp_12.html](http://dunsmor.com/lisp/onlisp/onlisp_12.html) diff --git a/de-de/css-de.html.markdown b/de-de/css-de.html.markdown new file mode 100644 index 00000000..e03b3174 --- /dev/null +++ b/de-de/css-de.html.markdown @@ -0,0 +1,230 @@ +--- +language: css +contributors: + - ["Mohammad Valipour", "https://github.com/mvalipour"] +translators: + - ["Kyr", "http://github.com/kyrami"] +lang: de-de +--- + +In den frühen Tagen des Internets gab es keine visuellen Elemente, alles war nur reiner Text. Aber mit der Weiterentwickliung von Browsern wurden auch vollständig visuelle Webseiten zu einem Standard. +CSS ist die allgemeine Sprache, die dazu da ist, damit man den HTML-Code und die Designelemente von Webseiten (strikt) unterscheiden kann. + +Kurzgefasst, CSS ermöglicht es, verschiedene HTML-Elemente anzuvisieren und ihnen stilistische Eigenschaften zu geben. + +CSS hat wie jede andere Sprache viele Versionen. Hier fokussieren wir uns auf CSS2.0, welche nicht die neueste, aber die am weitesten verbreitete und unterstützte Version ist. + +**NOTE:** Weil die Ausgabe von CSS visuelle Eigenschaften sind, wirst du wahrscheinlich eine CSS-Sandbox wie [dabblet](http://dabblet.com/) benutzen müssen, um die Sprache richtig zu lernen. +In diesem Artikel wird am meisten auf generelle Hinweise und die Syntax geachtet. + + +```css +/* kommentare werden in sternchen-schrägstrichkombinationen gepackt (genauso wie hier!) */ + +/* #################### + ## SELEKTOREN + ####################*/ + +/* Eigentlich ist die häufigste Anwendungsweise von CSS sehr simpel */ +selektor { eigenschaft: wert; /* mehr eigenschaften...*/ } + +/* der selektor wird dazu benutzt, ein element auf der seite anzuvisieren + +Aber man kann auch alle Elemente auf einer Seite anvisieren! */ +* { color:red; } /* farbe:rot */ + +/* +Wenn wir so ein Element auf einer Seite haben: + +<div class='eine-klasse klasse2' id='eineId' attr='wert' /> +*/ + +/* kann man es so bei seiner klasse anvisieren */ +.eine-klasse { } + +/*oder bei beiden klassen! */ +.eine-klasse.klasse2 { } + +/* oder beim namen des tags */ +div { } + +/* oder bei seiner id */ +#eineId { } + +/* oder daran, dass es ein Attribut hat! */ +[attr] { font-size:smaller; } + +/* oder daran, dass das attribut einen bestimmten wert hat*/ +[attr='wert'] { font-size:smaller; } + +/* beginnt mit einem wert*/ +[attr^='wert'] { font-size:smaller; } + +/* oder endet mit */ +[attr$='rt'] { font-size:smaller; } + +/* oder sogar nur beinhaltet */ +[attr~='er'] { font-size:smaller; } + + +/* was aber noch wichtiger ist, ist dass man alle diese kombinieren +kann - man sollte nur mit der leerzeichensetzung vorsichtig sein, +da es mit einem leerzeichen zwei verschiedene selektoren wären*/ +div.eine-klasse[attr$='rt'] { } /* so ist es richtig */ + +/* man kann auch ein element daran festmachen, wie sich die übergeordneten +elemente verhalten!*/ + +/*es muss allerdings ein direktes kind sein */ +div.ein-elternteil > .klassen-name {} + +/* oder jeder seiner eltern in der struktur */ +/* das folgende heißt also, dass jedes element mit der klasse 'klassen-name' +und dem elternteil IN JEDER TIEFE ausgewählt wird */ +div.ein-elternteil .klassen-name {} + +/* achtung: dasselbe ohne das leerzeichen hat eine andere bedeutung, +kannst du mir sagen, was? */ +div.ein-elternteil.klassen-name {} + +/* man kann auch ein element nach seinem direkten vorherigen zwilling +auswählen */ +.ich-bin-vorher + .dieses-element { } + +/* oder jeden zwilling davor */ +.ich-kann-jeder-davor-sein ~ .dieses-element {} + +/* es gibt ein paar pseudoklassen, die sich basierend auf dem +seitenverhalten, nämlich nicht auf der seitenstruktur auswählen +lassen können */ + +/* zum beispiel, wenn über ein element mit dem mauszeiger gefahren wird */ +:hover {} + +/* oder einen bereits besuchten link*/ +:visited {} + +/* oder einen noch nicht besuchten link*/ +:link {} + +/* oder ein eingabeelement, das zurzeit im fokus steht */ +:focus {} + + +/* #################### + ## EIGENSCHAFTEN + ####################*/ + +selector { + + /* einheiten */ + width: 50%; /* in prozent */ + font-size: 2em; /* mal der derzeitigen schriftgröße */ + width: 200px; /* in pixeln */ + font-size: 20pt; /* in punkten */ + width: 5cm; /* in zentimetern */ + width: 50mm; /* in millimetern */ + width: 5in; /* in zoll */ + + /* farben */ + background-color: #F6E /* in kurzem hex */ + background-color: #F262E2 /* in langem hex */ + background-color: tomato /* kann auch eine genannte farbe sein */ + background-color: rgb(255, 255, 255) /* in rgb */ + background-color: rgb(10%, 20%, 50%) /* in rgb prozent */ + background-color: rgba(255, 0, 0, 0.3); /* in semi-transparentem rgb */ + + /* bilder */ + background-image: url(/pfad-zum-bild/image.jpg); + + /* schriften */ + font-family: Arial; + font-family: "Courier New"; /* wenn der name ein leerzeichen beinhält, kommt er in + apostrophe */ + font-family: "Courier New", Trebuchet, Arial; /* wenn der erste nicht gefunden wird, wird + der zweite benutzt, und so weiter */ +} + +``` + +## Benutzung + +speichere das css, das du benutzen willst mit der endung '.css'. + +```xml +<!-- du musst die css-datei im <head>-bereich der seite erwähnen --> +<link rel='stylesheet' type='text/css' href='filepath/filename.css' /> + +<!-- es geht allerdings auch direkt, wobei diese methode nicht +empfohlen ist --> +<style> + selector { property:value; } +</style> + +<!-- oder direkt am element (sollte aber gelassen werden) --> +<div style='property:value;'> +</div> + +``` + +## Wichtigkeit + +ein element kann von mehr als einem selektoren angezielt werden. +und kann auch eine eigenschaft mehr als einmal zugewiesen bekommen. +in diesen fällen gibt es regeln, die die wichtigkeit von selektoren einführen. + +wie haben dieses CSS: + +```css +/*A*/ +p.klasse1[attr='wert'] + +/*B*/ +p.klasse1 {} + +/*C*/ +p.klasse2 {} + +/*D*/ +p {} + +/*E*/ +p { property: wert !important; } + +``` + +und das folgende markup: + +```xml +<p style='/*F*/ property:value;' class='class1 class2' attr='value'> +</p> +``` + +die wichtigkeit der stile ist wie folgt: +(die wichtigkeit gilt nur für **eigenschaften**, nicht für ganze blöcke) + +* `E` hat die größte wichtigkeit wegen dem schlüsselwort `!important`. + man sollte diese form aber vermeiden. +* `F` ist als nächstes, da es direkt an dem element definiert ist. +* `A` ist als nächstes, da es "spezifischer" als alle anderen ist. + spezifischer = mehr zuweisungen: 1 tagname `p` + + klassenname `klasse1` + 1 attribut `attr='value'` +* `C` ist als nächstes obwohl es genau so ist wie `B` + aber es erscheint als letztes. +* dann ist `B` +* und als letztes `D`. + +## Kompabilität + +die meisten features von CSS sind in allen browsern verfügbar. +man sollte jedoch immer darauf achten, wenn man etwas mit CSS +programmiert. + +[QuirksMode CSS](http://www.quirksmode.org/css/) ist eine der besten quellen dafür. + +## Weiterlesen + +* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](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/es-es/git-es.html.markdown b/es-es/git-es.html.markdown index 0623b29b..5c9d3378 100644 --- a/es-es/git-es.html.markdown +++ b/es-es/git-es.html.markdown @@ -6,7 +6,7 @@ contributors: translator: - ["Raúl Ascencio", "http://rscnt.github.io"] filename: LearnGit.txt -language: es-es +lang: es-es --- diff --git a/fr-fr/lua-fr.html.markdown b/fr-fr/lua-fr.html.markdown new file mode 100644 index 00000000..922d6ebc --- /dev/null +++ b/fr-fr/lua-fr.html.markdown @@ -0,0 +1,449 @@ +--- +language: lua +filename: learnlua-fr.lua +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] +translators: + - ["Roland Yonaba", "http://github.com/Yonaba"] +lang: fr-fr +--- + +```lua +-- Les commentaires unilignes commencent par un double tiret. + +--[[ + Les doubles crochets à la suite du double tiret + permettent d'insérer des commentaires multilignes. +--]] + +---------------------------------------------------- +-- 1. Variables et contrôle d'exécution. +---------------------------------------------------- + +num = 42 -- Tous les nombres sont de type double. +-- Rassurez vous cependant, les doubles stockés sur 64-bits +-- en réservent 52 pour la valeur exacte des entiers. La +-- précision n'est donc pas un problème pour tout entier qui +-- peut être codé sur moins de 52 bits. + +s = 'walternate' -- Chaines de caractères immuables comme en Python. +t = "une chaine avec des guillemets doubles" +u = [[les double crochets permettent + d'avoir une chaine de caractères + sur plusieurs lignes.]] +t = nil -- Affecte la valeur nulle à t; Lua possède un ramasse-miettes + +-- Le do/end définit un bloc de code +while num < 50 do + num = num + 1 -- Pas d'opérateurs de type ++ ou +=. +end + +-- Les structures en if: +if num > 40 then + print('supérieur à 40') +elseif s ~= 'walternate' then -- ~= : est différent de. + -- Le test d'égalité se fait avec == comme en Python. + io.write('inférieur à 40\n') -- Écrit par defaut sur la sortie stdout. +else + -- Les variables sont globales par défaut. + thisIsGlobal = 5 -- le style camelCase est courant. + + -- Une variable locale est déclarée avec le mot-clé local: + local line = io.read() -- Permet de lire la ligne suivante dans stdin. + + -- .. est l'opérateur de concaténation: + print("L'hiver approche, " .. line) +end + +-- Les variables non définies reçoivent par défaut la valeur nil. +foo = anUnknownVariable -- Maintenant, foo = nil. + +aBoolValue = false + +-- Seuls nil et false sont des valeurs fausses. +-- Mais 0 et '' sont des valeurs vraies! +if not aBoolValue then print('etait faux') end + +-- L'évaluation du 'or' et du 'and' est court-circuité. +-- Comme avec les ternaires du C et du JS: a?b:c +ans = aBoolValue and 'oui' or 'non' --> 'non' + +karlSum = 0 +for i = 1, 100 do -- Les bornes sont incluses dans l'intervalle. + karlSum = karlSum + i +end + +-- Utilisez "100, 1, -1" pour la décrémentation: +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- En général, l'intervalle est début, fin[, pas]. + +-- Un autre type de boucle: +repeat + print('the way of the future') + num = num - 1 +until num == 0 + + +---------------------------------------------------- +-- 2. Fonctions. +---------------------------------------------------- + +function fib(n) + if n < 2 then return n end + return fib(n - 2) + fib(n - 1) +end + +-- Lua implémente les fermetures et les fonctions anonymes: +function adder(x) + -- La fonction retournée est créée lorsque adder est appelé + -- et elle se rappelle de la valeur de x. + return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- Les valeurs de retour, les appels de fonction, les assignations +-- supportent tous les listes qui peuvent ne pas correspondre en longueur. +-- Dans ce cas, les variables à assigner en supplément reçoivent nil +-- tandis que les valeurs à attribuer en supplément sont ignorées + +x, y = 1, 2 -- x = 1 et y = 2 +x, y, z = 1, 2 -- x = 1, y = 2 et z = nil +x, y, z = 1, 2, 3, 4 -- x = 1, y = 2, z = 3, et 4 est ignoré. + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> affiche "zaphod nil nil" +-- x = 4, y = 8, les valeurs 15 à 42 sont ignorées. + +-- Les fonctions sont des valeurs de première classe +-- et peuvent être locales/globales. +-- Les déclarations suivantes sont identiques: +function f(x) return x * x end +f = function (x) return x * x end + +-- Il en va de même pour les déclarations suivantes: +local function g(x) return math.sin(x) end +local g = function(x) return math.sin(x) end +-- Sauf que pour le dernier cas, même si local g = function(x) +-- est équivalent à local function g(x), il n'est pas possible +-- de faire appel à g à l'intérieur du corps de la fonction (récursion) + +-- À moins de déclarer la fonction auparavant: +local g; g = function (x) return math.sin(x) end + +-- À propos, les fonctions trigonométriques interprètent +-- leurs arguments en radians. +print(math.cos(math.pi)) -- affiche "-1" +print(math.sin(math.pi)) -- affiche "0" + +-- Lorsqu'une fonction est appelée avec un seul argument qui est une chaine, +-- les parenthèses peuvent être omises: +print 'hello' -- équivalent à print('hello'). + +-- Lorsqu'une fonction est appelée avec un seul argument qui est une table, +-- les parenthèses peuvent aussi être omises. +print {} -- équivalent à print({}). + + +---------------------------------------------------- +-- 3. Tables. +---------------------------------------------------- + +-- Tables = Seule structure de données en Lua; +-- Ce sont des listes assotiatives. +-- Elles sont similaires aux tables PHP ou aux objets JS : +-- des tables-dictionnaires que l'on peut utiliser en tant que listes. + +-- Tables en tant que dictionnaires: + +-- Les clés sont des chaines de caractères par défaut: +t = {key1 = 'valeur1', key2 = false} + +-- Elles peuvent être indexées avec la notation en point, comme en JS: +print(t.key1) -- Affiche "valeur1". +t.newKey = {} -- Ajoute une nouvelle paire clé/valeur. +t.key2 = nil -- Supprime la clé "key2" de la table. + +-- Notation littérale pour toute valeur non nulle en tant que clé: +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- affiche "tau" + +-- La correspondance des clés se fait par valeur pour +-- les nombres et les chaines, mais par référence pour les tables. +a = u['@!#'] -- a = 'qbert'. +b = u[{}] -- On pourrait s'attendre à 1729, mais l'on obtient nil: +-- b = nil car la clé utilisée n'est pas le même objet que celui +-- utilisé pour stocker la valeur originale 1729. + +-- Si une fonction prend en argument une seule table, l'on peut +-- omettre les parenthèses: +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'} -- Affiche 'Sonmi~451'. + +for key, val in pairs(u) do -- Parcours d'une table. + print(key, val) +end + +-- _G est une table spéciale contenant toutes les variables globales, +-- et donc elle même. +print(_G['_G'] == _G) -- Affiche 'true'. + +-- Tables en tant que listes: + +-- De manière implicite, les clés sont des nombres entiers: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do -- #v retourne la taille de la table v si elle est une liste. + print(v[i]) -- Attention, en Lua, les indices commencent à 1! +end +-- Il n'existe pas vraiment de type 'liste' en Lua, v est juste +-- une table avec des clés qui sont des nombres entiers consécutifs +-- commençant à 1. Lua le traite comme étant une liste. + +---------------------------------------------------- +-- 3.1 Métatables and métaméthodes. +---------------------------------------------------- + +-- Une table peut avoir une métatable qui confère à la table +-- un patron/prototype de conception (surcharge d'opération). Nous verrons +-- dans la suite comment les métatables imitent le prototypage du JS. + +f1 = {a = 1, b = 2} -- Représente la fraction a/b. +f2 = {a = 2, b = 3} + +-- Ceci créée une erreur: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) + local sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metafraction) +setmetatable(f2, metafraction) + +s = f1 + f2 -- appèle __add(f1, f2) de la métatable de f1 + +-- f1, f2 ne possèdent pas de clé qui pointent vers leur métatable, comme +-- avec les prototypes en JS. Mais l'on peut utiliser getmetatable(f1). +-- La métatable est une table normale avec des clés prédéfinies, comme __add. + +-- Mais la ligne suivante génère une erreur puisque s n'a pas de métatable: +-- t = s + s +-- En implémentant de l'orienté objet, comme nous le verrons par la suite, +-- le problème est résolu. + +-- Une clé __index dans une métatable mt surcharge l'indexation dans sa table t +-- si la clé est absente de cette table t: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal -- Affiche "gru"! merci à la métatable! + +-- Ainsi donc, un accès direct à une valeur dans une table via une clé +-- inexistante (ce qui normalement retourne "nil") conduira à exploiter +-- le champ __index de la métatable. Cela peut être récursif. + +-- Le champ __index peut aussi être une fonction (tbl, clé) +-- ce qui permet une gestion plus souple des indexations. + +-- Les clés __index, __add,... sont appelées métaméthodes. +-- En voici la liste complète: + +-- __add(a, b) pour a + b +-- __sub(a, b) pour a - b +-- __mul(a, b) pour a * b +-- __div(a, b) pour a / b +-- __mod(a, b) pour a % b +-- __pow(a, b) pour a ^ b +-- __unm(a) pour -a +-- __concat(a, b) pour a .. b +-- __len(a) pour #a +-- __eq(a, b) pour a == b +-- __lt(a, b) pour a < b +-- __le(a, b) pour a <= b +-- __index(a, b) <fn ou table> pour a.b +-- __newindex(a, b, c) pour a.b = c +-- __call(a, ...) pour a(...) + +---------------------------------------------------- +-- 3.2 Pseudo-orienté objet et héritage. +---------------------------------------------------- + +-- Lua n'implémente pas d'orienté objet par défaut. +-- Mais il reste possible d'imiter de plusieurs manières +-- le concept de "classe" grâce aux tables et aux métatables. + +-- L'explication pour l'exemple qui suit vient juste après. + +Dog = {} -- 1. + +function Dog:new() -- 2. + local newObj = {sound = 'woof'} -- 3. + self.__index = self -- 4. + return setmetatable(newObj, self) -- 5. +end + +function Dog:makeSound() -- 6. + print('Je dis: ' .. self.sound..'!') +end + +mrDog = Dog:new() -- 7. +mrDog:makeSound() -- 'Je dis: woof! -- 8. + +-- 1. Dog agit comme une classe; c'est une simple table. +-- 2. L'expression tbl:fn(...) est identique à +-- tbl.fn(self, ...) +-- La notation : permet de passer par défaut un premier +-- argument appelé "self" à la fonction tbl.fn +-- Voir 7 & 8 ci-après pour comprendre comment self prend +-- sa valeur. +-- 3. newObj sera une instance de la classe Dog. +-- 4. self = la classe instanciée. Souvent, self = Dog, mais +-- cela peut changer du fait de l'héritage. +-- newObj reçoit les fonctions de self si l'__index des +-- métatables de newObj et de self pointent vers self. +-- 5. Rappel: setmetatable retourne son premier argument. +-- 6. La notation : fonctionne comme au 2, mais cette fois, self +-- est une instance au lieu d'être une classe. +-- 7. Similaire à Dog.new(Dog), donc self = Dog dans new(). +-- 8. Similaire à mrDog.makeSound(mrDog); self = mrDog. + +---------------------------------------------------- + +-- Exemple d'héritage: + +LoudDog = Dog:new() -- 1. + +function LoudDog:makeSound() + local s = self.sound .. ' ' -- 2. + print(s .. s .. s..'!') +end + +seymour = LoudDog:new() -- 3. +seymour:makeSound() -- 'woof woof woof!' -- 4. + +-- 1. LoudDog reçoit les méthodes et les variables de Dog. +-- 2. self possède une clé 'sound', reçue de new(), voir 3. +-- 3. Similaire à LoudDog.new(LoudDog) et traduit en Dog.new(LoudDog), +-- puisque LoudDog ne possède pas de clé 'new', mais a une métatable +-- qui a la clé __index = Dog. +-- Résulat: la métatable de seymour est LoudDog, et +-- LoudDog.__index = LoudDog. Donc seymour.key deviendra soit égal à +-- seymour.key, LoudDog.key, Dog.key, selon le fait qu'il s'agira +-- de la première table ayant la clé 'key' en question, en remontant +-- dans la hiérarchie. +-- 4. La clé 'makeSound' est trouvée dans LoudDog; cela est similaire +-- à LoudDog.makeSound(seymour). + +-- Si besoin est, la méthode new() de la sous-classe est +-- identique à la méthode new() de sa classe mère: +function LoudDog:new() + local newObj = {} + -- Prépare self à être la superclasse de newObj: + self.__index = self + return setmetatable(newObj, self) +end + +---------------------------------------------------- +-- 4. Modules. +---------------------------------------------------- + + +--[[ Cette section est mise en commentaire afin que le reste du +-- ce script reste exécutable. +``` + +```lua +-- Supposons que le fichier mod.lua contienne ceci: +local M = {} + +local function sayMyName() + print('Hrunkner') +end + +function M.sayHello() + print('hello') + sayMyName() +end + +return M + +-- Un autre fichier peut exploiter le contenu défini dans mod.lua's: +local mod = require('mod') -- Exécute le fichier mod.lua. + +-- require est le moyen par défaut d'inclure des modules. +-- require agit comme: (si non trouvé en cache; voir ci-après) +local mod = (function () + <contenu de mod.lua> +end)() +-- Comme si le contenu de mod.lua était enveloppé dans le corps d'une fonction, +-- si bien que les variables locales contenues dans mod.lua sont +-- inaccessibles en dehors de ce module. + +-- Le code suivant fonctionne car mod = M (dans mod.lua): +mod.sayHello() -- Dis bonjour à Hrunkner. + +-- Le code suivant génère une erreur car sayMyName est local à mod.lua: +mod.sayMyName() -- erreur! + +-- Les valeurs retournées par require sont mises en cache, ce qui fait +-- qu'un module est toujours chargé une seule fois, même s'il est inclus +-- avec require à plusieurs reprises. + +-- Supposons que mod2.lua contienne le code "print('Hi!')". +local a = require('mod2') -- Affiche "Hi!" +local b = require('mod2') -- N'affiche rien; et a = b. + +-- dofile est identique à require, sauf qu'il ne fait pas de mise en cache: +dofile('mod2') --> Hi! +dofile('mod2') --> Hi! (le code de mod2.lua est encore exécuté) + +-- loadfile charge le contenu d'un fichier, sans l'exécuter. +f = loadfile('mod2') -- L'appel f() exécute le contenu de mod2.lua. + +-- loadstring est similaire à loadfile, mais pour les chaines de caractères. +g = loadstring('print(343)') -- Retourne une fonction. +g() -- Affiche 343; Rien n'est affiché avant cet appel. + +--]] + +``` +## Références + +*Les références qui suivent sont en Anglais.* + +Les sujets non abordés dans ce tutoriel sont couverts en intégralité par +les librairies standard: + +* La librairie <a href="http://lua-users.org/wiki/StringLibraryTutorial">string</a> +* La librairie <a href="http://lua-users.org/wiki/TableLibraryTutorial">table</a> +* La librairie <a href="http://lua-users.org/wiki/MathLibraryTutorial">math</a> +* La librairie <a href="http://lua-users.org/wiki/IoLibraryTutorial">io</a> +* La librairie <a href="http://lua-users.org/wiki/OsLibraryTutorial">os</a> + +Autres références complémentaires: + +* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua for programmers</a> +* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Courte de référence de Lua</a> +* <a href="http://www.lua.org/pil/contents.html">Programming In Lua</a> +* <a href="http://www.lua.org/manual/">Les manuels de référence Lua</a> + +A propos, ce fichier est exécutable. Sauvegardez-le sous le nom *learn.lua* et +exécutez-le avec la commande `lua learn.lua` ! + +Ce tutoriel a été originalement écrit pour <a href="tylerneylon.com">tylerneylon.com</a> et est aussi +disponible en tant que <a href="https://gist.github.com/tylerneylon/5853042">gist</a>. +Il a été traduit en français par Roland Yonaba (voir son <a href="http://github.com/Yonaba">github</a>). + +Amusez-vous bien avec Lua!
\ No newline at end of file diff --git a/fr-fr/objective-c-fr.html.markdown b/fr-fr/objective-c-fr.html.markdown new file mode 100644 index 00000000..b14b3a52 --- /dev/null +++ b/fr-fr/objective-c-fr.html.markdown @@ -0,0 +1,527 @@ +--- + +language: Objective-C +contributors: + - ["Eugene Yagrushkin", "www.about.me/yagrushkin"] + - ["Yannick Loriot", "https://github.com/YannickL"] + - ["Levi Bostian", "https://github.com/levibostian"] +translators: + - ["Yannick Loriot", "https://github.com/YannickL"] +filename: LearnObjectiveC.m + +--- + +L'Objective-C est un langage de programmation orienté objet réflexif principalement utilisé par Apple pour les systèmes d'exploitations Mac OS X et iOS et leurs frameworks respectifs, Cocoa et Cocoa Touch. + +```objective-c +// Les commentaires sur une seule ligne commencent par // + +/* +Les +commentaires +multi-lignes +ressemblent +à +ceci +*/ + +// #import permet d'importer les en-têtes d'autres fichiers +// Utilisez <> pour importer des fichiers globaux (en général des frameworks) +// Utilisez "" pour importer des fichiers locaux (du projet) +#import <Foundation/Foundation.h> +#import "MaClasse.h" + +// Si vous activez les modules dans les projets iOS >= 7 ou Mac OS X >= 10.9 +// dans Xcode 5, vous pouvez importer les frameworks comme cela : +@import Foundation; + +// Le point d'entrée de votre programme est une fonction qui s'appelle main +// et qui retourne un entier comme type +int main (int argc, const char * argv[]) +{ + // Créer un groupe de libération automatique de la mémoire pour l'ensemble + // du programme + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + // Si vous utilisez le comptage de référence automatique (ARC), utilisez + // @autoreleasepool à la place : + @autoreleasepool { + + // NSLog() permet d'afficher une chaine de caractères dans la console + // Affiche la chaine de caractères "Bonjour Tous Le Monde !" + NSLog(@"Bonjour tous le Monde !"); + + /////////////////////////////////////// + // Les Types & Les Variables + /////////////////////////////////////// + + // La déclaration de primitive + int maPrimitive1 = 1; + long maPrimitive2 = 234554664565; + + // La déclaration d'objet + // Il faut mettre un astérisque devant la déclaration d'objet fortement typé + MaClasse *monObject1 = nil; // Typage fort + id monObject2 = nil; // Typage faible + // 'description' est une méthode qui permet de retourner un aperçut de l'objet sous forme textuelle + // La méthode 'description' est appelée par défaut quand on utilise le paramètre '%@' + NSLog(@"%@ and %@", monObject1, [monObject2 description]); // Affiche "(null) et (null)" + + // Les chaines de caractères + NSString *chaineMonde = @"Monde"; + NSLog(@"Bonjour tous le %@ !", chaineMonde); // affiche => "Bonjour Tous Le Monde !" + // NSMutableString est une chaine mutable + NSMutableString *chaineMutable = [NSMutableString stringWithString:@"Bonjour tous le"]; + [chaineMutable appendString:@" Monde !"]; + NSLog(@"%@", chaineMutable); // affiche => "Bonjour Tous Le Monde !" + + // Les caractères + NSNumber *laLettreZSousFormeDeNombre = @'Z'; + char laLettreZ = [laLettreZSousFormeDeNombre charValue]; // ou 'Z' + NSLog(@"%c", laLettreZ); + + // Les nombres + NSNumber *nombreQuaranteDeux = @42; + int quaranteDeux = [nombreQuaranteDeux intValue]; // ou 42 + NSLog(@"%i", quaranteDeux); + + NSNumber *nombreQuaranteDeuxnonSigne = @42U; + unsigned int quaranteDeuxnonSigne = [nombreQuaranteDeuxnonSigne unsignedIntValue]; + NSLog(@"%u", fortyTwoUnsigned); + + NSNumber *nombreQuaranteDeuxCourt = [NSNumber numberWithShort:42]; + short quaranteDeuxCourt = [nombreQuaranteDeuxCourt shortValue]; // ou 42 + NSLog(@"%hi", fortyTwoShort); + + NSNumber *nombreQuaranteDeuxLong = @42L; + long quaranteDeuxLong = [nombreQuaranteDeuxLong longValue]; // ou 42 + NSLog(@"%li", fortyTwoLong); + + // Les nombres flottants + NSNumber *nombrePiFlottant = @3.141592654F; + float piFlottant = [nombrePiFlottant floatValue]; // ou 3.141592654f + NSLog(@"%f", piFlottant); // affiche => 3.141592654 + NSLog(@"%5.2f", piFlottant); // affiche => " 3.14" + + NSNumber *nombrePiDouble = @3.1415926535; + double piDouble = [nombrePiDouble doubleValue]; // ou 3.1415926535 + NSLog(@"%f", piDouble); + NSLog(@"%4.2f", piDouble); // affiche => "3.14" + + // NSDecimalNumber est une classe pour avoir plus de précision sur les nombres + // flottants et les doubles + NSDecimalNumber *decNumUn = [NSDecimalNumber decimalNumberWithString:@"10.99"]; + NSDecimalNumber *decNumDeux = [NSDecimalNumber decimalNumberWithString:@"5.002"]; + // NSDecimalNumber ne permet pas d'utiliser les opérations standards (+, -, *, /) + // Il faut utiliser les méthodes suivantes à la place : + [decNumUn decimalNumberByAdding:decNumDeux]; + [decNumUn decimalNumberBySubtracting:decNumDeux]; + [decNumUn decimalNumberByMultiplyingBy:decNumDeux]; + [decNumUn decimalNumberByDividingBy:decNumDeux]; + NSLog(@"%@", decNumUn); // affiche => 10.99 comme NSDecimalNumber est immuable + + // Les booléens + NSNumber *ouiNumber = @YES; + NSNumber *nonNumber = @NO; + // ou + BOOL ouiBool = YES; + BOOL nonBool = NO; + NSLog(@"%i", ouiBool); // affiche => 1 + + // Les listes + // Une liste peut contenir uniquement des objets + NSArray *uneListe = @[@1, @2, @3, @4]; + NSNumber *troisiemeNombre = uneListe[2]; + NSLog(@"Troisième nombre = %@", troisiemeNombre); // affiche "Troisième nombre = 3" + // NSMutableArray est une version mutable de NSArray + // Cela permet de modifier la liste en ajoutant de nouveaux éléments et en supprimant ou + // changeant de place des objets déjà présent + // C'est très pratique, mais pas aussi performant que l'utilisation de la classe NSArray + NSMutableArray *listeMutable = [NSMutableArray arrayWithCapacity:2]; + [listeMutable addObject:@"Bonjour tous le"]; + [listeMutable addObject:@"Monde"]; + [listeMutable removeObjectAtIndex:0]; + NSLog(@"%@", [listeMutable objectAtIndex:0]); // affiche => "Monde" + + // Les dictionnaires + // Un dictionnaire est un ensemble de clés : valeurs + NSDictionary *unDictionnaire = @{ @"cle1" : @"valeur1", @"cle2" : @"valeur2" }; + NSObject *valeur = unDictionnaire[@"Une clé"]; + NSLog(@"Objet = %@", valeur); // affiche "Objet = (null)" + // NSMutableDictionary est un dictionnaire mutable, c-à-d que l'on peut modifier + NSMutableDictionary *dictionnaireMutable = [NSMutableDictionary dictionaryWithCapacity:2]; + [dictionnaireMutable setObject:@"valeur1" forKey:@"cle1"]; + [dictionnaireMutable setObject:@"valeur2" forKey:@"cle2"]; + [dictionnaireMutable removeObjectForKey:@"cle1"]; + + // Les ensembles + // Un ensemble ne peut contenir de duplicatas contrairement aux NSArray + NSSet *ensemble = [NSSet setWithObjects:@"Salut", @"Salut", @"Monde", nil]; + NSLog(@"%@", ensemble); // affiche => {(Salut, Monde)} (Pas forcément dans le même ordre) + // NSMutableSet est un ensemble mutable + NSMutableSet *ensembleMutable = [NSMutableSet setWithCapacity:2]; + [ensembleMutable addObject:@"Salut"]; + [ensembleMutable addObject:@"Salut"]; + NSLog(@"%@", ensembleMutable); // affiche => {(Salut)} + + /////////////////////////////////////// + // Les Operateurs + /////////////////////////////////////// + + // Les opérateurs sont pareil qu'en C + // Par exemple : + 2 + 5; // => 7 + 4.2f + 5.1f; // => 9.3f + 3 == 2; // => 0 (NO) + 3 != 2; // => 1 (YES) + 1 && 1; // => 1 (et logique) + 0 || 1; // => 1 (ou logique) + ~0x0F; // => 0xF0 (négation bit à bit) + 0x0F & 0xF0; // => 0x00 (et bit à bit) + 0x01 << 1; // => 0x02 (décalage à gauche (par 1)) + + /////////////////////////////////////// + // Les Structures de Contrôle + /////////////////////////////////////// + + // Structure "Si-Sinon" (If-Else) + if (NO) + { + NSLog(@"Je ne suis jamais affiché"); + } else if (0) + { + NSLog(@"Je ne suis jamais affiché aussi"); + } else + { + NSLog(@"Je suis affiché"); + } + + // Structure "Selon" (Switch) + switch (2) + { + case 0: + { + NSLog(@"Je ne suis jamais affiché"); + } break; + case 1: + { + NSLog(@"Je ne suis jamais affiché aussi"); + } break; + default: + { + NSLog(@"Je suis affiché"); + } break; + } + + // Structure de boucle "Tant Que" (While) + int ii = 0; + while (ii < 4) + { + NSLog(@"%d,", ii++); // ii++ incrémente ii après avoir utilisé sa valeur + } // => affiche "0," + // "1," + // "2," + // "3," + + // Structure de boucle "Pour" (For) + int jj; + for (jj=0; jj < 4; jj++) + { + NSLog(@"%d,", jj); + } // => affiche "0," + // "1," + // "2," + // "3," + + // Structure de boucle "Pour Chaque" (Foreach) + NSArray *valeurs = @[@0, @1, @2, @3]; + for (NSNumber *valeur in valeurs) + { + NSLog(@"%@,", valeur); + } // => affiche "0," + // "1," + // "2," + // "3," + + // Structure "Essayer-Attraper-Finalement" (Try-Catch-Finally) + @try + { + @throw [NSException exceptionWithName:@"FileNotFoundException" + reason:@"Fichier non trouvé" userInfo:nil]; + } @catch (NSException * e) + { + NSLog(@"Une exception est survenue : %@", e); + } @finally + { + NSLog(@"Finalement"); + } // => affiche "Une exception est survenue : Fichier non trouvé" + // "Finalement" + + /////////////////////////////////////// + // Les Objets + /////////////////////////////////////// + + // Définis et créé une instance d'objet en allouant un espace mémoire puis en + // l'initialisant. Un objet n'est pas complétement fonctionnel tant que les deux + // étapes précédentes ne sont pas terminées + MaClass *monObjet = [[MaClass alloc] init]; + + // L'Objet en Objective-C est basé sur le principe d'envoie de message et non sur + // celui d'appel de méthode comme la plupart des autres langages + // C'est un détail important car cela veut dire que l'on peut envoyer un message + // à un objet qui ne possède pas la méthode demandée sans aucune incidence sur le + // fonctionnement du programme (aucune exception ne sera levée) + [myObject instanceMethodWithParameter:@"Steve Jobs"]; + + // Nettoie la mémoire qui a été utilisée dans le programme + [pool drain]; + + // Fin de l'@autoreleasepool + } + + // Fin du programme + return 0; +} + +/////////////////////////////////////// +// Les Classes et Les Fonctions +/////////////////////////////////////// + +// Déclaration d'une classe dans un en-tête de fichier (MaClasse.h) : +// La déclaration d'une classe en Objective-C commence par la déclaration de son interface : +// @interface NomDeLaClasse : NomDeLaClasseParent <ListeDesProtocoles> +// { +// type nom; // Déclaration d'une variable; +// } +// @property type nom; // Déclaration d'une propriété +// -/+ (type)nomDeLaMethode; // Déclaration d'une methode +// @end // Termine la déclaration +// NSObject est la classe de base (super classe) en Objective-C +@interface MaClasse : NSObject <MonProtocole> +{ + int nombre; // Accès protégé par défaut (équivalent à '@protected int nombre;') + @private id donnee; // Accès privé (il est plus pratique de le faire dans l'implémentation) + NSString *nom; +} +// Les propriétés permettent de générer les accésseurs/affecteurs publiques à la compilation +// Par défaut, le nom de l'affecteur est la chaine 'set' suivi par le nom de la @property +@property int propInt; // Nom de l'affecteur = 'setPropInt' +@property (copy) id copyId; // (copy) => Copie l'objet pendant l'affectation +// (readonly) => Ne peut pas affecté la variable en dehors de l'@interface +// Il faut utiliser le mot clé '@synthesize' dans l'@implementation pour créer l'accésseur +@property (readonly) NSString *roString; +// Vous pouvez aussi personnaliser les noms des accésseurs ou des affecteurs +@property (getter=longeurGet, setter=longeurSet:) int longeur; + +// Methodes ++/- (TypeDeRetour)signatureDeLaMethode:(TypeDuParametre *)nomDuParametre; + +// '+' signifie que c'est une méthode de classe (statique) : ++ (NSString *)methodeDeClasse; ++ (MaClasse *)maClasseDepuisLaHauteur:(NSNumber *)hauteurParDefaut; + +// '-' pour les méthodes d'instances : +- (NSString *)methodeInstanceAvecUnParametre:(NSString *)string; +- (NSNumber *)methodeInstanceAvecUnParametre:(NSString*)string puisUnDeuxieme:(NSNumber *)number; + +// Contructeur avec des arguments : +- (id)initAvecDistance:(int)distanceParDefault; +// Les méthodes en Objective-C sont très descriptives + +@end // Fin de l'interface + + +// Voici un exemple d'utilisation de MaClasse +MaClasse *maClasse = [[MaClasse alloc] init]; // créer une instance de MaClasse +[maClasse setNombre:10]; +NSLog(@"%d", [maClasse nombre]); // affiche => 10 +[myClass longeurSet:32]; +NSLog(@"%i", [maClasse longeurGet]); // affiche => 32 +// Pour des raisons pratiques vous pouvez aussi utiliser la notation en point pour accéder aux +// variables d'instances : +maClasse.nombre = 45; +NSLog(@"%i", maClasse.nombre); // maClasse => 45 + +// Pour appeler une méthode de classe : +NSString *s1 = [MaClasse methodeDeClasse]; +MaClasse *m2 = [MaClasse maClasseDepuisLaHauteur:38]; + +// Pour appeler une méthode d'instance : +MaClasse *maClasse = [[MaClasse alloc] init]; // Créer une instance de MaClasse +NSString *stringDepuisUneInstanceDeMethode = [maClasse methodeInstanceAvecUnParametre:@"Salut"]; + +// Les sélecteurs sont un moyen de décrire les méthodes dynamiquement +// Ils sont utilisés pour appeler des méthodes de classe et avoir des pointeurs de fonctions +// facilement manipulable +// SEL est un type de donnée et @selector retourne un selecteur à partir d'un nom de methode +SEL selecteur = @selector(methodeInstanceAvecUnParametre:puisUnDeuxieme:); +if ([maClasse respondsToSelector:selecteur]) { // Vérifie si la classe possède la méthode + // Met les arguments de la méthode dans un seul objet pour l'envoyer via la fonction + // performSelector:withObject: + NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil]; + [myClass performSelector:selectorVar withObject:arguments]; // Appele la méthode via le sélecteur +} +else { + // NSStringFromSelector() retourne une chaine de caractères à partir d'un sélecteur + NSLog(@"MaClasse ne possède pas de méthode : %@", NSStringFromSelector(selecteur)); +} + +// Le fichier d'implémentation de la classe MaClasse (MaClasse.m) doit commencer comme ceci : +@implementation MaClasse { + long distance; // Variable d'instance privée (équivalent à @private dans l'interface) + NSNumber hauteur; +} + +// Pour accéder à une variable depuis l'implémentation on peut utiliser le _ (tiret bas) devant le nom +// de la variable : +_nombre = 5; +// Accès d'une variable définie dans le fichier d'implémentation : +distance = 18; +// Pour utiliser la variable définie par l'intermédiaire de @property, il faut utiliser @synthesize +// qui permet de créer les affecteurs et les accésseurs correspondants : +@synthesize roString = _roString; // _roString est maintenant disponible dans l'implementation + +// A l'inverse dela méthode 'init' qui est appelée lors de la création d'un objet, la fonction +// 'dealloc' est appelée quand l'objet est supprimé +- (void)dealloc +{ + [hauteur release]; // Si vous n'utilisez pas ARC, pensez bien à supprimer l'objet + [super dealloc]; // et à appeler la méthode 'dealloc' de la classe parent +} + +// Les constructeurs sont des fonctions qui permettent d'instancier un objet +// 'init' est le constructeur par défaut en Objective-C +- (id)init +{ + if ((self = [super init])) // 'super' est utilisé pour appeler la méthode de la classe parent + { + self.count = 1; // 'self' permet d'appeler la méthode de l'instance courante + } + return self; +} + +// Vous pouvez aussi créer des constructeurs avec des arguments +// Attention : chaque nom de constructeur doit absolument commencer par 'init' +- (id)initAvecUneDistance:(int)distanceParDefault +{ + if ((self = [super init])) + { + distance = distanceParDefault; + return self; + } +} + +// Implémentation d'une méthode de classe ++ (NSString *)methodDeClasse +{ + return [[self alloc] init]; +} + ++ (MaClasse *)maClasseDepuisUneHauteur:(NSNumber *)hauteurParDefaut +{ + hauteur = hauteurParDefaut; + return [[self alloc] init]; +} + +// Implémentation d'une méthode d'instance +- (NSString *)methodeInstanceAvecUnParametre:(NSString *)string +{ + return @"Ma chaine de caractère"; +} + +- (NSNumber *)methodeInstanceAvecUnParametre:(NSString*)string puisUnDeuxieme:(NSNumber *)number +{ + return @42; +} + +// Pour créer une méthode privée, il faut la définir dans l'implementation et non pas dans +// l'interface +- (NSNumber *)methodePrivee +{ + return @72; +} + +[self methodePrivee]; // Appel de la méthode privée + +// Implémentation d'une méthode qui est déclarée dans <MonProtocole> +- (void)methodeDuProtocole +{ + // expressions +} + +@end // Fin de l'implémentation + +/* + * Un protocole déclare des méthodes et propriétés que chaque implémentation doit avoir afin de se + * conformer à celui-ci + * Un protocole n'est pas une classe, c'est juste une interface + */ +@protocol MonProtocole + - (void)methodeDuProtocole; +@end + + +/////////////////////////////////////// +// Gestion de la mémoire +/////////////////////////////////////// +/* +À chaque fois qu'un objet est créé dans l'application, un bloc mémoire doit être alloué. +Quand l'application en a fini avec cet objet, la mémoire doit être libérée afin d'éviter les fuites +mémoires +Il n'y a pas de ramasse-miettes en Objective-C contrairement à Java par exemple. La gestion de la +mémoire repose sur le comptage de référence qui, pour chaque objet, assigne un compteur qui permet +de connaitre le nombre de référence qui l'utilise. + +Le principe est le suivant : +Lorsque l'objet est créé, le compteur est initialisé à 1. Quand une instance détient un objet, le +compteur est incrémenté de un. Quand l'objet est libéré, le compteur est décrémenté de un. Au moment +où le compteur arrive à zéro, l'objet est supprimé de la mémoire + +Une bonne pratique à suivre quand on travaille avec des objets est la suivante : +(1) créer un objet, (2) utiliser l'objet, (3) supprimer l'objet de la mémoire +*/ + +MaClasse *classeVar = [MyClass alloc]; // 'alloc' incrémente le compteur de référence +[classeVar release]; // Décrémente le compteur de rérence +// 'retain' incrémente le compteur de référence +// Si 'classeVar' est libéré, l'objet reste en mémoire car le compteur de référence est non nul +MaClasse *nouvelleVar = [classVar retain]; +[classeVar autorelease]; // Supprime l'appartenance de l'objet à la fin du bloc + +// Les @property peuvent utiliser 'retain' et 'assign' +@property (retain) MaClasse *instance; // Libère l'ancienne valeur et retient la nouvelle +@property (assign) NSSet *set; // Pointeur vers la valeur sans retenir/libérer l'ancienne valeur + +// Automatic Reference Counting (ARC) +// La gestion de la mémoire étant pénible, depuis iOS 4 et Xcode 4.2, Apple a introduit le comptage de +// référence automatique (Automatic Reference Counting en anglais) +// ARC est une fonctionnalité du compilateur qui permet d'ajouter les 'retain', 'release' et 'autorelease' +// automatiquement. Cela veut dire que lorsque vous utilisez ARC vous ne devez plus utiliser ces mot-clés +MaClasse *arcMaClasse = [[MaClasse alloc] init]; +// ... code utilisant arcMaClasse +// Sans ARC, vous auriez dû appeler [arcMaClasse release] après avoir utilisé l'objet. Mais avec ARC +// activé il n'est plus nécessaire de le faire car le compilateur ajoutera l'expréssion automatiquement +// pour vous + +// Les mots clés 'assign' et 'retain', avec ARC sont respectivement remplacé par 'weak' et 'strong' +@property (weak) MaClasse *weakVar; // 'weak' ne retient pas l'objet. Si le compteur de référence +// descend à zero, weakVar sera automatiquement mis à nil +@property (strong) MaClasse *strongVar; // 'strong' prend possession de l'objet comme le ferait avec +// le mot-clé 'retain' + +// Pour l'instanciation des variables (en dehors de @property), vous pouvez utiliser les instructions +// suivantes : +__strong NSString *strongString; // Par défaut. La variable est retenue en mémoire jusqu'à la fin +// de sa portée +__weak NSSet *weakSet; // Maintient une référence vers l'objet sans incrémenter son compteur de référence : +// Lorsque l'objet sera supprimé, weakSet sera mis à nil automatiquement +__unsafe_unretained NSArray *unsafeArray; // Comme __weak, mais la variable n'est pas mis à nil quand +// l'objet est supprimé + +``` +## Lectures Complémentaires + +[La Page Wikipedia de l'Objective-C](http://fr.wikipedia.org/wiki/Objective-C) + +[iOS pour les écoliers : Votre première app iOS](http://www.raywenderlich.com/fr/39272/ios-pour-les-ecoliers-votre-premiere-app-ios-partie-12) + +[Programming with Objective-C. Apple PDF book](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf)
\ No newline at end of file diff --git a/hy.html.markdown b/hy.html.markdown new file mode 100644 index 00000000..04bd05c9 --- /dev/null +++ b/hy.html.markdown @@ -0,0 +1,174 @@ +--- +language: hy +filename: learnhy.hy +contributors: + - ["Abhishek L", "http://twitter.com/abhishekl"] +--- + +Hy is a lisp dialect built on top of python. This is achieved by +converting hy code to python's abstract syntax tree (ast). This allows +hy to call native python code or python to call native hy code as well + +This tutorial works for hy ≥ 0.9.12 + +```clojure +;; this gives an gentle introduction to hy for a quick trial head to +;; http://try-hy.appspot.com +;; +; Semicolon comments, like other LISPS + +;; s-expression basics +; lisp programs are made of symbolic expressions or sexps which +; resemble +(some-function args) +; now the quintessential hello world +(print "hello world") + +;; simple data types +; All simple data types are exactly similar to their python counterparts +; which +42 ; => 42 +3.14 ; => 3.14 +True ; => True +4+10j ; => (4+10j) a complex number + +; lets start with some really simple arithmetic +(+ 4 1) ;=> 5 +; the operator is applied to all arguments, like other lisps +(+ 4 1 2 3) ;=> 10 +(- 2 1) ;=> 1 +(* 4 2) ;=> 8 +(/ 4 1) ;=> 4 +(% 4 2) ;=> 0 the modulo operator +; power is represented by ** operator like python +(** 3 2) ;=> 9 +; nesting forms will do the expected thing +(+ 2 (* 4 2)) ;=> 10 +; also logical operators and or not and equal to etc. do as expected +(= 5 4) ;=> False +(not (= 5 4)) ;=> True + +;; variables +; variables are set using setv, variable names can use utf-8 except +; for ()[]{}",'`;#| +(setv a 42) +(setv π 3.14159) +(def *foo* 42) +;; other container data types +; strings, lists, tuples & dicts +; these are exactly same as python's container types +"hello world" ;=> "hello world" +; string operations work similar to python +(+ "hello " "world") ;=> "hello world" +; lists are created using [], indexing starts at 0 +(setv mylist [1 2 3 4]) +; tuples are immutable data structures +(setv mytuple (, 1 2)) +; dictionaries are key value pairs +(setv dict1 {"key1" 42 "key2" 21}) +; :name can be used to define keywords in hy which can be used for keys +(setv dict2 {:key1 41 :key2 20}) +; use `get' to get the element at an index/key +(get mylist 1) ;=> 2 +(get dict1 "key1") ;=> 42 +; Alternatively if keywords were used they can directly be called +(:key1 dict2) ;=> 41 + +;; functions and other program constructs +; functions are defined using defn, the last sexp is returned by default +(defn greet [name] + "A simple greeting" ; an optional docstring + (print "hello " name)) + +(greet "bilbo") ;=> "hello bilbo" + +; functions can take optional arguments as well as keyword arguments +(defn foolist [arg1 &optional [arg2 2]] + [arg1 arg2]) + +(foolists 3) ;=> [3 2] +(foolists 10 3) ;=> [10 3] + +; anonymous functions are created using `fn' or `lambda' constructs +; which are similiar to `defn' +(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16] + +;; Sequence operations +; hy has some builtin utils for sequence operations etc. +; retrieve the first element using `first' or `car' +(setv mylist [1 2 3 4]) +(setv mydict {"a" 1 "b" 2}) +(first mylist) ;=> 1 + +; slice lists using slice +(slice mylist 1 3) ;=> [2 3] + +; get elements from a list or dict using `get' +(get mylist 1) ;=> 2 +(get mydict "b") ;=> 2 +; list indexing starts from 0 same as python +; assoc can set elements at keys/indexes +(assoc mylist 2 10) ; makes mylist [1 2 10 4] +(assoc mydict "c" 3) ; makes mydict {"a" 1 "b" 2 "c" 3} +; there are a whole lot of other core functions which makes working with +; sequences fun + +;; Python interop +;; import works just like in python +(import datetime) +(import [functools [partial reduce]]) ; imports fun1 and fun2 from module1 +(import [matplotlib.pyplot :as plt]) ; doing an import foo as bar +; all builtin python methods etc. are accessible from hy +; a.foo(arg) is called as (.foo a arg) +(.split (.strip "hello world ")) ;=> ["hello" "world"] + +;; Conditionals +; (if condition (body-if-true) (body-if-false) +(if (= passcode "moria") + (print "welcome") + (print "Speak friend, and Enter!")) + +; nest multiple if else if clauses with cond +(cond + [(= someval 42) + (print "Life, universe and everything else!")] + [(> someval 42) + (print "val too large")] + [(< someval 42) + (print "val too small")]) + +; group statements with do, these are executed sequentially +; forms like defn have an implicit do +(do + (setv someval 10) + (print "someval is set to " someval)) ;=> 10 + +; create lexical bindings with `let', all variables defined thusly +; have local scope +(let [[nemesis {"superman" "lex luther" + "sherlock" "moriarty" + "seinfeld" "newman"}]] + (for [(, h v) (.items nemesis)] + (print (.format "{0}'s nemesis was {1}" h v)))) + +;; classes +; classes are defined in the following way +(defclass Wizard [object] + [[--init-- (fn [self spell] + (setv self.spell spell) ; init the spell attr + None)] + [get-spell (fn [self] + self.spell)]]) + +;; do checkout hylang.org +``` + +### Further Reading + +This tutorial is just a very basic introduction to hy/lisp/python. + +Hy docs are here: [http://hy.readthedocs.org](http://hy.readthedocs.org) + +Hy's Github repo: [http://github.com/hylang/hy](http://github.com/hylang/hy) + +On freenode irc #hy, twitter hashtag #hylang diff --git a/javascript.html.markdown b/javascript.html.markdown index 7fb7ba55..85c5d817 100644 --- a/javascript.html.markdown +++ b/javascript.html.markdown @@ -5,7 +5,7 @@ contributors: filename: javascript.js --- -Javascript was created by Netscape's Brendan Eich in 1995. It was originally +JavaScript was created by Netscape's Brendan Eich in 1995. It was originally intended as a simpler scripting language for websites, complimenting the use of Java for more complex web applications, but its tight integration with Web pages and built-in support in browsers has caused it to become far more common than @@ -37,7 +37,7 @@ doStuff() /////////////////////////////////// // 1. Numbers, Strings and Operators -// Javascript has one number type (which is a 64-bit IEEE 754 double). +// JavaScript has one number type (which is a 64-bit IEEE 754 double). // As with Lua, don't freak out about the lack of ints: doubles have a 52-bit // mantissa, which is enough to store integers up to about 9✕10¹⁵ precisely. 3; // = 3 @@ -116,7 +116,7 @@ undefined; // used to indicate a value is not currently present (although /////////////////////////////////// // 2. Variables, Arrays and Objects -// Variables are declared with the var keyword. Javascript is dynamically typed, +// Variables are declared with the var keyword. JavaScript is dynamically typed, // so you don't need to specify type. Assignment uses a single = character. var someVar = 5; @@ -175,14 +175,14 @@ myObj.myFourthKey; // = undefined var count = 1; if (count == 3){ // evaluated if count is 3 -} else if (count == 4) { +} else if (count == 4){ // evaluated if count is 4 } else { // evaluated if it's not either 3 or 4 } // As does while. -while (true) { +while (true){ // An infinite loop! } @@ -327,7 +327,7 @@ var anotherFunc = function(s){ } anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" -// The 'apply' function is nearly identical, but takes an array for an argument list. +// The 'apply' function is nearly identical, but takes an array for an argument list. anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" @@ -477,7 +477,7 @@ 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) -[Javascript Garden](http://bonsaiden.github.io/JavaScript-Garden/) is an in-depth +[JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/) is an in-depth guide of all the counter-intuitive parts of the language. In addition to direct contributors to this article, some content is adapted diff --git a/julia.html.markdown b/julia.html.markdown index 4b946d46..3bc660cf 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -427,7 +427,7 @@ 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"=>"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") @@ -560,7 +560,7 @@ type Panther <: Cat # Panther is also a subtype of Cat Panther() = new("green") # Panthers will only have this constructor, and no default constructor. end -# Using inner constructors, like Panter does, gives you control +# Using inner constructors, like Panther does, gives you control # over how values of the type can be created. # When possible, you should use outer constructors rather than inner ones. @@ -657,6 +657,83 @@ fight(Lion("RAR"),Lion("brown","rarrr")) #=> prints The victorious cat says rarr 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 + +# Under the hood +# You can take a look at the llvm and the assembly code generated. + +square_area(l) = l * l # square_area (generic function with 1 method) + +square_area(5) #25 + +# What happens when we feed square_area an integer? +code_native(square_area, (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(square_area, (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(square_area, (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 + # +# Note that julia will use floating point instructions if any of the +# arguements are floats. +# Let's calculate the area of a circle +circle_area(r) = pi * r * r # circle_area (generic function with 1 method) +circle_area(5) # 78.53981633974483 + +code_native(circle_area, (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(circle_area, (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 + # ``` ## Further Reading diff --git a/ko-kr/go-kr.html.markdown b/ko-kr/go-kr.html.markdown new file mode 100644 index 00000000..7404572c --- /dev/null +++ b/ko-kr/go-kr.html.markdown @@ -0,0 +1,314 @@ +--- +name: Go +category: language +language: Go +filename: learngo.go +contributors: + - ["Sonia Keys", "https://github.com/soniakeys"] +translators: + - ["Jongmin Kim", "http://github.com/atomaths"] +lang: ko-kr +--- + +Go는 어떤 일을 잘 끝낼 수 있도록 하기위해 만들어졌다. Go가 잘 알려진 최신의 +트렌드는 아니지만, 실세계의 문제들을 해결하기 위해서는 가장 +새롭고 빠른 방법이다. + +Go는 정적 타이핑(static typing)의 명령형 언어들(imperative languages)이 +갖고 있는 특징과 유사한 개념들을 가지고 있다. Go는 컴파일과 실행속도가 +빠르며, 오늘날의 멀티코어 CPU를 위해 이해하기 쉬운 동시성(concurrency) +기능이 추가되었다. 그리고 큰 스케일의 프로그래밍에도 도움이 되는 +기능들을 가지고 있다. + +또한 Go에는 훌륭한 표준 라이브러리와 열정적인 커뮤니티가 있다. + +```go +// 한 줄 주석 +/* 여러 줄 + 주석 */ + +// 모든 Go 소스 파일은 package로 시작한다. +// 패키지 이름 중 main은 라이브러리가 아닌 실행파일을 선언하는 특별한 이름이다. +package main + +// import는 이 Go 소스 파일 내에서 참조하는 라이브러리 패키지들을 선언한다. +import ( + "fmt" // Go 표준 라이브러리에 있는 패키지 + "net/http" // 표준 라이브러리에는 웹 서버 패키지도 있다! (클라이언트도 있음) + "strconv" // 문자열 변환 패키지 +) + +// 함수 선언. main은 실행 프로그램에서 시작점이 되는 특별한 함수다. +// 중괄호를 사용한다. +func main() { + // Println은 표준 출력으로 개행을 출력한다. + // fmt 패키지를 통해 이용할 수 있다. + fmt.Println("Hello world!") + + // 다른 함수를 호출한다. + beyondHello() +} + +// 함수에 파라미터가 없더라도 빈 괄호는 있어야 한다. +func beyondHello() { + var x int // 변수 선언. 변수는 사용하기 전에 선언해야 한다. + x = 3 // 변수에 값 할당. + // 짧은 선언(short declaration)으로 := 를 사용하는데, + // 이렇게 값을 할당하면 값의 타입에 따라 변수의 타입이 결정된다. + y := 4 + sum, prod := learnMultiple(x, y) // 함수는 두 개 이상의 리턴 값을 줄 수 있다. + fmt.Println("sum:", sum, "prod:", prod) // 간단한 출력 + learnTypes() // 잠시 후에 좀더 자세히! +} + +// 함수는 파라미터들을 가질 수 있고, 복수개의 값을 리턴할 수 있다. +func learnMultiple(x, y int) (sum, prod int) { + return x + y, x * y // 두 개의 값을 리턴. +} + +// 내장 타입과 리터럴 +func learnTypes() { + // 짧은 선언은 유용하다. + s := "Learn Go!" // string 타입 + + s2 := `역따옴표 안의 string 리터럴은 +개행을 포함할 수 있다.` // 같은 string 타입 + + // non-ASCII 리터럴. Go 소스는 UTF-8로 작성해야 한다. + g := 'Σ' // 유니코드 코드 포인트를 담고 있고, uint32 타입의 가칭(alias)인 rune 타입 + + f := 3.14195 // float64, an IEEE-754 64-bit 부동소수 타입 + c := 3 + 4i // complex128, 내부적으로는 두 개의 float64 타입으로 표현됨 + + // 초기값과 함께 사용하는 var 키워드. + var u uint = 7 // unsigned, 하지만 int에 따른 구현의존적인 크기 + var pi float32 = 22. / 7 + + // 짧은 선언으로 변환(conversion)하는 문법. + // Go에서는 type casting 이라고 하지않고 type conversion 이라고 함. + n := byte('\n') // byte는 uint8의 가칭(alias) + + // 배열은 컴파일 시에 크기가 정해진다. + var a4 [4]int // 모두 0으로 초기화되는 int 타입 4개짜리 배열 + a3 := [...]int{3, 1, 5} // 3, 1, 5로 초기화되는 int 타입 3개짜리 배열 + + // 슬라이스(slice)라고 하는 타입은 배열에 대한 가변 크기를 가진다. + // 배열, 슬라이스 각자 장점이 있지만, 슬라이스가 더 많이 사용된다. + s3 := []int{4, 5, 9} // 위의 a3와 비교해보면 생략부호(...)가 없다. + s4 := make([]int, 4) // 모두 0으로 초기화되는 int 4개에 대한 슬라이스를 할당. + var d2 [][]float64 // 여기에서는 선언만 있고 할당은 없다. + bs := []byte("a slice") // string 타입을 byte 슬라이스 타입으로 형변환(type conversion) + + p, q := learnMemory() // int에 대한 포인터 타입인 p와 q를 선언 + fmt.Println(*p, *q) // C에서처럼 *는 포인터를 따라가 값을 참조한다. 여기서는 두 개의 int를 출력. + + // 맵(map)은 다른 언어의 해시(hash)나 딕셔너리(dictionary)처럼 가변의 연관배열 타입. + m := map[string]int{"three": 3, "four": 4} + m["one"] = 1 + + // 선언만 하고 사용하지 않는 변수가 있다면 Go에서는 컴파일 시 에러가 난다. + // 언더바를 이용해서 변수를 사용한 것처럼 하고 그 값은 무시해버릴 수 있다. + _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs + // 물론 출력을 하면 변수로 취급한다. + fmt.Println(s, c, a4, s3, d2, m) + + learnFlowControl() // 잠시 후에 다시 나옴 +} + +// Go는 가비지 컬렉션 기능을 JVM 같은 곳이 아닌 실행파일 런타임에 포함하고 있다. +// 그리고 포인터는 있지만, 포인터 연산(*p++ 같은)은 없다. +// 그래서 nil 포인터 접근같은 것 때문에 실수를 할 수는 있지만 +// 포인터 연산으로 인한 실수는 없게 된다. +func learnMemory() (p, q *int) { + // 지명된 리턴 값(named return value)인 p와 q는 int에 대한 포인터 타입이다. + p = new(int) // 내장함수인 new는 메모리를 할당해준다. + // 메모리 할당된 int는 0으로 초기화 되고, p는 이제 nil이 아니다. + s := make([]int, 20) // 메모리의 단일 블록으로 20개의 int 공간을 할당한다. + s[3] = 7 // 그중 하나에 값을 준다. + r := -2 // 또다른 로컬 변수를 선언한다. + return &s[3], &r // &는 어떤 대상체의 메모리 주소를 가져오게 된다. +} + +func expensiveComputation() int { + return 1e6 +} + +func learnFlowControl() { + // if문에 중괄호는 필요하지만, 조건이 들어갈 곳에 소괄호는 쓰지 않는다. + if true { + fmt.Println("told ya") + } + // 모든 Go 소스의 코드 포맷팅은 "go fmt" 커맨드라인 명령으로 소스코드의 포맷을 맞춘다. + if false { + // pout + } else { + // gloat + } + // if-else 체인 형태보다 switch 사용이 권장된다. + x := 1 + switch x { + case 0: + case 1: + // case 안에서는 break가 없어도 자동으로 다음 case로 내려가지 않는다. + // 자동으로 내려가게 하려면 fallthrough 키워드를 사용한다. + case 2: + // x는 1이므로 여기는 실행되지 않음. + } + // if 에서처럼 for 에서도 양쪽에 소괄호를 쓰지 않는다. + for x := 0; x < 3; x++ { // ++ 은 실행을 제어하는 하나의 구문(statement)이다. + fmt.Println("iteration", x) + } + // 여기서 x는 1이다. 위 for에서 x는 for 안의 블록 범위에 있기 때문. + + // For is the only loop statement in Go, but it has alternate forms. + // for 는 Go에서 유일한 루프 구문이지만 다양한 형태로 조건을 주거나 while + // 처럼 쓸 수도 있다. + for { // 무한루프 + break // 여기서 곧바로 break를 한 건 단지 + continue // break, continue를 루프 안에서 쓸 수 있다는 것을 보여주기 위함. + } + // for 에서처럼 if 에서 := 를 사용하는것은 y에 먼저 값을 대입하고, + // 그리고 y > x를 검사한다는 의미. + if y := expensiveComputation(); y > x { + x = y + } + // 함수 리터럴은 클로저다. + xBig := func() bool { + return x > 100 // 위 switch 문 바로 위에 있는 x를 참조한다. + } + fmt.Println("xBig:", xBig()) // true (x에 1e6를 대입했었다.) + x /= 1e5 // x는 10이 된다. + fmt.Println("xBig:", xBig()) // 이제 xBig()의 결과는 false가 된다. + + // `goto`가 필요하다면, 좋아하게 될지도... + goto love +love: + + learnInterfaces() // 곧이어서 좋은 기능에 대한 설명이 나올 거다. +} + +// String 이라는 메서드 하나를 가진 Stringer 라는 인터페이스 타입을 정의하자. +type Stringer interface { + String() string +} + +// x와 y라는 이름의 int 타입 필드를 가진 pair라는 struct를 정의하자. +type pair struct { + x, y int +} + +// pair 타입에 메서드 String을 정의하자. +// 이제 pair는 Stringer 인터페이스를 구현(implement)한 것이 되었다. +func (p pair) String() string { // 여기서 p는 리시버(receiver)라고 부른다. + // Sprintf는 fmt 패키지 안에 있는 외부로 공개된(exported) 함수다. + // 점(.)으로 p의 필드들을 참조할 수 있다. + return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { + // 중괄호 문법은 "구조체 리터럴(struct literal)"인데, 초기화된 구조체로 + // 취급하게 해준다. := 문법으로 p를 이 구조체로 선언하고 초기화한다. + p := pair{3, 4} + fmt.Println(p.String()) // 타입 pair인 p의 String 메서드를 호출. + var i Stringer // Stringer 인터페이스 타입 i를 선언. + i = p // pair는 Stringer를 구현했기 때문에 이 대입은 유효하다. + // 타입 Stringer인 i의 String 메서드 호출. 결과는 위와 같다. + fmt.Println(i.String()) + + // fmt 패키지의 함수들을 통해 어떤 객체를 출력해보려고 할 때, + // fmt 패키지 내에서는 그 객체가 가진 String 메서드를 호출하도록 되어 있다. + fmt.Println(p) // 결과는 위와 같다. Println은 String 메서드를 호출한다. + fmt.Println(i) // 결과는 위와 같다. + + learnErrorHandling() +} + +func learnErrorHandling() { + // ", ok" (comma okay)표현은 무언가가 맞는 것인지 아닌지 확인하는데 사용된다. + m := map[int]string{3: "three", 4: "four"} + if x, ok := m[1]; !ok { // 이 map 안에 키가 1인 것은 없으므로 ok는 false가 된다. + fmt.Println("no one there") + } else { + fmt.Print(x) // 만일 1이 map에 있었다면 x는 키 1의 값이 들어가게 된다. + } + + // Go에서는 함수가 복수 개의 리턴 값을 줄 수 있다는 점을 활용해 함수의 두 번째 리턴 + // 값으로 error를 리턴해주고 그 error가 nil 인지 아닌지 확인하는 관례가 있다. + // 이때 이 error 값은 단지 위에서처럼 함수의 결과가 성공했는지 실패했는지를 확인하는 + // 것뿐만 아니라 실패 시 어떤 문제가 있었는지 확인할 수 있는 수단도 된다. + if _, err := strconv.Atoi("non-int"); err != nil { // _ 는 값을 안 쓰고 버린다는 의미. + // "strconv.ParseInt: parsing "non-int": invalid syntax" 이런 에러가 출력된다. + fmt.Println(err) + } + // 인터페이스에 대해 잠시 후에 다시 잠깐 볼 것이다. + learnConcurrency() +} + +// c는 goroutine 간의 통신을 위한 채널(channel)이다. +func inc(i int, c chan int) { + c <- i + 1 // 채널이 <- 이 연산자 왼쪽에 온다면 그 채널로 데이터를 보낸다는 의미다. +} + +// 우리는 어떤 숫자들을 동시에 증가시키기 위해 inc 함수를 사용할 것이다. +func learnConcurrency() { + // make는 slice, map, channel 타입들에 대해 메모리를 할당하고 초기화를 한다. + // Go에는 메모리 할당 방법으로 new와 make가 있다. + c := make(chan int) + // 3개의 동시에 실행되는 goroutine를 시작한다. 만약 실행하고 있는 머신이 + // 멀티코어 CPU를 가지고 있고 올바르게 설정되어(GOMAXPROCS) 있다면 + // 숫자가 정말로 병렬적으로 증가하게 될 것이다. + go inc(0, c) // go는 새로운 goroutine을 시작하는 구문이다. + go inc(10, c) + go inc(-805, c) + // 채널로부터 3개의 결과를 읽어 출력한다. + // 결과가 어떤 순서로 오는지는 알 수 없다. + fmt.Println(<-c, <-c, <-c) // 채널이 <- 연산자 오른쪽에 있는 건, 채널로부터 데이터를 받는 연산이다. + + cs := make(chan string) // string을 다루는 또 다른 채널 + cc := make(chan chan string) // string 채널의 채널 + go func() { c <- 84 }() // c 채널로 값을 보내는 goroutine 시작. + go func() { cs <- "wordy" }() // cs 채널로 값을 보내느 goroutine 시작. + // select 구문은 switch 문과 비슷하지만, case에서 채널 연산에 관한 일을 한다. + // select의 case들은 채널통신을 할 준비가 된 case 하나가 무작위로 선택되어 + // 그 부분이 실행된다. + select { + case i := <-c: // 채널로부터 받아진 값은 변수에 대입할 수 있다. + fmt.Printf("it's a %T", i) + case <-cs: // 또는 받은 값을 그냥 버릴 수도 있다. + fmt.Println("it's a string") + case <-cc: // 통신할 준비가 되어 있지 않은 비어있는 채널. + fmt.Println("didn't happen.") + } + // 여기서는 c나 cs 채널로부터 값 하나를 받을 수 있다. 위에서 실행한 두 개의 + // goroutine 중 하나가 완료되면 다른 하나는 블락된 상태로 있게 된다. + + learnWebProgramming() // Go에서는 웹 서버쪽 개발도 쉽게 할 수 있다. +} + +// http 패키지의 함수 하나로 웹 서버를 실행시킨다. +func learnWebProgramming() { + // ListenAndServe의 첫 번째 파라미터는 listen 하기 위한 TCP 주소고, + // 두 번째 파라미터는 http.Handler 인터페이스다. + err := http.ListenAndServe(":8080", pair{}) + fmt.Println(err) // don't ignore errors +} + +// http.Handler의 하나 뿐인 메서드, ServeHTTP를 pair에서 구현한다. +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // http.ResponseWriter의 메서드로 클라이언트에게 데이터를 보낸다. + w.Write([]byte("You learned Go in Y minutes!")) +} +``` + +## 더 읽어볼 것들 + +Go에 대한 모든 것들은 [Go 공식 웹 사이트](http://golang.org/)를 참고하자. +여기에는 따라해볼 튜토리얼, 웹 기반의 인터랙티브 실행환경과 많은 읽을거리들이 있다. + +Go 언어 자체에 대한 스펙도 읽어보기를 적극 추천한다. 읽기 쉽게 되어있고 +그리 길지는 않다. + +Go 소스코드에 대해 좀더 알아보고 싶다면 [Go 표준 라이브러리](http://golang.org/src/pkg/)를 +분석해보기 바란다. 이해하기 쉽게 문서화되어 있고, Go 스타일 그리고 Go에서의 +관례 배우기에 가장 좋은 방법일 것이다. 또는 [문서](http://golang.org/pkg/) 안에서 +함수 이름 하나를 클릭해보면 소스코드를 브라우저에서 살펴볼 수도 있다. diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 419c0475..453a42a5 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -4,6 +4,7 @@ language: Objective-C contributors: - ["Eugene Yagrushkin", "www.about.me/yagrushkin"] - ["Yannick Loriot", "https://github.com/YannickL"] + - ["Levi Bostian", "https://github.com/levibostian"] filename: LearnObjectiveC.m --- @@ -11,24 +12,32 @@ filename: LearnObjectiveC.m Objective-C is the main programming language used by Apple for the OS X and iOS operating systems and their respective frameworks, Cocoa and Cocoa Touch. It is a general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language. -```cpp +```objective-c // Single-line comments start with // /* -Multi-line comments look like this. +Multi-line comments look like this */ // Imports the Foundation headers with #import +// Use <> to import global files (in general frameworks) +// Use "" to import local files (from project) #import <Foundation/Foundation.h> #import "MyClass.h" +// If you enable modules for iOS >= 7.0 or OS X >= 10.9 projects in +// Xcode 5 you can import frameworks like that: +@import Foundation; + // Your program's entry point is a function called -// main with an integer return type. +// main with an integer return type int main (int argc, const char * argv[]) { // Create an autorelease pool to manage the memory into the program NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - + // If using automatic reference counting (ARC), use @autoreleasepool instead: + @autoreleasepool { + // Use NSLog to print lines to the console NSLog(@"Hello World!"); // Print the string "Hello World!" @@ -51,7 +60,7 @@ int main (int argc, const char * argv[]) // String NSString *worldString = @"World"; NSLog(@"Hello %@!", worldString); // prints => "Hello World!" - // NSMutableString is a mutable version of the NSString object. + // NSMutableString is a mutable version of the NSString object NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"]; [mutableString appendString:@" World!"]; NSLog(@"%@", mutableString); // prints => "Hello World!" @@ -74,16 +83,16 @@ int main (int argc, const char * argv[]) short fortyTwoShort = [fortyTwoShortNumber shortValue]; // or 42 NSLog(@"%hi", fortyTwoShort); - NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:41]; - unsigned short fortyTwoUnsigned = [fortyTwoShortNumber unsignedShortValue]; // or 41 - NSLog(@"%hu", fortyTwoUnsigned); + NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41]; + unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // or 41 + NSLog(@"%u", fortyOneUnsigned); NSNumber *fortyTwoLongNumber = @42L; long fortyTwoLong = [fortyTwoLongNumber longValue]; // or 42 NSLog(@"%li", fortyTwoLong); - NSNumber *fortyTwoLongNumber = @53L; - unsigned long fiftyThreeUnsigned = [fortyTwoLongNumber unsignedLongValue]; // or 53 + NSNumber *fiftyThreeLongNumber = @53L; + unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // or 53 NSLog(@"%lu", fiftyThreeUnsigned); // Floating point literals @@ -105,7 +114,7 @@ int main (int argc, const char * argv[]) [oneDecNum decimalNumberBySubtracting:twoDecNum]; [oneDecNum decimalNumberByMultiplyingBy:twoDecNum]; [oneDecNum decimalNumberByDividingBy:twoDecNum]; - NSLog(@"%@", oneDecNum); // prints => 10.99 as NSDecimalNumber is immutable. + NSLog(@"%@", oneDecNum); // prints => 10.99 as NSDecimalNumber is immutable // BOOL literals NSNumber *yesNumber = @YES; @@ -116,11 +125,12 @@ int main (int argc, const char * argv[]) NSLog(@"%i", yesBool); // prints => 1 // Array object + // May contain different data types, but must be an Objective-C object NSArray *anArray = @[@1, @2, @3, @4]; NSNumber *thirdNumber = anArray[2]; NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3" // NSMutableArray is mutable version of NSArray allowing to change items in array - // and extend or shrink array object. Convenient, but not as efficient as NSArray. + // and extend or shrink array object. Convenient, but not as efficient as NSArray NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2]; [mutableArray addObject:@"Hello"]; [mutableArray addObject:@"World"]; @@ -131,7 +141,7 @@ int main (int argc, const char * argv[]) NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" }; NSObject *valueObject = aDictionary[@"A Key"]; NSLog(@"Object = %@", valueObject); // Print "Object = (null)" - // NSMutableDictionary also available as a mutable dictionary object. + // NSMutableDictionary also available as a mutable dictionary object NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2]; [mutableDictionary setObject:@"value1" forKey:@"key1"]; [mutableDictionary setObject:@"value2" forKey:@"key2"]; @@ -140,7 +150,7 @@ int main (int argc, const char * argv[]) // Set object NSSet *set = [NSSet setWithObjects:@"Hello", @"Hello", @"World", nil]; NSLog(@"%@", set); // prints => {(Hello, World)} (may be in different order) - // NSMutableSet also available as a mutable set object. + // NSMutableSet also available as a mutable set object NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2]; [mutableSet addObject:@"Hello"]; [mutableSet addObject:@"Hello"]; @@ -199,7 +209,7 @@ int main (int argc, const char * argv[]) int ii = 0; while (ii < 4) { - NSLog(@"%d,", ii++); // ii++ increments ii in-place, after using its value. + NSLog(@"%d,", ii++); // ii++ increments ii in-place, after using its value } // => prints "0," // "1," // "2," @@ -225,7 +235,7 @@ int main (int argc, const char * argv[]) // "2," // "3," - // Object for loop statement. Can be used with any Objective-C object type. + // Object for loop statement. Can be used with any Objective-C object type for (id item in values) { NSLog(@"%@,", item); } // => prints "0," @@ -252,17 +262,20 @@ int main (int argc, const char * argv[]) // Objects /////////////////////////////////////// - // Create an object instance by allocating memory and initializing it. - // An object is not fully functional until both steps have been completed. + // Create an object instance by allocating memory and initializing it + // An object is not fully functional until both steps have been completed MyClass *myObject = [[MyClass alloc] init]; // The Objective-C model of object-oriented programming is based on message - // passing to object instances. - // In Objective-C one does not simply call a method; one sends a message. + // passing to object instances + // In Objective-C one does not simply call a method; one sends a message [myObject instanceMethodWithParameter:@"Steve Jobs"]; // Clean up the memory you used into your program [pool drain]; + + // End of @autoreleasepool + } // End the program return 0; @@ -272,79 +285,141 @@ int main (int argc, const char * argv[]) // Classes And Functions /////////////////////////////////////// -// Declare your class in a header(MyClass.h) file: -// Class Declaration Syntax: +// Declare your class in a header file (MyClass.h): +// Class declaration syntax: // @interface ClassName : ParentClassName <ImplementedProtocols> // { -// Member variable declarations; +// type name; <= variable declarations; // } -// -/+ (type) Method declarations; +// @property type name; <= property declarations +// -/+ (type) Method declarations; <= Method declarations // @end -@interface MyClass : NSObject <MyProtocol> +@interface MyClass : NSObject <MyProtocol> // NSObject is Objective-C's base object class. { // Instance variable declarations (can exist in either interface or implementation file) int count; // Protected access by default. - @private id data; // Private access. (More convenient to declare in implementation file) + @private id data; // Private access (More convenient to declare in implementation file) NSString *name; } -// Convenient notation to auto generate public access getter and setter -@property int count; -@property (copy) NSString *name; // Copy the object during assignment. -@property (readonly) id data; // Declare only a getter method. -// To access public variable in implementation file, use '_' followed by variable name: -_count = 5; -NSLog(@"%d", _count); // prints => 5 -// To access public variable outside implementation file, @property generates setter method -// automatically. Method name is 'set' followed by @property variable name: -MyClass *myClass = [[MyClass alloc] init]; // create MyClass object instance. -[myClass setCount:10]; -NSLog(@"%@", [myClass count]); // prints => 10 +// Convenient notation for public access variables to auto generate a setter method +// By default, setter method name is 'set' followed by @property variable name +@property int propInt; // Setter method name = 'setPropInt' +@property (copy) id copyId; // (copy) => Copy the object during assignment +// (readonly) => Cannot set value outside @interface +@property (readonly) NSString *roString; // Use @synthesize in @implementation to create accessor // You can customize the getter and setter names instead of using default 'set' name: -@property (getter=countGet, setter=countSet:) int count; -[myClass countSet:32]; -NSLog(@"%i", [myClass countGet]); // prints => 32 -// For convenience, you may use dot notation to set object instance variables: -myClass.count = 45; -NSLog(@"%i", myClass.count); // prints => 45 - +@property (getter=lengthGet, setter=lengthSet:) int length; + // Methods +/- (return type)methodSignature:(Parameter Type *)parameterName; -// + for class method +// + for class methods: + (NSString *)classMethod; ++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight; -// - for instance method +// - for instance methods: - (NSString *)instanceMethodWithParameter:(NSString *)string; - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number; -@end +// Constructor methods with arguments: +- (id)initWithDistance:(int)defaultDistance; +// Objective-C method names are very descriptive. Always name methods according to their arguments + +@end // States the end of the interface + + +// To access public variables from the implementation file, @property generates a setter method +// automatically. Method name is 'set' followed by @property variable name: +MyClass *myClass = [[MyClass alloc] init]; // create MyClass object instance +[myClass setCount:10]; +NSLog(@"%d", [myClass count]); // prints => 10 +// Or using the custom getter and setter method defined in @interface: +[myClass lengthSet:32]; +NSLog(@"%i", [myClass lengthGet]); // prints => 32 +// For convenience, you may use dot notation to set and access object instance variables: +myClass.count = 45; +NSLog(@"%i", myClass.count); // prints => 45 + +// Call class methods: +NSString *classMethodString = [MyClass classMethod]; +MyClass *classFromName = [MyClass myClassFromName:@"Hello"]; + +// Call instance methods: +MyClass *myClass = [[MyClass alloc] init]; // Create MyClass object instance +NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Hello"]; + +// Selectors +// Way to dynamically represent methods. Used to call methods of a class, pass methods +// through functions to tell other classes they should call it, and to save methods +// as a variable +// SEL is the data type. @selector() returns a selector from method name provided +// methodAParameterAsString:andAParameterAsNumber: is method name for method in MyClass +SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:); +if ([myClass respondsToSelector:selectorVar]) { // Checks if class contains method + // Must put all method arguments into one object to send to performSelector function + NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil]; + [myClass performSelector:selectorVar withObject:arguments]; // Calls the method +} else { + // NSStringFromSelector() returns a NSString of the method name of a given selector + NSLog(@"MyClass does not have method: %@", NSStringFromSelector(selectedVar)); +} // Implement the methods in an implementation (MyClass.m) file: @implementation MyClass { - long count; // Private access instance variable. + long distance; // Private access instance variable + NSNumber height; +} + +// To access a public variable from the interface file, use '_' followed by variable name: +_count = 5; // References "int count" from MyClass interface +// Access variables defined in implementation file: +distance = 18; // References "long distance" from MyClass implementation +// To use @property variable in implementation, use @synthesize to create accessor variable: +@synthesize roString = _roString; // _roString available now in @implementation + +// Called before calling any class methods or instantiating any objects ++ (void)initialize +{ + if (self == [MyClass class]) { + distance = 0; + } } -// Call when the object is releasing +// Counterpart to initialize method. Called when an object's reference count is zero - (void)dealloc { + [height release]; // If not using ARC, make sure to release class variable objects + [super dealloc]; // and call parent class dealloc } -// Constructors are a way of creating classes -// This is a default constructor which is called when the object is creating +// Constructors are a way of creating instances of a class +// This is a default constructor which is called when the object is initialized. - (id)init { - if ((self = [super init])) + if ((self = [super init])) // 'super' used to access methods from parent class { - self.count = 1; + self.count = 1; // 'self' used for object to call itself } return self; } +// Can create constructors that contain arguments: +- (id)initWithDistance:(int)defaultDistance +{ + distance = defaultDistance; + return self; +} + (NSString *)classMethod { return [[self alloc] init]; } ++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight +{ + height = defaultHeight; + return [[self alloc] init]; +} + - (NSString *)instanceMethodWithParameter:(NSString *)string { return @"New string"; @@ -355,13 +430,19 @@ NSLog(@"%i", myClass.count); // prints => 45 return @42; } +// To create a private method, create the method in the @implementation but not in the @interface +- (NSNumber *)secretPrivateMethod { + return @72; +} +[self secretPrivateMethod]; // Calls private method + // Methods declared into MyProtocol - (void)myProtocolMethod { // statements } -@end +@end // States the end of the implementation /* * A protocol declares methods that can be implemented by any class. @@ -373,12 +454,58 @@ NSLog(@"%i", myClass.count); // prints => 45 @end +/////////////////////////////////////// +// Memory Management +/////////////////////////////////////// +/* +For each object used in an application, memory must be allocated for that object. When the application +is done using that object, memory must be deallocated to ensure application efficiency. +Objective-C does not use garbage collection and instead uses reference counting. As long as +there is at least one reference to an object (also called "owning" an object), then the object +will be available to use (known as "ownership"). + +When an instance owns an object, its reference counter is increments by one. When the +object is released, the reference counter decrements by one. When reference count is zero, +the object is removed from memory. + +With all object interactions, follow the pattern of: +(1) create the object, (2) use the object, (3) then free the object from memory. +*/ + +MyClass *classVar = [MyClass alloc]; // 'alloc' sets classVar's reference count to one. Returns pointer to object +[classVar release]; // Decrements classVar's reference count +// 'retain' claims ownership of existing object instance and increments reference count. Returns pointer to object +MyClass *newVar = [classVar retain]; // If classVar is released, object is still in memory because newVar is owner +[classVar autorelease]; // Removes ownership of object at end of @autoreleasepool block. Returns pointer to object + +// @property can use 'retain' and 'assign' as well for small convenient definitions +@property (retain) MyClass *instance; // Release old value and retain a new one (strong reference) +@property (assign) NSSet *set; // Pointer to new value without retaining/releasing old (weak reference) + +// Automatic Reference Counting (ARC) +// Because memory management can be a pain, Xcode 4.2 and iOS 4 introduced Automatic Reference Counting (ARC). +// ARC is a compiler feature that inserts retain, release, and autorelease automatically for you, so when using ARC, +// you must not use retain, relase, or autorelease +MyClass *arcMyClass = [[MyClass alloc] init]; +// ... code using arcMyClass +// Without ARC, you will need to call: [arcMyClass release] after you're done using arcMyClass. But with ARC, +// there is no need. It will insert this release statement for you + +// As for the 'assign' and 'retain' @property attributes, with ARC you use 'weak' and 'strong' +@property (weak) MyClass *weakVar; // 'weak' does not take ownership of object. If original instance's reference count +// is set to zero, weakVar will automatically receive value of nil to avoid application crashing +@property (strong) MyClass *strongVar; // 'strong' takes ownership of object. Ensures object will stay in memory to use + +// For regular variables (not @property declared variables), use the following: +__strong NSString *strongString; // Default. Variable is retained in memory until it leaves it's scope +__weak NSSet *weakSet; // Weak reference to existing object. When existing object is released, weakSet is set to nil +__unsafe_unretained NSArray *unsafeArray; // Like __weak, but unsafeArray not set to nil when existing object is released ``` ## Further Reading [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C) -[Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/) +[Programming with Objective-C. Apple PDF book](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf) [iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started) diff --git a/php.html.markdown b/php.html.markdown index c3317d59..e1bb86a0 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -212,7 +212,7 @@ assert($c >= $d); // The following will only be true if the values match and are the same type. assert($c === $d); assert($a !== $d); -assert(1 == '1'); +assert(1 === '1'); assert(1 !== '1'); // Variables can be converted between types, depending on their usage. diff --git a/racket.html.markdown b/racket.html.markdown index adacd91d..eddc00bf 100644 --- a/racket.html.markdown +++ b/racket.html.markdown @@ -6,6 +6,7 @@ contributors: - ["th3rac25", "https://github.com/voila"] - ["Eli Barzilay", "https://github.com/elibarzilay"] - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"] + - ["Duong H. Nguyen", "https://github.com/cmpitg"] --- Racket is a general purpose, multi-paradigm programming language in the Lisp/Scheme family. @@ -600,6 +601,45 @@ vec ; => #(1 2 3 4) ;; expected: positive? ;; given: -5 ;; more details.... + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 11. Input & output +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Racket has this concept of "port", which is very similar to file +;; descriptors in other languages + +;; Open "/tmp/tmp.txt" and write "Hello World" +;; This would trigger an error if the file's already existed +(define out-port (open-output-file "/tmp/tmp.txt")) +(displayln "Hello World" out-port) +(close-output-port out-port) + +;; Append to "/tmp/tmp.txt" +(define out-port (open-output-file "/tmp/tmp.txt" + #:exists 'append)) +(displayln "Hola mundo" out-port) +(close-output-port out-port) + +;; Read from the file again +(define in-port (open-input-file "/tmp/tmp.txt")) +(displayln (read-line in-port)) +; => "Hello World" +(displayln (read-line in-port)) +; => "Hola mundo" +(close-input-port in-port) + +;; Alternatively, with call-with-output-file you don't need to explicitly +;; close the file +(call-with-output-file "/tmp/tmp.txt" + #:exists 'update ; Rewrite the content + (λ (out-port) + (displayln "World Hello!" out-port))) + +;; And call-with-input-file does the same thing for input +(call-with-input-file "/tmp/tmp.txt" + (λ (in-port) + (displayln (read-line in-port)))) ``` ## Further Reading diff --git a/zh-cn/clojure-cn.html.markdown b/zh-cn/clojure-cn.html.markdown new file mode 100644 index 00000000..d5d8232b --- /dev/null +++ b/zh-cn/clojure-cn.html.markdown @@ -0,0 +1,366 @@ +--- +language: clojure +filename: learnclojure-cn.clj +contributors: + - ["Bill Zhang", "http://jingege.github.io/"] +lang: zh-cn +--- + +Clojure是运行在JVM上的Lisp家族中的一员。她比Common Lisp更强调纯[函数式编程](https://en.wikipedia.org/wiki/Functional_programming),且自发布时便包含了一组工具来处理状态。 + +这种组合让她能十分简单且自动地处理并发问题。 + +(你需要使用Clojure 1.2或更新的发行版) + +```clojure +; 注释以分号开始。 + +; Clojure代码由一个个form组成, 即写在小括号里的由空格分开的一组语句。 +; Clojure解释器会把第一个元素当做一个函数或者宏来调用,其余的被认为是参数。 + +; Clojure代码的第一条语句一般是用ns来指定当前的命名空间。 +(ns learnclojure) + +; 更基本的例子: + +; str会使用所有参数来创建一个字符串 +(str "Hello" " " "World") ; => "Hello World" + +; 数学计算比较直观 +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; 等号是 = +(= 1 1) ; => true +(= 2 1) ; => false + +; 逻辑非 +(not true) ; => false + +; 嵌套的form工作起来应该和你预想的一样 +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; 类型 +;;;;;;;;;;;;; + +; Clojure使用Java的Object来描述布尔值、字符串和数字 +; 用函数 `class` 来查看具体的类型 +(class 1) ; 整形默认是java.lang.Long类型 +(class 1.); 浮点默认是java.lang.Double类型的 +(class ""); String是java.lang.String类型的,要用双引号引起来 +(class false) ; 布尔值是java.lang.Boolean类型的 +(class nil); "null"被称作nil + +; 如果你想创建一组数据字面量,用单引号(')来阻止form被解析和求值 +'(+ 1 2) ; => (+ 1 2) +; (单引号是quote的简写形式,故上式等价于(quote (+ 1 2))) + +; 可以对一个引用列表求值 +(eval '(+ 1 2)) ; => 3 + +; 集合(Collection)和序列 +;;;;;;;;;;;;;;;;;;; + +; List的底层实现是链表,Vector的底层实现是数组 +; 二者也都是java类 +(class [1 2 3]); => clojure.lang.PersistentVector +(class '(1 2 3)); => clojure.lang.PersistentList + +; list本可以写成(1 2 3), 但必须用引用来避免被解释器当做函数来求值。 +; (list 1 2 3)等价于'(1 2 3) + +; 集合其实就是一组数据 +; List和Vector都是集合: +(coll? '(1 2 3)) ; => true +(coll? [1 2 3]) ; => true + +; 序列 (seqs) 是数据列表的抽象描述 +; 只有列表才可称作序列。 +(seq? '(1 2 3)) ; => true +(seq? [1 2 3]) ; => false + +; 序列被访问时只需要提供一个值,所以序列可以被懒加载——也就意味着可以定义一个无限序列: +(range 4) ; => (0 1 2 3) +(range) ; => (0 1 2 3 4 ...) (无限序列) +(take 4 (range)) ; (0 1 2 3) + +; cons用以向列表或向量的起始位置添加元素 +(cons 4 [1 2 3]) ; => (4 1 2 3) +(cons 4 '(1 2 3)) ; => (4 1 2 3) + +; conj将以最高效的方式向集合中添加元素。 +; 对于列表,数据会在起始位置插入,而对于向量,则在末尾位置插入。 +(conj [1 2 3] 4) ; => [1 2 3 4] +(conj '(1 2 3) 4) ; => (4 1 2 3) + +; 用concat来合并列表或向量 +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; 用filter来过滤集合中的元素,用map来根据指定的函数来映射得到一个新的集合 +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; recuce使用函数来规约集合 +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; reduce还能指定一个初始参数 +(reduce conj [] '(3 2 1)) +; = (conj (conj (conj [] 3) 2) 1) +; => [3 2 1] + +; 函数 +;;;;;;;;;;;;;;;;;;;;; + +; 用fn来创建函数。函数的返回值是最后一个表达式的值 +(fn [] "Hello World") ; => fn + +; (你需要再嵌套一组小括号来调用它) +((fn [] "Hello World")) ; => "Hello World" + +; 你可以用def来创建一个变量(var) +(def x 1) +x ; => 1 + +; 将函数定义为一个变量(var) +(def hello-world (fn [] "Hello World")) +(hello-world) ; => "Hello World" + +; 你可用defn来简化函数的定义 +(defn hello-world [] "Hello World") + +; 中括号内的内容是函数的参数。 +(defn hello [name] + (str "Hello " name)) +(hello "Steve") ; => "Hello Steve" + +; 你还可以用这种简写的方式来创建函数: +(def hello2 #(str "Hello " %1)) +(hello2 "Fanny") ; => "Hello Fanny" + +; 函数也可以有多个参数列表。 +(defn hello3 + ([] "Hello World") + ([name] (str "Hello " name))) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" + +; 可以定义变参函数,即把&后面的参数全部放入一个序列 +(defn count-args [& args] + (str "You passed " (count args) " args: " args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" + +; 可以混用定参和变参(用&来界定) +(defn hello-count [name & args] + (str "Hello " name ", you passed " (count args) " extra args")) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" + + +; 哈希表 +;;;;;;;;;; + +; 基于hash的map和基于数组的map(即arraymap)实现了相同的接口,hashmap查询起来比较快, +; 但不保证元素的顺序。 +(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap +(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap + +; arraymap在足够大的时候,大多数操作会将其自动转换成hashmap, +; 所以不用担心(对大的arraymap的查询性能)。 + +; map支持很多类型的key,但推荐使用keyword类型 +; keyword类型和字符串类似,但做了一些优化。 +(class :a) ; => clojure.lang.Keyword + +(def stringmap {"a" 1, "b" 2, "c" 3}) +stringmap ; => {"a" 1, "b" 2, "c" 3} + +(def keymap {:a 1, :b 2, :c 3}) +keymap ; => {:a 1, :c 3, :b 2} + +; 顺便说一下,map里的逗号是可有可无的,作用只是提高map的可读性。 + +; 从map中查找元素就像把map名作为函数调用一样。 +(stringmap "a") ; => 1 +(keymap :a) ; => 1 + +; 可以把keyword写在前面来从map中查找元素。 +(:b keymap) ; => 2 + +; 但不要试图用字符串类型的key来这么做。 +;("a" stringmap) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; 查找不存在的key会返回nil。 +(stringmap "d") ; => nil + +; 用assoc函数来向hashmap里添加元素 +(def newkeymap (assoc keymap :d 4)) +newkeymap ; => {:a 1, :b 2, :c 3, :d 4} + +; 但是要记住的是clojure的数据类型是不可变的! +keymap ; => {:a 1, :b 2, :c 3} + +; 用dissoc来移除元素 +(dissoc keymap :a :b) ; => {:c 3} + +; 集合(Set) +;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; 用conj新增元素 +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; 用disj移除元素 +(disj #{1 2 3} 1) ; => #{2 3} + +; 把集合当做函数调用来检查元素是否存在: +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; 在clojure.sets模块下有很多相关函数。 + +; 常用的form +;;;;;;;;;;;;;;;;; + +; clojure里的逻辑控制结构都是用宏(macro)实现的,这在语法上看起来没什么不同。 +(if false "a" "b") ; => "b" +(if false "a") ; => nil + +; 用let来创建临时的绑定变量。 +(let [a 1 b 2] + (> a b)) ; => false + +; 用do将多个语句组合在一起依次执行 +(do + (print "Hello") + "World") ; => "World" (prints "Hello") + +; 函数定义里有一个隐式的do +(defn print-and-say-hello [name] + (print "Saying hello to " name) + (str "Hello " name)) +(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") + +; let也是如此 +(let [name "Urkel"] + (print "Saying hello to " name) + (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") + +; 模块 +;;;;;;;;;;;;;;; + +; 用use来导入模块里的所有函数 +(use 'clojure.set) + +; 然后就可以使用set相关的函数了 +(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} +(difference #{1 2 3} #{2 3 4}) ; => #{1} + +; 你也可以从一个模块里导入一部分函数。 +(use '[clojure.set :only [intersection]]) + +; 用require来导入一个模块 +(require 'clojure.string) + +; 用/来调用模块里的函数 +; 下面是从模块`clojure.string`里调用`blank?`函数。 +(clojure.string/blank? "") ; => true + +; 在`import`里你可以给模块名指定一个较短的别名。 +(require '[clojure.string :as str]) +(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." +; (#""用来表示一个正则表达式) + +; 你可以在一个namespace定义里用:require的方式来require(或use,但最好不要用)模块。 +; 这样的话你无需引用模块列表。 +(ns test + (:require + [clojure.string :as str] + [clojure.set :as set])) + +; Java +;;;;;;;;;;;;;;;;; + +; Java有大量的优秀的库,你肯定想学会如何用clojure来使用这些Java库。 + +; 用import来导入java类 +(import java.util.Date) + +; 也可以在ns定义里导入 +(ns test + (:import java.util.Date + java.util.Calendar)) + +; 用类名末尾加`.`的方式来new一个Java对象 +(Date.) ; <a date object> + +; 用`.`操作符来调用方法,或者用`.method`的简化方式。 +(. (Date.) getTime) ; <a timestamp> +(.getTime (Date.)) ; 和上例一样。 + +; 用`/`调用静态方法 +(System/currentTimeMillis) ; <a timestamp> (system is always present) + +; 用`doto`来更方便的使用(可变)类。 +(import java.util.Calendar) +(doto (Calendar/getInstance) + (.set 2000 1 1 0 0 0) + .getTime) ; => A Date. set to 2000-01-01 00:00:00 + +; STM +;;;;;;;;;;;;;;;;; + +; 软件内存事务(Software Transactional Memory)被clojure用来处理持久化的状态。 +; clojure里内置了一些结构来使用STM。 +; atom是最简单的。给它传一个初始值 +(def my-atom (atom {})) + +; 用`swap!`更新atom。 +; `swap!`会以atom的当前值为第一个参数来调用一个指定的函数, +; `swap`其余的参数作为该函数的第二个参数。 +(swap! my-atom assoc :a 1) ; Sets my-atom to the result of (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2) + +; 用`@`读取atom的值 +my-atom ;=> Atom<#...> (返回Atom对象) +@my-atom ; => {:a 1 :b 2} + +; 下例是一个使用atom实现的简单计数器 +(def counter (atom 0)) +(defn inc-counter [] + (swap! counter inc)) + +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) + +@counter ; => 5 + +; 其他STM相关的结构是ref和agent. +; Refs: http://clojure.org/refs +; Agents: http://clojure.org/agents +``` + +### 进阶读物 + +本文肯定不足以讲述关于clojure的一切,但是希望足以让你迈出第一步。 + +Clojure.org官网有很多文章: +[http://clojure.org/](http://clojure.org/) + +Clojuredocs.org有大多数核心函数的文档,还带了示例哦: +[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) + +4Clojure是个很赞的用来练习clojure/FP技能的地方: +[http://www.4clojure.com/](http://www.4clojure.com/) + +Clojure-doc.org (你没看错)有很多入门级的文章: +[http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 7cc9c171..4a87dc21 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -5,6 +5,8 @@ filename: learngo-cn.go contributors: - ["Sonia Keys", "https://github.com/soniakeys"] - ["pantaovay", "https://github.com/pantaovay"] + - ["lidashuang", "https://github.com/lidashuang"] + --- 发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 @@ -30,7 +32,7 @@ import ( ) // 函数声明:Main是程序执行的入口。 -// 不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +// 不管你喜欢还是不喜欢,反正Go就用了花括号来包住函数体。 func main() { // 往标准输出打印一行。 // 用包名fmt限制打印函数。 @@ -47,7 +49,7 @@ func beyondHello() { x = 3 // 变量赋值。 // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 y := 4 - sum, prod := learnMultiple(x, y) // 多个返回变量的函数 + sum, prod := learnMultiple(x, y) // 返回多个变量的函数 fmt.Println("sum:", sum, "prod:", prod) // 简单输出 learnTypes() // 少于y分钟,学的更多! } @@ -82,7 +84,7 @@ can include line breaks.` // 同样是String类型 var a4 [4] int // 有4个int变量的数组,初始为0 a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化 - // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 + // Slice 可以动态的增删。Array和Slice各有千秋,但是使用slice的地方更多些。 s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号 s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0 @@ -114,7 +116,7 @@ func learnMemory() (p, q *int) { s := make([]int, 20) // 给20个int变量分配一块内存 s[3] = 7 // 赋值 r := -2 // 声明另一个局部变量 - return &s[3], &r // & 取址 + return &s[3], &r // & 取地址 } func expensiveComputation() int { @@ -149,7 +151,7 @@ func learnFlowControl() { // x在这里还是1。为什么? // for 是go里唯一的循环关键字,不过它有很多变种 - for { // 无限循环 + for { // 死循环 break // 骗你的 continue // 不会运行的 } @@ -239,7 +241,7 @@ func learnConcurrency() { go inc(-805, c) // 从channel中独处结果并打印。 // 打印出什么东西是不可预知的。 - fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是读操作。 cs := make(chan string) // 操作string的channel cc := make(chan chan string) // 操作channel的channel @@ -255,7 +257,7 @@ func learnConcurrency() { case <-cc: // 空的,还没作好通讯的准备 fmt.Println("didn't happen.") } - // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 + // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个一直阻塞。 learnWebProgramming() // Go很适合web编程,我知道你也想学! } diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 89fc256e..86ad1d07 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -401,8 +401,6 @@ if (Object.create === undefined){ // 如果存在则不覆盖 [Mozilla 开发者 网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了很好的 Javascript文档,并且由于是wiki,所以你也可以自行编辑来分享你的知识。 -wiki, so as you learn more you can help others out by sharing your own -knowledge. MDN的 [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index c6ebb515..24939681 100644 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -180,7 +180,7 @@ assert($c >= $d); // 下面的比较只有在类型相同、值相同的情况下才为真 assert($c === $d); assert($a !== $d); -assert(1 == '1'); +assert(1 === '1'); assert(1 !== '1'); // 变量可以根据其使用来进行类型转换 @@ -243,7 +243,7 @@ if ($x === '0') { -// 下面的语法常用语模板中: +// 下面的语法常用于模板中: ?> <?php if ($x): ?> @@ -333,7 +333,7 @@ function my_function () { echo my_function(); // => "Hello" // 函数名需要以字母或者下划线开头, -// 后面可以跟着任意的字幕、下划线、数字. +// 后面可以跟着任意的字母、下划线、数字. function add ($x, $y = 1) { // $y 是可选参数,默认值为 1 $result = $x + $y; diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 619e6e92..3c47f3f9 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -6,6 +6,7 @@ contributors: - ["David Underwood", "http://theflyingdeveloper.com"] - ["Joel Walden", "http://joelwalden.net"] - ["Luke Holder", "http://twitter.com/lukeholder"] + - ["lidashuang", "https://github.com/lidashuang"] translators: - ["Lin Xiangyu", "https://github.com/oa414"] --- @@ -173,7 +174,7 @@ new_hash = { defcon: 3, action: true} new_hash.keys #=> [:defcon, :action] # 小贴士:数组和哈希表都是可枚举的 -# 它们可以共享一些有用的方法,比如each, map, count, 和more +# 它们可以共享一些有用的方法,比如each, map, count 等等 # 控制流 |