diff options
42 files changed, 11477 insertions, 209 deletions
diff --git a/README.markdown b/README.markdown index 77e09abd..efc2fa07 100644 --- a/README.markdown +++ b/README.markdown @@ -16,8 +16,9 @@ properly! The most requested languages are: -* Scala -* Javascript +* Go +* ~~Scala~~ +* ~~Javascript~~ ... but there are many more requests to do "every language", so don't let that stop you. diff --git a/c.html.markdown b/c.html.markdown index 69bf099e..d243b19d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,8 +1,10 @@ --- +name: c +category: language language: c -author: Adam Bard -author_url: http://adambard.com/ filename: learnc.c +contributors: + - ["Adam Bard", "http://adambard.com/"] --- Ah, C. Still the language of modern high-performance computing. @@ -68,7 +70,7 @@ double x_double = 0.0; // Integral types may be unsigned. This means they can't be negative, but // the maximum value of an unsigned variable is greater than the maximum -// value of the same size. +// signed value of the same size. unsigned char ux_char; unsigned short ux_short; unsigned int ux_int; @@ -363,6 +365,36 @@ int area(rect r){ return r.width * r.height; } +/////////////////////////////////////// +// Function pointers +/////////////////////////////////////// +/* +At runtime, functions are located at known memory addresses. Function pointers are +much likely any other pointer (they just store a memory address), but can be used +to invoke functions directly, and to pass handlers (or callback functions) around. +However, definition syntax may be initially confusing. + +Example: use str_reverse from a pointer +*/ +void str_reverse_through_pointer(char * str_in) { + // Define a function pointer variable, named f. + void (*f)(char *); // Signature should exactly match the target function. + f = &str_reverse; // Assign the address for the actual function (determined at runtime) + (*f)(str_in); // Just calling the function through the pointer + // f(str_in); // That's an alternative but equally valid syntax for calling it. +} + +/* +As long as function signatures match, you can assign any function to the same pointer. +Function pointers are usually typedef'd for simplicity and readability, as follows: +*/ + +typedef void (*my_fnp_type)(char *); + +// The used when declaring the actual pointer variable: +// ... +// my_fnp_type f; + ``` ## Further Reading diff --git a/clojure.html.markdown b/clojure.html.markdown index 39a27bcf..6baae0ce 100644 --- a/clojure.html.markdown +++ b/clojure.html.markdown @@ -1,8 +1,8 @@ --- language: clojure -author: Adam Bard -author_url: http://adambard.com/ filename: learnclojure.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] --- Clojure is a Lisp family language developed for the Java Virtual Machine. It has diff --git a/coffeescript.html.markdown b/coffeescript.html.markdown new file mode 100644 index 00000000..429f10b5 --- /dev/null +++ b/coffeescript.html.markdown @@ -0,0 +1,55 @@ +--- +language: coffeescript +contributors: + - ["Tenor Biel", "http://github.com/L8D"] +filename: coffeescript.coffee +--- + +``` coffeescript +# CoffeeScript is a hipster language. +# It goes with the trends of many modern languages. +# So comments are like Ruby and Python, they use hashes. + +### +Block comments are like these, and they translate directly to '/ *'s and '* /'s +for the resulting JavaScript code. + +You should understand most of JavaScript semantices +before continuing. +### + +# Assignment: +number = 42 #=> var number = 42; +opposite = true #=> var opposite = true; + +# Conditions: +number = -42 if opposite #=> if(opposite) { number = -42; } + +# Functions: +square = (x) -> x * x #=> var square = function(x) { return x * x; } + +# Ranges: +list = [1..5] #=> var list = [1, 2, 3, 4, 5]; + +# Objects: +math = + root: Math.sqrt + square: square + cube: (x) -> x * square x +#=> var math = { +# "root": Math.sqrt, +# "square": square, +# "cube": function(x) { return x * square(x); } +#} + +# Splats: +race = (winner, runners...) -> + print winner, runners + +# Existence: +alert "I knew it!" if elvis? +#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } + +# Array comprehensions: +cubes = (math.cube num for num in list) #=> ... +``` diff --git a/dart.html.markdown b/dart.html.markdown index 27365746..34d1c6a8 100644 --- a/dart.html.markdown +++ b/dart.html.markdown @@ -1,8 +1,8 @@ --- language: dart -author: Joao Pedrosa -author_url: https://github.com/jpedrosa/ filename: learndart.dart +contributors: + - ["Joao Pedrosa", "https://github.com/jpedrosa/"] --- Dart is a newcomer into the realm of programming languages. diff --git a/elisp.html.markdown b/elisp.html.markdown new file mode 100644 index 00000000..d3910759 --- /dev/null +++ b/elisp.html.markdown @@ -0,0 +1,353 @@ +--- +language: elisp +contributors: + - ["Bastien Guerry", "http://bzg.fr"] +filename: learn-emacs-lisp.el +--- + +```scheme +;; This gives an introduction to Emacs Lisp in 15 minutes (v0.2d) +;; +;; Author: Bastien / @bzg2 / http://bzg.fr +;; +;; First make sure you read this text by Peter Norvig: +;; http://norvig.com/21-days.html +;; +;; Then install GNU Emacs 24.3: +;; +;; Debian: apt-get install emacs (or see your distro instructions) +;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg +;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip +;; +;; More general information can be found at: +;; http://www.gnu.org/software/emacs/#Obtaining + +;; Important warning: +;; +;; Going through this tutorial won't damage your computer unless +;; you get so angry that you throw it on the floor. In that case, +;; I hereby decline any responsability. Have fun! + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Fire up Emacs. +;; +;; Hit the `q' key to dismiss the welcome message. +;; +;; Now look at the gray line at the bottom of the window: +;; +;; "*scratch*" is the name of the editing space you are now in. +;; This editing space is called a "buffer". +;; +;; The scratch buffer is the default buffer when opening Emacs. +;; You are never editing files: you are editing buffers that you +;; can save to a file. +;; +;; "Lisp interaction" refers to a set of commands available here. +;; +;; Emacs has a built-in set of commands available in every buffer, +;; and several subsets of commands available when you activate a +;; specific mode. Here we use the `lisp-interaction-mode', which +;; comes with commands to evaluate and navigate within Elisp code. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Semi-colons start comments anywhere on a line. +;; +;; Elisp programs are made of symbolic expressions ("sexps"): +(+ 2 2) + +;; This symbolic expression reads as "Add 2 to 2". + +;; Sexps are enclosed into parentheses, possibly nested: +(+ 2 (+ 1 1)) + +;; A symbolic expression contains atoms or other symbolic +;; expressions. In the above examples, 1 and 2 are atoms, +;; (+ 2 (+ 1 1)) and (+ 1 1) are symbolic expressions. + +;; From `lisp-interaction-mode' you can evaluate sexps. +;; Put the cursor right after the closing parenthesis then +;; hold down the control and hit the j keys ("C-j" for short). + +(+ 3 (+ 1 2)) +;; ^ cursor here +;; `C-j' => 6 + +;; `C-j' inserts the result of the evaluation in the buffer. + +;; `C-xC-e' displays the same result in Emacs bottom line, +;; called the "minibuffer". We will generally use `C-xC-e', +;; as we don't want to clutter the buffer with useless text. + +;; `setq' stores a value into a variable: +(setq my-name "Bastien") +;; `C-xC-e' => "Bastien" (displayed in the mini-buffer) + +;; `insert' will insert "Hello!" where the cursor is: +(insert "Hello!") +;; `C-xC-e' => "Hello!" + +;; We used `insert' with only one argument "Hello!", but +;; we can pass more arguments -- here we use two: + +(insert "Hello" " world!") +;; `C-xC-e' => "Hello world!" + +;; You can use variables instead of strings: +(insert "Hello, I am " my-name) +;; `C-xC-e' => "Hello, I am Bastien" + +;; You can combine sexps into functions: +(defun hello () (insert "Hello, I am " my-name)) +;; `C-xC-e' => hello + +;; You can evaluate functions: +(hello) +;; `C-xC-e' => Hello, I am Bastien + +;; The empty parentheses in the function's definition means that +;; it does not accept arguments. But always using `my-name' is +;; boring, let's tell the function to accept one argument (here +;; the argument is called "name"): + +(defun hello (name) (insert "Hello " name)) +;; `C-xC-e' => hello + +;; Now let's call the function with the string "you" as the value +;; for its unique argument: +(hello "you") +;; `C-xC-e' => "Hello you" + +;; Yeah! + +;; Take a breath. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Now switch to a new buffer named "*test*" in another window: + +(switch-to-buffer-other-window "*test*") +;; `C-xC-e' +;; => [screen has two windows and cursor is in the *test* buffer] + +;; Mouse over the top window and left-click to go back. Or you can +;; use `C-xo' (i.e. hold down control-x and hit o) to go to the other +;; window interactively. + +;; You can combine several sexps with `progn': +(progn + (switch-to-buffer-other-window "*test*") + (hello "you")) +;; `C-xC-e' +;; => [The screen has two windows and cursor is in the *test* buffer] + +;; Now if you don't mind, I'll stop asking you to hit `C-xC-e': do it +;; for every sexp that follows. + +;; Always go back to the *scratch* buffer with the mouse or `C-xo'. + +;; It's often useful to erase the buffer: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "there")) + +;; Or to go back to the other window: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "you") + (other-window 1)) + +;; You can bind a value to a local variable with `let': +(let ((local-name "you")) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello local-name) + (other-window 1)) + +;; No need to use `progn' in that case, since `let' also combines +;; several sexps. + +;; Let's format a string: +(format "Hello %s!\n" "visitor") + +;; %s is a place-holder for a string, replaced by "visitor". +;; \n is the newline character. + +;; Let's refine our function by using format: +(defun hello (name) + (insert (format "Hello %s!\n" name))) + +(hello "you") + +;; Let's create another function which uses `let': +(defun greeting (name) + (let ((your-name "Bastien")) + (insert (format "Hello %s!\n\nI am %s." + name ; the argument of the function + your-name ; the let-bound variable "Bastien" + )))) + +;; And evaluate it: +(greeting "you") + +;; Some function are interactive: +(read-from-minibuffer "Enter your name: ") + +;; Evaluating this function returns what you entered at the prompt. + +;; Let's make our `greeting' function prompt for your name: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (insert (format "Hello!\n\nI am %s and you are %s." + from-name ; the argument of the function + your-name ; the let-bound var, entered at prompt + )))) + +(greeting "Bastien") + +;; Let's complete it by displaying the results in the other window: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (insert (format "Hello %s!\n\nI am %s." your-name from-name)) + (other-window 1))) + +;; Now test it: +(greeting "Bastien") + +;; Take a breath. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Let's store a list of names: +(setq list-of-names '("Sarah" "Chloe" "Mathilde")) + +;; Get the first element of this list with `car': +(car list-of-names) + +;; Get a list of all but the first element with `cdr': +(cdr list-of-names) + +;; Add an element to the beginning of a list with `push': +(push "Stephanie" list-of-names) + +;; NOTE: `car' and `cdr' don't modify the list, but `push' does. +;; This is an important difference: some functions don't have any +;; side-effects (like `car') while others have (like `push'). + +;; Let's call `hello' for each element in `list-of-names': +(mapcar 'hello list-of-names) + +;; Refine `greeting' to say hello to everyone in `list-of-names': +(defun greeting () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (mapcar 'hello list-of-names) + (other-window 1)) + +(greeting) + +;; Remember the `hello' function we defined above? It takes one +;; argument, a name. `mapcar' calls `hello', successively using each +;; element of `list-of-names' as the argument for `hello'. + +;; Now let's arrange a bit what we have in the displayed buffer: + +(defun replace-hello-by-bonjour () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (search-forward "Hello") + (replace-match "Bonjour")) + (other-window 1)) + +;; (goto-char (point-min)) goes to the beginning of the buffer. +;; (search-forward "Hello") searches for the string "Hello". +;; (while x y) evaluates the y sexp(s) while x returns something. +;; If x returns `nil' (nothing), we exit the while loop. + +(replace-hello-by-bonjour) + +;; You should see all occurrences of "Hello" in the *test* buffer +;; replaced by "Bonjour". + +;; You should also get an error: "Search failed: Hello". +;; +;; To avoid this error, you need to tell `search-forward' whether it +;; should stop searching at some point in the buffer, and whether it +;; should silently fail when nothing is found: + +;; (search-forward "Hello" nil t) does the trick: + +;; The `nil' argument says: the search is not bound to a position. +;; The `t' argument says: silently fail when nothing is found. + +;; We use this sexp in the function below, which doesn't throw an error: + +(defun hello-to-bonjour () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + ;; Say hello to names in `list-of-names' + (mapcar 'hello list-of-names) + (goto-char (point-min)) + ;; Replace "Hello" by "Bonjour" + (while (search-forward "Hello" nil t) + (replace-match "Bonjour")) + (other-window 1)) + +(hello-to-bonjour) + +;; Let's colorize the names: + +(defun boldify-names () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (re-search-forward "Bonjour \\(.+\\)!" nil t) + (add-text-properties (match-beginning 1) + (match-end 1) + (list 'face 'bold))) + (other-window 1)) + +;; This functions introduces `re-search-forward': instead of +;; searching for the string "Bonjour", you search for a pattern, +;; using a "regular expression" (abbreviated in the prefix "re-"). + +;; The regular expression is "Bonjour \\(.+\\)!" and it reads: +;; the string "Bonjour ", and +;; a group of | this is the \\( ... \\) construct +;; any character | this is the . +;; possibly repeated | this is the + +;; and the "!" string. + +;; Ready? Test it! + +(boldify-names) + +;; `add-text-properties' adds... text properties, like a face. + +;; OK, we are done. Happy hacking! + +;; If you want to know more about a variable or a function: +;; +;; C-h v a-variable RET +;; C-h f a-function RET +;; +;; To read the Emacs Lisp manual with Emacs: +;; +;; C-h i m elisp RET +;; +;; To read an online introduction to Emacs Lisp: +;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html + +;; Thanks to these people for their feedback and suggestions: +;; - Wes Hardaker +;; - notbob +;; - Kevin Montuori +;; - Arne Babenhauserheide +;; - Alan Schmitt +;; - LinXitoW +;; - Aaron Meurer +``` diff --git a/elixir.html.markdown b/elixir.html.markdown index 2e9aa5a1..8ea499ff 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -1,7 +1,7 @@ --- language: elixir -author: Joao Marques -author_url: http://github.com/mrshankly +contributors: + - ["Joao Marques", "http://github.com/mrshankly"] filename: learnelixir.ex --- @@ -33,7 +33,7 @@ and many more features. # Atoms, that are literals, a constant with name. They start with `:`. :hello # atom -# Tuples that are stored contigously in memory. +# Tuples that are stored contiguously in memory. {1,2,3} # tuple # We can access a tuple element with the `elem` function: @@ -47,7 +47,7 @@ elem({1, 2, 3}, 0) #=> 1 head #=> 1 tail #=> [2,3] -# In elixir, just like in erlang, the `=` denotes pattern matching and +# In elixir, just like in Erlang, the `=` denotes pattern matching and # not an assignment. # # This means that the left-hand side (pattern) is matched against a @@ -170,7 +170,7 @@ case {:one, :two} do "This will match any value" end -# It's common practive to assign a value to `_` if we don't need it. +# It's common practice to assign a value to `_` if we don't need it. # For example, if only the head of a list matters to us: [head | _] = [1,2,3] head #=> 1 diff --git a/erlang.html.markdown b/erlang.html.markdown index 42d0b809..065219ba 100644 --- a/erlang.html.markdown +++ b/erlang.html.markdown @@ -1,12 +1,12 @@ --- language: erlang -author: Giovanni Cappellotto -author_url: http://www.focustheweb.com/ +contributors: + - ["Giovanni Cappellotto", "http://www.focustheweb.com/"] filename: learnerlang.erl --- ```erlang -% Percent sign start a one-line comment. +% Percent sign starts a one-line comment. %% Two percent characters shall be used to comment functions. @@ -17,7 +17,7 @@ filename: learnerlang.erl % patterns. % Periods (`.`) (followed by whitespace) separate entire functions and % expressions in the shell. -% Semicolons (`;`) separate clauses. We find clauses in several contexts: in kn +% Semicolons (`;`) separate clauses. We find clauses in several contexts: % function definitions and in `case`, `if`, `try..catch` and `receive` % expressions. @@ -26,8 +26,10 @@ filename: learnerlang.erl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Num = 42. % All variable names must start with an uppercase letter. + % Erlang has single assignment variables, if you try to assign a different value % to the variable `Num`, you’ll get an error. +Num = 43. % ** exception error: no match of right hand side value 43 % In most languages, `=` denotes an assignment statement. In Erlang, however, % `=` denotes a pattern matching operation. `Lhs = Rhs` really means this: @@ -42,6 +44,11 @@ Pi = 3.14159. % start with lowercase letters, followed by a sequence of alphanumeric % characters or the underscore (`_`) or at (`@`) sign. Hello = hello. +OtherNode = example@node. + +% Atoms with non alphanumeric values can be written by enclosing the atoms +% with apostrophes. +AtomWithSpace = 'some atom with space'. % Tuples are similar to structs in C. Point = {point, 10, 45}. @@ -60,15 +67,15 @@ Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}. % We create a list by enclosing the list elements in square brackets and % separating them with commas. % The individual elements of a list can be of any type. -% The first element of a list the head of the list. If you imagine removing the +% The first element of a list is the head of the list. If you imagine removing the % head from the list, what’s left is called the tail of the list. ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}]. -% If `T` is a list, then `[H|T]` is also a list, with head H and tail T. +% If `T` is a list, then `[H|T]` is also a list, with head `H` and tail `T`. % The vertical bar (`|`) separates the head of a list from its tail. % `[]` is the empty list. % We can extract elements from a list with a pattern matching operation. If we -% have the nonempty list `L`, then the expression `[X|Y] = L`, where `X` and `Y` +% have a nonempty list `L`, then the expression `[X|Y] = L`, where `X` and `Y` % are unbound variables, will extract the head of the list into `X` and the tail % of the list into `Y`. [FirstThing|OtherThingsToBuy] = ThingsToBuy. @@ -78,6 +85,7 @@ ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}]. % There are no strings in Erlang. Strings are really just lists of integers. % Strings are enclosed in double quotation marks (`"`). Name = "Hello". +[72, 101, 108, 108, 111] = "Hello". %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -89,9 +97,9 @@ Name = "Hello". % Modules must be compiled before the code can be run. A compiled module has the % extension `.beam`. -module(geometry). --export([area/1]). +-export([area/1]). % the list of functions exported from the module. -% The function area consists of two clauses. The clauses are separated by a +% The function `area` consists of two clauses. The clauses are separated by a % semicolon, and the final clause is terminated by dot-whitespace. % Each clause has a head and a body; the head consists of a function name % followed by a pattern (in parentheses), and the body consists of a sequence of @@ -109,17 +117,17 @@ c(geometry). % {ok,geometry} geometry:area({rectangle, 10, 5}). % 50 geometry:area({circle, 1.4}). % 6.15752 -% In Erlang, two functions with the same name and different arity in the same -% module represent entirely different functions. +% In Erlang, two functions with the same name and different arity (number of arguments) +% in the same module represent entirely different functions. -module(lib_misc). --export([sum/1]). +-export([sum/1]). % export function `sum` of arity 1 accepting one argument: list of integers. sum(L) -> sum(L, 0). sum([], N) -> N; sum([H|T], N) -> sum(T, H+N). -% Funs are "anonymous" functions. They are called this because they have no -% name. -Double = fun(X) -> 2*X end. +% Funs are "anonymous" functions. They are called this way because they have no +% name. However they can be assigned to variables. +Double = fun(X) -> 2*X end. % `Double` points to an anonymous function with handle: #Fun<erl_eval.6.17052888> Double(2). % 4 % Functions accept funs as their arguments and can return funs. @@ -133,6 +141,8 @@ Triple(5). % 15 % from the list `L`." L = [1,2,3,4,5]. [2*X || X <- L]. % [2,4,6,8,10] +% A list comprehension can have generators and filters which select subset of the generated values. +EvenNumbers = [N || N <- [1, 2, 3, 4], N rem 2 == 0]. % [2, 4] % Guards are constructs that we can use to increase the power of pattern % matching. Using guards, we can perform simple tests and comparisons on the @@ -181,7 +191,7 @@ X2 = X1#todo{status = done}. % #todo{status = done,who = joe,text = "Fix errata in book"} % `case` expressions. -% `filter` returns a list of all those elements `X` in `L` for which `P(X)` is +% `filter` returns a list of all elements `X` in a list `L` for which `P(X)` is % true. filter(P, [H|T]) -> case P(H) of @@ -189,6 +199,7 @@ filter(P, [H|T]) -> false -> filter(P, T) end; filter(P, []) -> []. +filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]). % [2, 4] % `if` expressions. max(X, Y) -> @@ -198,7 +209,7 @@ max(X, Y) -> true -> nil; end. -% Warning: at least one of the guards in the if expression must evaluate to true; +% Warning: at least one of the guards in the `if` expression must evaluate to true; % otherwise, an exception will be raised. @@ -234,6 +245,7 @@ catcher(N) -> catch generate_exception(N). ## References -* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong +* ["Learn You Some Erlang for great good!"](http://learnyousomeerlang.com/) +* ["Programming Erlang: Software for a Concurrent World" by Joe Armstrong](http://pragprog.com/book/jaerlang/programming-erlang) +* [Erlang/OTP Reference Documentation](http://www.erlang.org/doc/) * [Erlang - Programming Rules and Conventions](http://www.erlang.se/doc/programming_rules.shtml) -* [Erlang/OTP Documentation](http://www.erlang.org/doc/) diff --git a/es-es/c-es.html.markdown b/es-es/c-es.html.markdown new file mode 100644 index 00000000..b109f761 --- /dev/null +++ b/es-es/c-es.html.markdown @@ -0,0 +1,425 @@ +--- +language: c +filename: learnc-es.c +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Francisco García", "http://flaskbreaker.tumblr.com/"] +lang: es-es +--- + +¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la +computación moderna de alto rendimiento. + +C es el lenguaje de más bajo nivel que la mayoría de los programadores +llegarán a usar, pero lo compensa de sobra con pura velocidad. Solo +ten en cuenta el manejo manual de memoria y te llevará tan lejos como +necesites. + +```c +// Los comentarios de una sola línea comienzan con // + +/* +Los comentarios multilínea tienen este aspecto. +*/ + +// Importa cabeceras con #include +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// Declara por adelantado las armaduras de las funciones en un archivo .h, +// o al principio de tu archivo .c . +void function_1(); +void function_2(); + +// El punto de entrada de tu programa es una función llamada main con +// retorno de tipo entero (integer). +int main() { + +// Muestra la salida usando printf, para el "formato print" +// %d es un entero, \n es una nueva línea +printf("%d\n", 0); // => Muestra 0 +// Todas las sentencias deben terminar con un punto y coma. + +/////////////////////////////////////// +// Tipos +/////////////////////////////////////// + +// Tienes que declarar una variable antes de usarla. La declaración de una +// variable necesites que especifiques su tipo; el tipo de una variable +// determina su tamaño en bytes. + +// 'ints' (enteros) son normalmente de 4 bytes +int x_int = 0; + +// 'shorts' son normalmente de 2 bytes +short x_short = 0; + +// 'chars' son fijo de 1 byte +char x_char = 0; +char y_char = 'y'; // Los caracteres literales se entrecomillan con '' + +// 'longs' son a menudo de 4 a 8 bytes; 'long longs' son fijo de por lo +// menos 64 bits +long x_long = 0; +long long x_long_long = 0; + +// 'floats' son normalmente números de coma flotante de 32 bits +float x_float = 0.0; + +// 'doubles' son normalmente números de coma flotante de 64 bits +double x_double = 0.0; + +// Todos los tipos enteros pueden ser 'unsigned'. Esto significa que no +// pueden ser negativos, pero el valor máximo de una variable 'unsigned' +// es mayor que el de una no 'unsigned' del mismo tamaño. +unsigned char ux_char; +unsigned short ux_short; +unsigned int ux_int; +unsigned long long ux_long_long; + +// Todos menos 'char', que es siempre de 1 byte, varían el tamaño +// dependiendo de tu máquina. sizeof(T) te dice el tamaño de una variable +// de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos +// portatilmente. +// Por ejemplo, +printf("%lu\n", sizeof(int)); // => 4 (en máquinas con 'words' de 4 bytes) + +// Los arrays deben ser inicializados con un tamaño concreto. +char my_char_array[20]; // Este array ocupa 1 * 20 = 20 bytes +int my_int_array[20]; // Este array ocupa 4 * 20 = 80 bytes + // (suponiendo que tenemos 'words' de 4-byte) + + +// Puedes inicializar un array a 0 así: +char my_array[20] = {0}; + +// Indexar un array es como en otros lenguajes -o, más bien, otros +// lenguajes son como C- +my_array[0]; // => 0 + +// Los arrays varían; ¡son sólo memoria! +my_array[1] = 2; +printf("%d\n", my_array[1]); // => 2 + +// Las cadenas (strings) son sólo arrays de 'chars' (caracteres) +// terminados en un byte NUL (0x00), representado en las cadenas como el +// carácter especial '\0'. +// (No tenemos porqué añadir el byte nulo en cadenas literales; el +// compilador lo añade al final por nosotros.) +char a_string[20] = "Esto es una cadena"; +printf("%s\n", a_string); // %s se sutituye por una cadena. + +/* +Te habrás dado cuenta de que a_string es solo de 18 caracteres. +El 'char' #19 es el byte nulo. +El 'char' #20 es de valor indefinido. +*/ + +printf("%d\n", a_string[18]); // => 0 + +/////////////////////////////////////// +// Operadores +/////////////////////////////////////// + +int i1 = 1, i2 = 2; // Forma corta de declaración múltiple +float f1 = 1.0, f2 = 2.0; + +// La aritmética es sencilla +i1 + i2; // => 3 +i2 - i1; // => 1 +i2 * i1; // => 2 +i1 / i2; // => 0 (0.5, pero es truncado tras el 0) + +f1 / f2; // => 0.5, más o menos épsilon +// Módulo está también +11 % 3; // => 2 + +// Los operadores de comparación te resultaran familiares, pero no hay +// booleanos en C. Usamos enteros (ints) en su lugar. 0 es falso, +// cualquier otra cosa es verdadero. (Los operadores de comparación +// siempre devuelven 0 o 1) +3 == 2; // => 0 (Falso) +3 != 2; // => 1 (Verdadero) +3 > 2; // => 1 +3 < 2; // => 0 +2 <= 2; // => 1 +2 >= 2; // => 1 + +// La lógica funiona en enteros +!3; // => 0 (not lógico) +!0; // => 1 +1 && 1; // => 1 (and lógico) +0 && 1; // => 0 +0 || 1; // => 1 (or lógico) +0 || 0; // => 0 + +// ¡Operadores de bits! +~0x0F; // => 0xF0 (Negación) +0x0F & 0xF0; // => 0x00 (AND) +0x0F | 0xF0; // => 0xFF (OR) +0x04 ^ 0x0F; // => 0x0B (XOR) +0x01 << 1; // => 0x02 (desplazar hacia la izquierda (por 1)) +0x02 >> 1; // => 0x01 (desplazar hacia la derecha (por 1)) + +/////////////////////////////////////// +// Estructuras de Control +/////////////////////////////////////// + +if (0) { + printf("Yo nunca ocurro\n"); +} else if (0) { + printf("Yo tampoco ocurro nunca\n"); +} else { + printf("Yo me muestro\n"); +} + +// Mientras el bucle exista +int ii = 0; +while (ii < 10) { + printf("%d, ", ii++); // ii++ incrementa ii en uno, después de usar su valor. +} // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +int kk = 0; +do { + printf("%d, ", kk); +} while (++kk < 10); // ++kk incrementa kk en uno, antes de usar su valor. +// => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +// Bucles 'for' también +int jj; +for (jj=0; jj < 10; jj++) { + printf("%d, ", jj); +} // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +/////////////////////////////////////// +// Cambios de Tipo +/////////////////////////////////////// + +// Cada valor en C tiene un tipo, pero tu puedes ingresar un valor en +// otro tipo si quieres. + +int x_hex = 0x01; // Puedes asignar hexadecimales a variables + +// El cambio de tipos intentará mantener sus valores numéricos +printf("%d\n", x_hex); // => Muestra 1 +printf("%d\n", (short) x_hex); // => Muestra 1 +printf("%d\n", (char) x_hex); // => Muestra 1 + +// Los tipos se desbordan sin aviso +printf("%d\n", (char) 257); // => 1 (El valor máximo de un 'char' es 255) + +// Los tipos enteros puden cambiarse a tipos de coma flotante, y viceversa +printf("%f\n", (float)100); // %f se sustituye por un 'float' +printf("%lf\n", (double)100); // %lf se sustituye por un 'double' +printf("%d\n", (char)100.0); + +/////////////////////////////////////// +// Punteros +/////////////////////////////////////// + +// Un puntero es una variable declarada para almacenar una dirección de +// memoria. Su declaración además nos dirá el tipo de dato al que apunta. +// Puedes obtener la dirección de memoria de tus variables, y después +// enlazarlas con ellos. + +int x = 0; +printf("%p\n", &x); // Usa & para obtener la dirección de una variable. +// (%p se sustituye por un puntero) +// => Muestra alguna dirección de memoria; + +// Los tipos de puntero terminan con * en su declaración +int* px; // px es un puntero a un 'int' +px = &x; // Almacena la dirección de x en px +printf("%p\n", px); // => Muestra alguna dirección de memoria + +// Para obtener el valor de la dirección a la que apunta un puntero, pon +// * delante para desreferenciarle. +printf("%d\n", *px); // => Muestra 0, el valor de x y de la dirección a la + // que apunta px + +// También puedes cambiar el valor al que está apuntando el puntero. +// Tenemos que meter la desreferencia entre paréntesis porque ++ tiene +// prioridad frente a *. +(*px)++; // Incrementa el valor al que apunta px en 1 +printf("%d\n", *px); // => Muestra 1 +printf("%d\n", x); // => Muestra 1 + +int x_array[20]; // Los arrays son una buena manera de distribuir bloques +int xx; // continuos de memoria. +for (xx=0; xx<20; xx++) { + x_array[xx] = 20 - xx; +} // Inicializa x_array a 20, 19, 18,... 2, 1 + +// Declara un puntero de tipo 'int' y lo inicializa para apuntar a x_array +int* x_ptr = x_array; +// x_ptr ahira apunta al primer elemento del 'array' (el entero 20). +// Esto funciona porque las 'arrays' actualmente son solo punteros a su +// primer elemento. + +// Los 'arrays' son punteros a su primer elemento. +printf("%d\n", *(x_ptr)); // => Muestra 20 +printf("%d\n", x_array[0]); // => Muestra 20 + +// Los punteros aumentan y disminuyen en función de su tipo. +printf("%d\n", *(x_ptr + 1)); // => Muestra 19 +printf("%d\n", x_array[1]); // => Muestra 19 + +// Puedes también asigner dinamicamente bloques contiguos de memoria con +// la función malloc de la librería estándard, que toma un entero como +// argumento representando el número de bytes a asignar de la pila. +int* my_ptr = (int*) malloc(sizeof(int) * 20); +for (xx=0; xx<20; xx++) { + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx funcionaría también aquí +} // Inicializa la memoria a 20, 19, 18, 17... 2, 1 (como 'ints') + +// Desreferenciando la memoria que no has asignado te dará resultados +// impredecibles +printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? + +// Cuando hallas acabado con el bloque de memoría malloc, necesitas +// liberarlo o sino nadie más podrá usarlo hasta que tu programa se cierre +free(my_ptr); + +// Las cadenas pueden ser 'arrays' de chars, pero normalmente se +// representan con punteros 'char': +char* my_str = "This is my very own string"; + +printf("%c\n", *my_str); // => 'T' + +function_1(); +} // fin de la función main + +/////////////////////////////////////// +// Funciones +/////////////////////////////////////// + +// Sintexis de la declaración de funciones: +// <tipo de retorno> <nombre>(<argumentos>) + +int add_two_ints(int x1, int x2){ + return x1 + x2; // Usa 'return' para dar una salida +} + +/* +Las funciones son de paso por valor, pero puedes hacer tus propias +referencias con punteros de manera que las funciones puedan cambiar sus +valores. + +Ejemplo: invertidor de cadenas in-situ +*/ + +// Una función 'void' no retorna valor +void str_reverse(char* str_in){ + char tmp; + int ii=0, len = strlen(str_in); // Strlen es parte de la librería + for(ii=0; ii<len/2; ii++){ // estándard + tmp = str_in[ii]; + str_in[ii] = str_in[len - ii - 1]; // ii-th último 'char' + str_in[len - ii - 1] = tmp; + } +} + +/* +char c[] = "Esto es una prueba."; +str_reverse(c); +printf("%s\n", c); // => ".abeurp anu se otsE" +*/ + +/////////////////////////////////////// +// Definición de tipos y estructuras +/////////////////////////////////////// + +// Los 'Typedefs' pueden ser utilizados para crear alias de tipos. +typedef int my_type; +my_type my_type_var = 0; + +// Las estructuras son sólo grupos de datos. +struct rectangle { + int width; + int height; +}; + + +void function_1(){ + + struct rectangle my_rec; + + // Utiliza los miembros de una estructura con . + my_rec.width = 10; + my_rec.height = 20; + + // Puedes declarar punteros a estructuras + struct rectangle* my_rec_ptr = &my_rec; + + // Usa la desreferencia para modificar sus miembros... + (*my_rec_ptr).width = 30; + + // ... o usa la abreviatura -> + my_rec_ptr->height = 10; // Lo mismo que (*my_rec_ptr).height = 10; +} + +// Puedes aplicar un 'typedef' a una estructura por conveniencía. +typedef struct rectangle rect; + +int area(rect r){ + return r.width * r.height; +} + +/////////////////////////////////////// +// Punteros a Funciones +/////////////////////////////////////// +/* +En tiempo de ejecución, las funciones se localizan en unas direcciones de +memoria concretas. Los punteros a funciones son como cualquier otro +puntero (almacenan una dirección de memoria), pero pueden ser usados para +utilizar funciones directamente, o para pasar 'handlers' (o funciones +'callback') por todos lados. +Sin embargo, la sintaxis de definición parecera confusa al principio. + +Ejemplo: usar str_reverse desde un puntero +*/ +void str_reverse_through_pointer(char * str_in) { + // Define un puntero a una función, llamado f. + void (*f)(char *); + // La armadura debe coincidir exactamente con al función objetivo. + + // Assigna la dirección de la función (determinado en tiempo de ejecuión) + f = &str_reverse; + + // Llamando la función desde el puntero + (*f)(str_in); + + // Esta es una alternativa para llamarla pero con una sintaxis igual de válida. + // f(str_in); +} + +/* +Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar +cualquier función al mismo puntero. +Los punteros a funciones son normalmente envueltos en 'typedef' para +simplificar su legibilidad, como sigue: +*/ + +typedef void (*my_fnp_type)(char *); + +// Es usado para declarar la variable puntero actual: +// ... +// my_fnp_type f; + +``` + +## Otras lecturas + +Lo mejor que puedes en contrar es una copia de [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language) + +Otro buen recurso es [Learn C the hard way](http://c.learncodethehardway.org/book/) + +Aparte de eso, Google es tu amigo. diff --git a/es-es/elisp-es.html.markdown b/es-es/elisp-es.html.markdown new file mode 100644 index 00000000..a6cd3934 --- /dev/null +++ b/es-es/elisp-es.html.markdown @@ -0,0 +1,378 @@ +--- +language: elisp +contributors: + - ["Bastien Guerry", "http://bzg.fr"] +translators: + - ["Guillermo Vayá", "http://willyfrog.es"] +lang: es-es +filename: learn-emacs-lisp-es.el +--- + +```scheme +;; Introduccion a Emacs Lisp en 15 minutos (v0.2d) +;; +;; Autor: Bastien / @bzg2 / http://bzg.fr +;; Traducción: Guillermo Vayá / @Driadan / http://willyfrog.es +;; +;; Antes de nada, lee este texto de Peter Norvig: +;; Traducido: http://loro.sourceforge.net/notes/21-dias.html +;; Original: http://norvig.com/21-days.html +;; +;; Ahora instala GNU Emacs 24.3: +;; +;; Debian: apt-get install emacs +;; (o sigue las instrucciones de tu distribución preferida) +;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg +;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip +;; +;; Puedes encontrar información general sobre Emacs en: +;; http://www.gnu.org/software/emacs/#Obtaining + +;; Aviso importante: +;; +;; Seguir este tutorial no provocará daños en tu ordenador a menos que +;; te enfades tanto que que acabes tirándolo al suelo. En tal caso +;; declino cualquier responsabilidad. ¡A divertirse! + + +;; "N. del. T.": Algunos términos comunes de la informática se han dejado +;; sin traducir ya que es mucho más probable que el lector los conozca en +;; su forma en inglés, siendo la versión en español de muy raro uso. +;; Además "sexps" se ha decidido traducir por sexpresión. +;; Por último, añadir que no se han traducido los ejemplos de código ya que no +;; es necesario entender qué dice el string para comprender el funcionamiento +;; y podría llevar a error. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Inicia Emacs. +;; +;; Pulsa la tecla `q' para pasar el mensaje de bienvenida. +;; +;; Mira a la línea gris en la parte inferior de la ventana: +;; +;; "*scratch*" es el nombre del espacio editable donde estás. +;; A este espacio editable se le llama "buffer". +;; +;; Scratch es el buffer por defecto cuando abres Emacs. +;; En Emacs nunca editas ficheros, sino que editas buffers que +;; posteriormente pueden grabarse a un fichero. +;; can save to a file. +;; +;; "Lisp interaction" indica el conjunto de ordenes disponibles. +;; +;; Emacs dispone de un set de comandos disponibles en cualquier buffer +;; ("built-ins") y aparte varios conjuntos de ordenes disponibles +;; según el modo específico que esté activo. En nuestro caso +;; estamos usando `lisp-interaction-mode', el cual incluye las +;; ordenes necesarias para evaluar y navegar código Elisp. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Un punto y coma comienza un comentario. Pueden ponerse en cualquier +;; posicion de la linea. +;; +;; Los programas en Elisp se componen de expresiones simbólicas +;; tambien llamadas "sexps": +(+ 2 2) + +;; Esta expresión simbólica se lee tal que "Suma 2 y 2" + +;; Las sexpresiones se rodean por paréntesis, y pueden anidarse: +(+ 2 (+ 1 1)) + +;; Una expresion simbólica está formada bien por átomos o bien por otras +;; expresiones simbólicas. En el ejemplo de arriba, 1 y 2 son átomos, +;; mientras que (+ 2 (+ 1 1)) y (+ 1 1) son expresiones simbólicas. + +;; Gracias a `lisp-interaction-mode' puedes evaluar las sexpresiones. +;; Coloca el cursor justo despues del paréntesis de cierre y +;; mantén pulsada la tecla Control y la j (para abreviar usaremos "C-j"). + +(+ 3 (+ 1 2)) +;; ^ pon aquí el cursor +;; `C-j' => 6 + +;; `C-j' añade el resultado de la evaluación al buffer. + +;; `C-xC-e' muestra el mismo resultado pero en la linea inferior +;; la cual se llama "minibuffer". Este será el metodo que usaremos +;; normalmente para no llenar el buffer con texto inútil. + +;; `setq' guarda un valor en una variable: +(setq my-name "Bastien") +;; `C-xC-e' => "Bastien" (aparece en el mini-buffer) + +;; `insert' añade "Hello!" en el punto donde esté tu cursor: +(insert "Hello!") +;; `C-xC-e' => "Hello!" + +;; Aunque hemos usado `insert' con solo un parámetro "Hello!", se +;; pueden pasar más. Por ejemplo, en esta otra sexpresión usamos dos: + +(insert "Hello" " world!") +;; `C-xC-e' => "Hello world!" + +;; Se pueden usar variables en lugar de strings: +(insert "Hello, I am " my-name) +;; `C-xC-e' => "Hello, I am Bastien" + +;; Puedes combinar sexpresiones en funciones: +(defun hello () (insert "Hello, I am " my-name)) +;; `C-xC-e' => hello + +;; Evaluemos la funcion: +(hello) +;; `C-xC-e' => Hello, I am Bastien + +;; Los parentesis vacios en la definicion de una funcion indican +;; que no acepta parámetros. En cualquier caso, usar `my-name' siempre +;; es aburrido, asi que vamos a hacer que la función accepte un parámetro +;; (en este caso el parametro se llama "name"): +(defun hello (name) (insert "Hello " name)) +;; `C-xC-e' => hello + +;; Ahora vamos a llamar a la funcion con el string "you" como valor para +;; el único parámetro que posee. +(hello "you") +;; `C-xC-e' => "Hello you" + +;; ¡Genial! + +;; Descansa un poco y respira. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Ahora cambiaremos al nuevo buffer, llamado "*test*", en una nueva ventana. + +(switch-to-buffer-other-window "*test*") +;; `C-xC-e' +;; => [La pantalla ahora tiene dos ventanas y el cursor está en el buffer *test*] + +;; Mueve el ratón sobre la ventana superior y pulsa el boton izdo. para volver. +;; Otra forma es usando `C-xo' (pulsa simultaneamente control y x y luego la o) +;; para ir a la otra ventana. + +;; Se pueden combinar varias sexpresiones mediante `progn': +(progn + (switch-to-buffer-other-window "*test*") + (hello "you")) +;; `C-xC-e' +;; => [De las dos ventanas de la pantalla, el cursor está en la marcada como *test*] + +;; A partir de ahora, si no te importa, dejaremos de decir que pulses `C-xC-e': +;; tendrás que hacerlo para ejecutar cada sexpresión que siga. + +;; También tendrás que volver al buffer *scratch* bien con el ratón o con `C-xo'. + +;; En ocasiones será util limpiar el buffer: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "there")) + +;; O volver a la ventana anterior: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "you") + (other-window 1)) + +;; Puedes enlazar un valor a una variable local con `let': +(let ((local-name "you")) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello local-name) + (other-window 1)) + +;; En este caso, no hace falta añadir `progn' ya que `let' permite combinar +;; varias sexpresiones. + +;; Vamos a darle formato a un string: +(format "Hello %s!\n" "visitor") + +;; Cada %s indica la posicion donde irá un string, el cual será reemplazado +;; por "visitor". "\n" es el caracter de nueva línea. + +;; Mejoremos nuestra funcion usando `format': +(defun hello (name) + (insert (format "Hello %s!\n" name))) + +(hello "you") + +;; Creemos una nueva funcion que utililce `let': +(defun greeting (name) + (let ((your-name "Bastien")) + (insert (format "Hello %s!\n\nI am %s." + name ; the argument of the function + your-name ; the let-bound variable "Bastien" + )))) + +;; Y ahora la evaluamos: +(greeting "you") + +;; Algunas funciones son interactivas: +(read-from-minibuffer "Enter your name: ") + +;; Al evaluar esta función, ésta devuelve lo que hayas introducido. + +;; Ahora hagamos nuestra función `greeting' preguntar por tu nombre: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (insert (format "Hello!\n\nI am %s and you are %s." + from-name ; the argument of the function + your-name ; the let-bound var, entered at prompt + )))) + +(greeting "Bastien") + +;; Y ahora la completamos mostrando el resultado en la otra ventana: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (insert (format "Hello %s!\n\nI am %s." your-name from-name)) + (other-window 1))) + +;; Probémosla: +(greeting "Bastien") + +;; Descansa un poco y respira. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Creemos una lista de nombres: +(setq list-of-names '("Sarah" "Chloe" "Mathilde")) + +;; Para coger el primer elemento de la lista usaremos `car': +(car list-of-names) + +;; Para coger todos menos el primer elemento de la lista +;; usaremos `cdr': +(cdr list-of-names) + +;; Para añadir un elemento al comienzo de la lista utilizamos `push': +(push "Stephanie" list-of-names) + +;; OJO: `car' y `cdr' no modifican la lista, mientras que `push' sí. +;; ¡Es una diferencia importante! Algunas funciones no tienen efectos +;; colaterales (como `car') mientras que otras sí (como `push'). +;; "N. del T.": estos efectos colaterales se les llama `side-effects' en +;; las distintas variantes de lisp. + +;; Llamemos a `hello' con cada elemento de `list-of-names': +(mapcar 'hello list-of-names) + +;; Retocamos `greeting' para que salude a todos los que estén en `list-of-names': +(defun greeting () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (mapcar 'hello list-of-names) + (other-window 1)) + +(greeting) + +;; ¿Te acuerdas de la función `hello' definida un poco más arriba? +;; Recibía un parámetro: `name'. Así que `mapcar' llama a `hello' con cada +;; elemento de `list-of-names' como parámetro de `hello'. + +;; Ahora ordenaremos un poco lo que tenemos en el buffer: + +(defun replace-hello-by-bonjour () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (search-forward "Hello") + (replace-match "Bonjour")) + (other-window 1)) + +;; (goto-char (point-min)) mueve el cursor al principio del buffer. +;; (search-forward "Hello") busca un string "Hello". +;; (while x y) evalua la/s sexpresion/es y mientras que x devuelva +;; alguna cosa. +;; En el momento que x devuelva `nil' (es decir nada), sale del +;; bucle `while'. + +(replace-hello-by-bonjour) + +;; Observamos que todas las veces que teníamos la palabra "Hello" en el buffer *test* +;; han sido reemplazadas por "Bonjour". + +;; Y además, hemos obtenido un error: "Search failed: Hello". +;; +;; Para evitar este error, hay que decirle a `search-forward' si debería dejar de +;; buscar en el buffer en algún momento y si debería fallar sin quejarse cuando +;; no encuentra nada. + +;; (search-forward "Hello" nil t) justo hace eso: + +;; El argumento `nil' significa que la busqueda no está ligada a ninguna posición. +;; Y el argumento `t' le pide que no diga nada si no encuentra el string. + +;; Usaremos esta sexpresión en la función siguiente, la cual ya +;; no muestra ningún error: + +(defun hello-to-bonjour () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + ;; Say hello to names in `list-of-names' + (mapcar 'hello list-of-names) + (goto-char (point-min)) + ;; Replace "Hello" by "Bonjour" + (while (search-forward "Hello" nil t) + (replace-match "Bonjour")) + (other-window 1)) + +(hello-to-bonjour) + +;; Añadamos algo de color a los nombres: + +(defun boldify-names () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (re-search-forward "Bonjour \\(.+\\)!" nil t) + (add-text-properties (match-beginning 1) + (match-end 1) + (list 'face 'bold))) + (other-window 1)) + +;; Esta función nos presenta `re-search-forward': en vez de +;; buscar el string "Bonjour" exacto, se busca por un patrón +;; usando una "expresión regular" (lo cual se muestra abreviado +;; en el prefijo "re-" del inglés "Regular Expression"). + +;; La expresión regular a utilizar es "Bonjour \\(.+\\)!" y se traduce como: +;; el string "Bonjour ", seguido de +;; un grupo de | representado por \\( ... \\) +;; cualquier caracter | representado por . +;; al menos una vez | representado por + +;; y el string "!". + +;; ¿Preparado? ¡Probemoslo! + +(boldify-names) + +;; `add-text-properties' añade propiedades al texto, como una fuente. + +;; ¡Hale! ¡Ya lo tenemos! ¡Feliz hacking! + +;; Si quieres saber más sobre una función o una variable: +;; +;; C-h v la-variable RET +;; C-h f la-funcion RET +;; +;; Si quieres leer el manual de Emacs Lisp desde dentro de Emacs: +;; +;; C-h i m elisp RET +;; +;; Para leer una introducción en linea de Emacs Lisp: +;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html + +;; Me gustaría agradecer a las siguientes personas su feedback y sugerencias: +;; - Wes Hardaker +;; - notbob +;; - Kevin Montuori +;; - Arne Babenhauserheide +;; - Alan Schmitt +;; - LinXitoW +;; - Aaron Meurer +``` diff --git a/es-es/java-es.html.markdown b/es-es/java-es.html.markdown new file mode 100644 index 00000000..b34dca8d --- /dev/null +++ b/es-es/java-es.html.markdown @@ -0,0 +1,410 @@ +--- +language: java +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] +translators: + - ["Camilo Garrido", "http://www.twitter.com/hirohope"] +lang: es-es +filename: LearnJava-es.java +--- + +Java es un lenguage de programación de propósito general, concurrente, basado en clases y +orientado a objetos. +[Lee más aquí.](http://docs.oracle.com/javase/tutorial/java/index.html) + +```java +// Comentarios de una sóla línea comienzan con // +/* +Comentarios multilínea lucen así +*/ +/** +Comentarios JavaDoc lucen así. Suelen describir la clase o varios atributos +de una clase. +*/ + +// Importa la clase ArrayList dentro del paquete java.util +import java.util.ArrayList; +// Importa todas las clases dentro del paquete java.security +import java.security.*; + +// Cada archivo .java contiene una clase pública, con el mismo nombre del archivo. +public class AprendeJava { + + // Un programa debe tener un método 'main' como punto de entrada + public static void main (String[] args) { + + // Usa System.out.println para imprimir líneas + System.out.println("¡Hola mundo!"); + System.out.println( + "Entero (int): " + 10 + + " Doble (double): " + 3.14 + + " Booleano (boolean): " + true); + + // Para imprimir sin el salto de línea, usa System.out.print + System.out.print("Hola "); + System.out.print("Mundo"); + + + /////////////////////////////////////// + // Tipos & Variables + /////////////////////////////////////// + + // Declara una variable usando <tipo> <nombre> [ + // Byte - Entero complemento a dos con signo de 8-bit + // (-128 <= byte <= 127) + byte fooByte = 100; + + // Short - Entero complemento a dos con signo de 16-bit + // (-32,768 <= short <= 32,767) + short fooShort = 10000; + + // Integer - Entero complemento a dos con signo de 32-bit + // (-2,147,483,648 <= int <= 2,147,483,647) + int fooInt = 1; + + // Long - Entero complemento a dos con signo de 64-bit + // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) + long fooLong = 100000L; + // L es usado para denotar que el valor de esta variable es del tipo Long; + // cualquier cosa sin ella es tratado como un entero por defecto. + + // Nota: Java no tiene tipos sin signo + + // Float - Número de coma flotante IEEE 754 de precisión simple de 32-bit + float fooFloat = 234.5f; + // f es usado para denotar qeu el valor de esta variable es del tipo float; + // de otra manera es tratado como un double. + + // Double - Número de coma flotante IEEE 754 de precisión doble de 64-bit + double fooDouble = 123.4; + + // Boolean - true & false + boolean fooBoolean = true; + boolean barBoolean = false; + + // Char - Un simple carácter unicode de 16-bit + char fooChar = 'A'; + + // Usa 'final' para hacer inmutable las variables + final int HORAS_QUE_TRABAJO_POR_SEMANA = 9001; + + // Strings + String fooString = "¡Mi String está aquí!"; + + // \n es un carácter escapado que inicia una nueva línea + String barString = "¿Imprimiendo en una nueva linea?\n¡Ningun problema!"; + // \t es un carácter escapado que añade un carácter tab + String bazString = "¿Quieres añadir un 'tab'?\t¡Ningun problema!"; + System.out.println(fooString); + System.out.println(barString); + System.out.println(bazString); + + // Arreglos + //El tamaño del arreglo debe decidirse en la declaración + //El formato para la declaración de un arreglo es la siguiente: + //<tipo_de_dato> [] <nombre_variable> = new <tipo_de_dato>[<tamaño_arreglo>]; + int [] arreglo_de_enteros = new int[10]; + String [] arreglo_de_strings = new String[1]; + boolean [] arreglo_de_booleanos = new boolean[100]; + + // Otra forma de declarar & inicializar un arreglo + int [] y = {9000, 1000, 1337}; + + // Indexación de un arreglo - Accediendo un elemento + System.out.println("arreglo_de_enteros @ 0: " + arreglo_de_enteros[0]); + + // Arreglos comienzan su indexación en cero y son mutables + arreglo_de_enteros[1] = 1; + System.out.println("arreglo_de_enteros @ 1: " + arreglo_de_enteros[1]); // => 1 + + // Otros para echar un vistazo + // ArrayLists - Son como arreglos excepto que ofrecen más funcionalidades + // y el tamaño es mutable + // LinkedLists + // Maps + // HashMaps + + /////////////////////////////////////// + // Operadores + /////////////////////////////////////// + System.out.println("\n->Operadores"); + + int i1 = 1, i2 = 2; // Abreviación para múltiples declaraciones + + // La aritmética es directa + System.out.println("1+2 = " + (i1 + i2)); // => 3 + System.out.println("2-1 = " + (i2 - i1)); // => 1 + System.out.println("2*1 = " + (i2 * i1)); // => 2 + System.out.println("1/2 = " + (i1 / i2)); // => 0 (0.5 truncado) + + // Módulo + System.out.println("11%3 = "+(11 % 3)); // => 2 + + // Operadores de comparación + System.out.println("3 == 2? " + (3 == 2)); // => false + System.out.println("3 != 2? " + (3 != 2)); // => true + System.out.println("3 > 2? " + (3 > 2)); // => true + System.out.println("3 < 2? " + (3 < 2)); // => false + System.out.println("2 <= 2? " + (2 <= 2)); // => true + System.out.println("2 >= 2? " + (2 >= 2)); // => true + + // ¡Operaciones a nivel de bits! + /* + ~ Complemento unario bit a bit + << Deplazamiento hacia la izquierda con signo + >> Deplazamiento hacia la derecha con signo + >>> Deplazamiento hacia la derecha sin signo + & AND lógico + ^ OR lógico exclusivo + | OR lógico inclusivo + */ + + // Incrementos + int i = 0; + System.out.println("\n->Incrementos y reducciones"); + System.out.println(i++); //i = 1. Post-incremento + System.out.println(++i); //i = 2. Pre-incremento + System.out.println(i--); //i = 1. Post-reducción + System.out.println(--i); //i = 0. Pre-reducción + + /////////////////////////////////////// + // Estructuras de Control + /////////////////////////////////////// + System.out.println("\n->Estructuras de Control"); + + // Condiciones 'if' son como en c + int j = 10; + if (j == 10){ + System.out.println("Me imprimieron"); + } else if (j > 10) { + System.out.println("A mi no"); + } else { + System.out.println("A mi tampoco"); + } + + // Ciclos 'while' + int fooWhile = 0; + while(fooWhile < 100) + { + //System.out.println(fooWhile); + //Incrementar el contador + //Iteró 99 veces, fooWhile 0->99 + fooWhile++; + } + System.out.println("Valor fooWhile: " + fooWhile); + + // Ciclos 'do while' + int fooDoWhile = 0; + do + { + //System.out.println(fooDoWhile); + //Incrementar el contador + //Iteró 99 veces, fooDoWhile 0->99 + fooDoWhile++; + }while(fooDoWhile < 100); + System.out.println("Valor fooDoWhile: " + fooDoWhile); + + // Ciclos 'for' + int fooFor; + //Estructura del ciclo 'for' => for(<declaración_de_inicio>; <condicional>; <paso>) + for(fooFor=0; fooFor<10; fooFor++){ + //System.out.println(fooFor); + //Iteró 10 veces, fooFor 0->9 + } + System.out.println("Valor fooFor: " + fooFor); + + // Switch Case + // Un 'switch' funciona con un tipo de dato byte, short, char e int + // También funciona con tipos enumerados (discutido en tipos Enum), + // la clase String y unas pocas clases especiales que envuelven + // tipos primitivos: Character, Byte, Short e Integer. + int mes = 3; + String mesString; + switch (mes){ + case 1: + mesString = "Enero"; + break; + case 2: + mesString = "Febrero"; + break; + case 3: + mesString = "Marzo"; + break; + default: + mesString = "Algun otro mes"; + break; + } + System.out.println("Resultado switch Case: " + mesString); + + + /////////////////////////////////////// + // Convirtiendo Tipos de Datos y Conversión de Tipos + /////////////////////////////////////// + + // Convirtiendo datos + + // Convertir String a Integer + Integer.parseInt("123");//retorna una versión entera de "123" + + // Convertir Integer a String + Integer.toString(123);//retorna una versión string de 123 + + // Para otras conversiones fíjate en las siguientes clases + // Double + // Long + // String + + // Conversión de tipos + // También puedes convertir objetos java, hay muchos detalles + // con unos pocos conceptos intermedios + // No dudes en verlos acá + // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html + + + /////////////////////////////////////// + // Clases y Funciones + /////////////////////////////////////// + + System.out.println("\n->Clases & Funciones"); + + // (A continuación la definición de una clase Bicicleta) + + // Usa 'new' para instanciar una clase + Bicicleta excursion = new Bicicleta(); + + // Llama métodos del objeto + excursion.aumentarVelocidad(3); // Siempre deberías usar metodos 'set' (establecer) y 'get' (obtener) + excursion.setRitmo(100); + + // 'toString' es una convención para mostrar los valores de este objeto. + System.out.println("informacion de la excursion: " + excursion.toString()); + + } // Fin del método 'main' +} // Fin de la clase AprendeJava + + +// Puedes incluir otras clases no públicas en un archivo .java + + +// Sintaxis de declaración de clases: +// <public/private/protected> class <nombre_de_la_clase>{ +// //variables_de_clase, constructores, todas las funciones. +// //las funciones son llamadas como métodos en Java. +// } + +class Bicicleta { + + // Campos/Variables de Bicicleta + public int ritmo; // Public: Puede ser accedido desde cualquier parte + private int velocidad; // Private: Accesible sólo desde esta clase + protected int engranaje; // Protected: Accesible desde esta clases y sus subclases + String nombre; // default: Sólo accesible desde este paquete + + // Constructores son la manera de crear clases + // Este es un constructor por defecto + public Bicicleta() { + engranaje = 1; + ritmo = 50; + velocidad = 5; + nombre = "Bontrager"; + } + + // Este es un constructor específico (contiene argumentos) + public Bicicleta(int ritmoInicial, int velocidadInicial, int engranajeInicial, String nombre) { + this.engranaje = engranajeInicial; + this.ritmo = ritmoInicial; + this.velocidad = velocidadInicial; + this.nombre = nombre; + } + + // Sintaxis de función: + // <public/private/protected> <tipo_de_retorno> <nombre_funcion>(<argumentos>) + + // Las clases de Java usualmente implementan métodos 'get' (obtener) y 'set' (establecer) para sus campos + + // Sintaxis de declaración de métodos + // <alcance> <tipo_de_retorno> <nombre_metodo>(<argumentos>) + public int getRitmo() { + return ritmo; + } + + // Métodos void no requieren retornar + public void setRitmo(int nuevoValor) { + ritmo = nuevoValor; + } + + public void setEngranaje(int nuevoValor) { + engranaje = nuevoValor; + } + + public void aumentarVelocidad(int incremento) { + velocidad += incremento; + } + + public void disminuirVelocidad(int reduccion) { + velocidad -= reduccion; + } + + public void setNombre(String nuevoNombre) { + nombre = nuevoNombre; + } + + public String getNombre() { + return nombre; + } + + //Método para mostrar los valores de los atributos de este objeto. + @Override + public String toString() { + return "engranaje: " + engranaje + + " ritmo: " + ritmo + + " velocidad: " + velocidad + + " nombre: " + nombre; + } +} // fin clase Bicicleta + +// PennyFarthing es una subclase de Bicicleta +class PennyFarthing extends Bicicleta { + // (Penny Farthings son esas bicicletas con una gran rueda forntal. + // No tienen engranajes.) + + public PennyFarthing(int ritmoInicial, int velocidadInicial){ + // Llama al constructor del padre con super + super(ritmoInicial, velocidadInicial, 0, "PennyFarthing"); + } + + // Deberías marcar un método que estás sobre escribiendo con una @anotacion + // Para aprender más sobre que son y el propósito de las anotaciones + // echa un vistazo acá: http://docs.oracle.com/javase/tutorial/java/annotations/ + @Override + public void setEngranaje(int engranaje) { + engranaje = 0; + } + +} + +``` + +## Más Lectura + +Estos links son sólo para tener un entendimiento del tema, no dudes en +usar Google y encontrar ejemplos más específicos + +Otros temas a investigar: + +* [Java Tutorial Trail from Sun / Oracle](http://docs.oracle.com/javase/tutorial/index.html) + +* [Java Access level modifiers](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) + +* [Object-Oriented Programming Concepts](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): + * [Inheritance](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) + * [Polymorphism](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) + * [Abstraction](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) + +* [Exceptions](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) + +* [Interfaces](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) + +* [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html) + +* [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html) diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown new file mode 100644 index 00000000..f92f5cde --- /dev/null +++ b/es-es/python-es.html.markdown @@ -0,0 +1,490 @@ +--- +language: python +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Camilo Garrido", "http://www.twitter.com/hirohope"] +lang: es-es +filename: learnpython-es.py +--- + +Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno +de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica. +Es básicamente pseudocódigo ejecutable. + +¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] + +Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser aplicable a Python 2.x. ¡Pronto un recorrido por Python 3! + +```python +# Comentarios de una línea comienzan con una almohadilla (o signo gato) +""" Strings multilinea pueden escribirse + usando tres "'s, y comunmente son usados + como comentarios. +""" + +#################################################### +## 1. Tipos de datos primitivos y operadores. +#################################################### + +# Tienes números +3 #=> 3 + +# Matemática es lo que esperarías +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# La división es un poco complicada. Es división entera y toma la parte entera +# de los resultados automáticamente. +5 / 2 #=> 2 + +# Para arreglar la división necesitamos aprender sobre 'floats' +# (números de coma flotante). +2.0 # Esto es un 'float' +11.0 / 4.0 #=> 2.75 ahhh...mucho mejor + +# Refuerza la precedencia con paréntesis +(1 + 3) * 2 #=> 8 + +# Valores 'boolean' (booleanos) son primitivos +True +False + +# Niega con 'not' +not True #=> False +not False #=> True + +# Igualdad es == +1 == 1 #=> True +2 == 1 #=> False + +# Desigualdad es != +1 != 1 #=> False +2 != 1 #=> True + +# Más comparaciones +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# ¡Las comparaciones pueden ser concatenadas! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Strings se crean con " o ' +"Esto es un string." +'Esto también es un string' + +# ¡Strings también pueden ser sumados! +"Hola " + "mundo!" #=> "Hola mundo!" + +# Un string puede ser tratado como una lista de caracteres +"Esto es un string"[0] #=> 'E' + +# % pueden ser usados para formatear strings, como esto: +"%s pueden ser %s" % ("strings", "interpolados") + +# Una forma más reciente de formatear strings es el método 'format'. +# Este método es la forma preferida +"{0} pueden ser {1}".format("strings", "formateados") +# Puedes usar palabras claves si no quieres contar. +"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") + +# None es un objeto +None #=> None + +# No uses el símbolo de igualdad `==` para comparar objetos con None +# Usa `is` en lugar de +"etc" is None #=> False +None is None #=> True + +# El operador 'is' prueba la identidad del objeto. Esto no es +# muy útil cuando se trata de datos primitivos, pero es +# muy útil cuando se trata de objetos. + +# None, 0, y strings/listas vacíos(as) todas se evalúan como False. +# Todos los otros valores son True +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Variables y Colecciones +#################################################### + +# Imprimir es muy fácil +print "Soy Python. ¡Encantado de conocerte!" + + +# No hay necesidad de declarar las variables antes de asignarlas. +una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas +una_variable #=> 5 + +# Acceder a variables no asignadas previamente es una excepción. +# Ve Control de Flujo para aprender más sobre el manejo de excepciones. +otra_variable # Levanta un error de nombre + +# 'if' puede ser usado como una expresión +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Listas sobre secuencias +lista = [] +# Puedes empezar con una lista prellenada +otra_lista = [4, 5, 6] + +# Añadir cosas al final de una lista con 'append' +lista.append(1) #lista ahora es [1] +lista.append(2) #lista ahora es [1, 2] +lista.append(4) #lista ahora es [1, 2, 4] +lista.append(3) #lista ahora es [1, 2, 4, 3] +# Remueve del final de la lista con 'pop' +lista.pop() #=> 3 y lista ahora es [1, 2, 4] +# Pongámoslo de vuelta +lista.append(3) # Nuevamente lista ahora es [1, 2, 4, 3]. + +# Accede a una lista como lo harías con cualquier arreglo +lista[0] #=> 1 +# Mira el último elemento +lista[-1] #=> 3 + +# Mirar fuera de los límites es un error 'IndexError' +lista[4] # Levanta la excepción IndexError + +# Puedes mirar por rango con la sintáxis de trozo. +# (Es un rango cerrado/abierto para ustedes los matemáticos.) +lista[1:3] #=> [2, 4] +# Omite el inicio +lista[2:] #=> [4, 3] +# Omite el final +lista[:3] #=> [1, 2, 4] + +# Remueve elementos arbitrarios de una lista con 'del' +del lista[2] # lista ahora es [1, 2, 3] + +# Puedes sumar listas +lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan + +# Concatenar listas con 'extend' +lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] + +# Chequea la existencia en una lista con +1 in lista #=> True + +# Examina el largo de una lista con 'len' +len(lista) #=> 6 + + +# Tuplas son como listas pero son inmutables. +tupla = (1, 2, 3) +tupla[0] #=> 1 +tupla[0] = 3 # Levanta un error TypeError + +# También puedes hacer todas esas cosas que haces con listas +len(tupla) #=> 3 +tupla + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tupla[:2] #=> (1, 2) +2 in tupla #=> True + +# Puedes desempacar tuplas (o listas) en variables +a, b, c = (1, 2, 3) # a ahora es 1, b ahora es 2 y c ahora es 3 +# Tuplas son creadas por defecto si omites los paréntesis +d, e, f = 4, 5, 6 +# Ahora mira que fácil es intercambiar dos valores +e, d = d, e # d ahora es 5 y e ahora es 4 + + +# Diccionarios almacenan mapeos +dicc_vacio = {} +# Aquí está un diccionario prellenado +dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} + +# Busca valores con [] +dicc_lleno["uno"] #=> 1 + +# Obtén todas las llaves como una lista +dicc_lleno.keys() #=> ["tres", "dos", "uno"] +# Nota - El orden de las llaves del diccionario no está garantizada. +# Tus resultados podrían no ser los mismos del ejemplo. + +# Obtén todos los valores como una lista +dicc_lleno.values() #=> [3, 2, 1] +# Nota - Lo mismo que con las llaves, no se garantiza el orden. + +# Chequea la existencia de una llave en el diccionario con 'in' +"uno" in dicc_lleno #=> True +1 in dicc_lleno #=> False + +# Buscar una llave inexistente deriva en KeyError +dicc_lleno["cuatro"] # KeyError + +# Usa el método 'get' para evitar la excepción KeyError +dicc_lleno.get("uno") #=> 1 +dicc_lleno.get("cuatro") #=> None +# El método 'get' soporta un argumento por defecto cuando el valor no existe. +dicc_lleno.get("uno", 4) #=> 1 +dicc_lleno.get("cuatro", 4) #=> 4 + +# El método 'setdefault' es una manera segura de añadir nuevos pares +# llave-valor en un diccionario +dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 +dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 + + +# Sets (conjuntos) almacenan ... bueno, conjuntos +conjunto_vacio = set() +# Inicializar un conjunto con montón de valores +un_conjunto = set([1,2,2,3,4]) # un_conjunto ahora es set([1, 2, 3, 4]) + +# Desde Python 2.7, {} puede ser usado para declarar un conjunto +conjunto_lleno = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Añade más valores a un conjunto +conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} + +# Haz intersección de conjuntos con & +otro_conjunto = {3, 4, 5, 6} +conjunto_lleno & otro_conjunto #=> {3, 4, 5} + +# Haz unión de conjuntos con | +conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} + +# Haz diferencia de conjuntos con - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# CHequea la existencia en un conjunto con 'in' +2 in conjunto_lleno #=> True +10 in conjunto_lleno #=> False + + +#################################################### +## 3. Control de Flujo +#################################################### + +# Hagamos sólo una variable +una_variable = 5 + +# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! +# imprime "una_variable es menor que 10" +if una_variable > 10: + print "una_variable es completamente mas grande que 10." +elif una_variable < 10: # Este condición 'elif' es opcional. + print "una_variable es mas chica que 10." +else: # Esto también es opcional. + print "una_variable es de hecho 10." + + +""" +For itera sobre listas +imprime: + perro es un mamifero + gato es un mamifero + raton es un mamifero +""" +for animal in ["perro", "gato", "raton"]: + # Puedes usar % para interpolar strings formateados + print "%s es un mamifero" % animal + +""" +`range(número)` retorna una lista de números +desde cero hasta el número dado +imprime: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While itera hasta que una condición no se cumple. +imprime: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # versión corta de x = x + 1 + +# Maneja excepciones con un bloque try/except + +# Funciona desde Python 2.6 en adelante: +try: + # Usa raise para levantar un error + raise IndexError("Este es un error de indice") +except IndexError as e: + pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. + + +#################################################### +## 4. Funciones +#################################################### + +# Usa 'def' para crear nuevas funciones +def add(x, y): + print "x es %s y y es %s" % (x, y) + return x + y # Retorna valores con una la declaración return + +# Llamando funciones con parámetros +add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 + +# Otra forma de llamar funciones es con argumentos de palabras claves +add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. + +# Puedes definir funciones que tomen un número variable de argumentos +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Puedes definir funciones que toman un número variable de argumentos +# de palabras claves +def keyword_args(**kwargs): + return kwargs + +# Llamémosla para ver que sucede +keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"} + +# Puedes hacer ambas a la vez si quieres +def todos_los_argumentos(*args, **kwargs): + print args + print kwargs +""" +todos_los_argumentos(1, 2, a=3, b=4) imprime: + (1, 2) + {"a": 3, "b": 4} +""" + +# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs! +# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4) +todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4) +todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4) + +# Python tiene funciones de primera clase +def crear_suma(x): + def suma(y): + return x + y + return suma + +sumar_10 = crear_suma(10) +sumar_10(3) #=> 13 + +# También hay funciones anónimas +(lambda x: x > 2)(3) #=> True + +# Hay funciones integradas de orden superior +map(sumar_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# Podemos usar listas por comprensión para mapeos y filtros agradables +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. Clases +#################################################### + +# Heredamos de object para obtener una clase. +class Humano(object): + + # Un atributo de clase es compartido por todas las instancias de esta clase + especie = "H. sapiens" + + # Constructor basico + def __init__(self, nombre): + # Asigna el argumento al atributo nombre de la instancia + self.nombre = nombre + + # Un metodo de instancia. Todos los metodos toman self como primer argumento + def decir(self, msg): + return "%s: %s" % (self.nombre, msg) + + # Un metodo de clase es compartido a través de todas las instancias + # Son llamados con la clase como primer argumento + @classmethod + def get_especie(cls): + return cls.especie + + # Un metodo estatico es llamado sin la clase o instancia como referencia + @staticmethod + def roncar(): + return "*roncar*" + + +# Instancia una clase +i = Humano(nombre="Ian") +print i.decir("hi") # imprime "Ian: hi" + +j = Humano("Joel") +print j.decir("hello") #imprime "Joel: hello" + +# Llama nuestro método de clase +i.get_especie() #=> "H. sapiens" + +# Cambia los atributos compartidos +Humano.especie = "H. neanderthalensis" +i.get_especie() #=> "H. neanderthalensis" +j.get_especie() #=> "H. neanderthalensis" + +# Llama al método estático +Humano.roncar() #=> "*roncar*" + + +#################################################### +## 6. Módulos +#################################################### + +# Puedes importar módulos +import math +print math.sqrt(16) #=> 4 + +# Puedes obtener funciones específicas desde un módulo +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Puedes importar todas las funciones de un módulo +# Precaución: Esto no es recomendable +from math import * + +# Puedes acortar los nombres de los módulos +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Los módulos de Python son sólo archivos ordinarios de Python. +# Puedes escribir tus propios módulos e importarlos. El nombre del módulo +# es el mismo del nombre del archivo. + +# Puedes encontrar que funciones y atributos definen un módulo. +import math +dir(math) + + +``` + +## ¿Listo para más? + +### Gratis y en línea + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Encuadernados + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/es-es/ruby-es.html.markdown b/es-es/ruby-es.html.markdown new file mode 100644 index 00000000..66a5d0fe --- /dev/null +++ b/es-es/ruby-es.html.markdown @@ -0,0 +1,377 @@ +--- +language: ruby +filename: learnruby-es.rb +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] +translators: + - ["Camilo Garrido", "http://www.twitter.com/hirohope"] +lang: es-es +--- + +```ruby +# Esto es un comentario + +=begin +Este es un comentario multilínea +Nadie los usa. +Tu tampoco deberías +=end + +# Lo primero y principal: Todo es un objeto + +# Los números son objetos + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# Un poco de aritmética básica +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# La aritmética es sólo azúcar sintáctico +# para llamar un método de un objeto +1.+(3) #=> 4 +10.* 5 #=> 50 + +# Los valores especiales son objetos +nil # Nada que ver aqui +true # Verdadero +false # Falso + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# Igualdad +1 == 1 #=> true +2 == 1 #=> false + +# Desigualdad +1 != 1 #=> false +2 != 1 #=> true +!true #=> false +!false #=> true + +# Además de 'false', 'nil' es otro valor falso + +!nil #=> true +!false #=> true +!0 #=> false + +# Más comparaciones +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# Los strings son objetos + +'Soy un string'.class #=> String +"Soy un string también".class #=> String + +referente = "usar interpolacion de strings" +"Yo puedo #{referente} usando strings de comillas dobles" +#=> "Yo puedo usar interpolacion de strings usando strings de comillas dobles" + + +# Imprime a la salida estándar +puts "¡Estoy imprimiendo!" + +# Variables +x = 25 #=> 25 +x #=> 25 + +# Nota que la asignación retorna el valor asignado +# Esto significa que puedes hacer múltiples asignaciones: + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# Por convención, usa snake_case para nombres de variables +snake_case = true + +# Usa nombres de variables descriptivos +ruta_para_la_raiz_de_un_projecto = '/buen/nombre/' +ruta = '/mal/nombre/' + +# Los símbolos (son objetos) +# Los símbolos son inmutables, constantes reusables representadas internamente por un +# valor entero. Son usalmente usados en vez de strings para expresar eficientemente +# valores específicos y significativos + +:pendiente.class #=> Symbol + +status = :pendiente + +status == :pendiente #=> true + +status == 'pendiente' #=> false + +status == :aprovado #=> false + +# Arreglos + +# Esto es un arreglo +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# Arreglos pueden contener elementos de distintos tipos + +arreglo = [1, "hola", false] #=> => [1, "hola", false] + +# Arreglos pueden ser indexados +# Desde el frente +arreglo[0] #=> 1 +arreglo[12] #=> nil + +# Tal como la aritmética, el acceso como variable[índice] +# es sólo azúcar sintáctica +# para llamar el método [] de un objeto +arreglo.[] 0 #=> 1 +arreglo.[] 12 #=> nil + +# Desde el final +arreglo[-1] #=> 5 + +# Con un índice de inicio y final +arreglo[2, 4] #=> [3, 4, 5] + +# O con rango +arreglo[1..3] #=> [2, 3, 4] + +# Añade elementos a un arreglo así +arreglo << 6 #=> [1, 2, 3, 4, 5, 6] + +# Hashes son los diccionarios principales de Ruby con pares llave/valor. +# Hashes se denotan con llaves: +hash = {'color' => 'verde', 'numero' => 5} + +hash.keys #=> ['color', 'numero'] + +# Hashes pueden buscar rápidamente una llave: +hash['color'] #=> 'verde' +hash['numero'] #=> 5 + +# Preguntarle a un hash por una llave que no existe retorna 'nil': +hash['nada aqui'] #=> nil + +# Itera sobre un hash con el método 'each': +hash.each do |k, v| + puts "#{k} is #{v}" +end + +# Desde Ruby 1.9, hay una sintaxis especial cuando se usa un símbolo como llave: + +nuevo_hash = { defcon: 3, accion: true} + +nuevo_hash.keys #=> [:defcon, :accion] + +# Tip: Tanto los arreglos como los hashes son Enumerable (enumerables) +# Comparten muchos métodos útiles tales como 'each', 'map', 'count', y más + +# Estructuras de Control + +if true + "declaracion 'if'" +elsif false + "else if, opcional" +else + "else, tambien opcional" +end + +for contador in 1..5 + puts "iteracion #{contador}" +end +#=> iteracion 1 +#=> iteracion 2 +#=> iteracion 3 +#=> iteracion 4 +#=> iteracion 5 + +# Aunque +# Nadie usa los ciclos `for` +# Usa `each`, así: + +(1..5).each do |contador| + puts "iteracion #{contador}" +end +#=> iteracion 1 +#=> iteracion 2 +#=> iteracion 3 +#=> iteracion 4 +#=> iteracion 5 + +counter = 1 +while counter <= 5 do + puts "iteracion #{counter}" + counter += 1 +end +#=> iteracion 1 +#=> iteracion 2 +#=> iteracion 3 +#=> iteracion 4 +#=> iteracion 5 + +nota = 'B' + +case nota +when 'A' + puts "Muy bien muchacho" +when 'B' + puts "Mejor suerte para la proxima" +when 'C' + puts "Puedes hacerlo mejor" +when 'D' + puts "Sobreviviendo" +when 'F' + puts "¡Reprobaste!" +else + puts "Sistema alternativo de notas, ¿eh?" +end + +# Funciones + +def doble(x) + x * 2 +end + +# Funciones (y todos los bloques) implícitamente retornan el valor de la última instrucción +doble(2) #=> 4 + +# Paréntesis son opcionales cuando el resultado es ambiguo +doble 3 #=> 6 + +doble doble 3 #=> 12 + +def suma(x,y) + x + y +end + +# Arguméntos del método son separados por coma +suma 3, 4 #=> 7 + +suma suma(3,4), 5 #=> 12 + +# yield +# Todos los métodos tienen un parámetro de bloqueo opcional e implícitp +# puede llamarse con la palabra clave 'yield' + +def alrededor + puts "{" + yield + puts "}" +end + +alrededor { puts 'hola mundo' } + +# { +# hola mundo +# } + + +# Define una clase con la palabra clave 'class' +class Humano + + # Una variable de clase. Es compartida por todas las instancias de la clase. + @@species = "H. sapiens" + + # Inicializador Básico + def initialize(nombre, edad=0) + # Asigna el argumento a la variable de instancia 'nombre' + @nombre = nombre + # Si no dan edad, se usará el valor por defecto en la lista de argumentos. + @edad = edad + end + + # Método 'setter' (establecer) básico + def nombre=(nombre) + @nombre = nombre + end + + # Método 'getter' (obtener) básico + def nombre + @nombre + end + + # Un método de clase usa 'self' (sí mismo) para distinguirse de métodos de instancia. + # Sólo puede ser llamado en la clase, no por una instancia. + def self.decir(mensaje) + puts "#{mensaje}" + end + + def especie + @@especie + end + +end + + +# Instancia una clase +jim = Humano.new("Jim Halpert") + +dwight = Humano.new("Dwight K. Schrute") + +# Llamemos un par de métodos +jim.especie #=> "H. sapiens" +jim.nombre #=> "Jim Halpert" +jim.nombre = "Jim Halpert II" #=> "Jim Halpert II" +jim.nombre #=> "Jim Halpert II" +dwight.especie #=> "H. sapiens" +dwight.nombre #=> "Dwight K. Schrute" + +# Llama el método de clase +Humano.decir("Hi") #=> "Hi" + +# Las clases también son un objeto en ruby. Por lo cual, las clases también pueden tener variables de instancia. +# Variables de clase son compartidas a través de la clase y todos sus descendientes. + +# clase base +class Humano + @@foo = 0 + + def self.foo + @@foo + end + + def self.foo=(valor) + @@foo = valor + end +end + +# clase derivada +class Trabajador < Humano +end + +Humano.foo # 0 +Trabajador.foo # 0 + +Humano.foo = 2 # 2 +Trabajador.foo # 2 + +# Las variables de instancia de la clase no son compartidas por los descendientes de la clase. + +class Humano + @bar = 0 + + def self.bar + @bar + end + + def self.bar=(valor) + @bar = valor + end +end + +class Doctor < Humano +end + +Human.bar # 0 +Doctor.bar # nil + +``` diff --git a/fsharp.html.markdown b/fsharp.html.markdown index b1860372..49951c78 100644 --- a/fsharp.html.markdown +++ b/fsharp.html.markdown @@ -1,7 +1,7 @@ --- language: F# -author: Scott Wlaschin -author_url: http://fsharpforfunandprofit.com/ +contributors: + - ["Scott Wlaschin", "http://fsharpforfunandprofit.com/"] filename: learnfsharp.fs --- diff --git a/git.html.markdown b/git.html.markdown new file mode 100644 index 00000000..d8537300 --- /dev/null +++ b/git.html.markdown @@ -0,0 +1,393 @@ +--- +category: tool +tool: git +contributors: + - ["Jake Prather", "http:#github.com/JakeHP"] +filename: LearnGit.txt + +--- + +Git is a distributed version control and source code management system. + +It does this through a series of snapshots of your project, and it works +with those snapshots to provide you with functionality to version and +manage your source code. + +## Versioning Concepts + +### What is version control? + +Version control is a system that records changes to a file, or set of files, over time. + +### Centralized Versioning VS Distributed Versioning + +* Centralized version control focuses on synchronizing, tracking, and backing up files. +* Distributed version control focuses on sharing changes. Every change has a unique id. +* Distributed systems have no defined structure. You could easily have a SVN style, centralized system, with git. + +[Additional Information](http://git-scm.com/book/en/Getting-Started-About-Version-Control) + +### Why Use Git? + +* Can work offline. +* Collaborating with others is easy! +* Branching is easy! +* Merging is easy! +* Git is fast. +* Git is flexible. + +## Git Architecture + + +### Repository + +A set of files, directories, historical records, commits, and heads. Imagine it as a source code datastructure, +with the attribute that each source code "element" gives you access to its revision history, among other things. + +A git repository is comprised of the .git directory & working tree. + +### .git Directory (component of repository) + +The .git directory contains all the configurations, logs, branches, HEAD, and more. +[Detailed List.](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### Working Tree (component of repository) + +This is basically the directories and files in your repository. It is often referred to +as your working directory. + +### Index (component of .git dir) + +The Index is the staging area in git. It's basically a layer that separates your working tree +from the Git repository. This gives developers more power over what gets sent to the Git +repository. + +### Commit + +A git commit is a snapshot of a set of changes, or manipulations to your Working Tree. +For example, if you added 5 files, and removed 2 others, these changes will be contained +in a commit (or snapshot). This commit can then be pushed to other repositories, or not! + +### Branch + +A branch is essentially a pointer that points to the last commit you made. As you commit, +this pointer will automatically update and point to the latest commit. + +### HEAD and head (component of .git dir) + +HEAD is a pointer that points to the current branch. A repository only has 1 *active* HEAD. +head is a pointer that points to any commit. A repository can have any number of heads. + +### Conceptual Resources + +* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/) +* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html) + + +## Commands + + +### init + +Create an empty Git repository. The Git repository's settings, stored information, +and more is stored in a directory (a folder) named ".git". + +```bash +$ git init +``` + +### config + +To configure settings. Whether it be for the repository, the system itself, or global +configurations. + + +```bash +# Print & Set Some Basic Config Variables (Global) +$ git config --global user.email +$ git config --global user.name + +$ git config --global user.email "MyEmail@Zoho.com" +$ git config --global user.name "My Name" +``` + +[Learn More About git config.](http://git-scm.com/docs/git-config) + +### help + +To give you quick access to an extremely detailed guide of each command. Or to +just give you a quick reminder of some semantics. + +```bash +# Quickly check available commands +$ git help + +# Check all available commands +$ git help -a + +# Command specific help - user manual +# git help <command_here> +$ git help add +$ git help commit +$ git help init +``` + +### status + +To show differences between the index file (basically your working copy/repo) and the current +HEAD commit. + + +```bash +# Will display the branch, untracked files, changes and other differences +$ git status + +# To learn other "tid bits" about git status +$ git help status +``` + +### add + +To add files to the current working tree/directory/repo. If you do not `git add` new files to the +working tree/directory, they will not be included in commits! + +```bash +# add a file in your current working directory +$ git add HelloWorld.java + +# add a file in a nested dir +$ git add /path/to/file/HelloWorld.c + +# Regular Expression support! +$ git add ./*.java +``` + +### branch + +Manage your branches. You can view, edit, create, delete branches using this command. + +```bash +# list existing branches & remotes +$ git branch -a + +# create a new branch +$ git branch myNewBranch + +# delete a branch +$ git branch -d myBranch + +# rename a branch +# git branch -m <oldname> <newname> +$ git branch -m myBranchName myNewBranchName + +# edit a branch's description +$ git branch myBranchName --edit-description +``` + +### checkout + +Updates all files in the working tree to match the version in the index, or specified tree. + +```bash +# Checkout a repo - defaults to master branch +$ git checkout +# Checkout a specified branch +$ git checkout branchName +# Create a new branch & switch to it, like: "git branch <name>; git checkout <name>" +$ git checkout -b newBranch +``` + +### clone + +Clones, or copies, an existing repository into a new directory. It also adds +remote-tracking branches for each branch in the cloned repo, which allows you to push +to a remote branch. + +```bash +# Clone learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git +``` + +### commit + +Stores the current contents of the index in a new "commit." This commit contains +the changes made and a message created by the user. + +```bash +# commit with a message +$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" +``` + +### diff + +Shows differences between a file in the working directory, index and commits. + +```bash +# Show difference between your working dir and the index +$ git diff + +# Show differences between the index and the most recent commit. +$ git diff --cached + +# Show differences between your working dir and the most recent commit +$ git diff HEAD +``` + +### grep + +Allows you to quickly search a repository. + +Optional Configurations: + +```bash +# Thanks to Travis Jeffery for these +# Set line numbers to be shown in grep search results +$ git config --global grep.lineNumber true + +# Make search results more readable, including grouping +$ git config --global alias.g "grep --break --heading --line-number" +``` + +```bash +# Search for "variableName" in all java files +$ git grep 'variableName' -- '*.java' + +# Search for a line that contains "arrayListName" and, "add" or "remove" +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +Google is your friend; for more examples +[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) + +### log + +Display commits to the repository. + +```bash +# Show all commits +$ git log + +# Show X number of commits +$ git log -n 10 + +# Show merge commits only +$ git log --merges +``` + +### merge + +"Merge" in changes from external commits into the current branch. + +```bash +# Merge the specified branch into the current. +$ git merge branchName + +# Always generate a merge commit when merging +$ git merge --no-ff branchName +``` + +### mv + +Rename or move a file + +```bash +# Renaming a file +$ git mv HelloWorld.c HelloNewWorld.c + +# Moving a file +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# Force rename or move +# "existingFile" already exists in the directory, will be overwritten +$ git mv -f myFile existingFile +``` + +### pull + +Pulls from a repository and merges it with another branch. + +```bash +# Update your local repo, by merging in new changes +# from the remote "origin" and "master" branch. +# git pull <remote> <branch> +# git pull => implicitly defaults to => git pull origin master +$ git pull origin master + +# Merge in changes from remote branch and rebase +# branch commits onto your local repo, like: "git pull <remote> <branch>, git rebase <branch>" +$ git pull origin master --rebase +``` + +### push + +Push and merge changes from a branch to a remote & branch. + +```bash +# Push and merge changes from a local repo to a +# remote named "origin" and "master" branch. +# git push <remote> <branch> +# git push => implicitly defaults to => git push origin master +$ git push origin master +``` + +### rebase (caution) + +Take all changes that were committed on one branch, and replay them onto another branch. +*Do not rebase commits that you have pushed to a public repo*. + +```bash +# Rebase experimentBranch onto master +# git rebase <basebranch> <topicbranch> +$ git rebase master experimentBranch +``` + +[Additional Reading.](http://git-scm.com/book/en/Git-Branching-Rebasing) + +### reset (caution) + +Reset the current HEAD to the specified state. This allows you to undo merges, +pulls, commits, adds, and more. It's a great command but also dangerous if you don't +know what you are doing. + +```bash +# Reset the staging area, to match the latest commit (leaves dir unchanged) +$ git reset + +# Reset the staging area, to match the latest commit, and overwrite working dir +$ git reset --hard + +# Moves the current branch tip to the specified commit (leaves dir unchanged) +# all changes still exist in the directory. +$ git reset 31f2bb1 + +# Moves the current branch tip backward to the specified commit +# and makes the working dir match (deletes uncommited changes and all commits +# after the specified commit). +$ git reset --hard 31f2bb1 +``` + +### rm + +The opposite of git add, git rm removes files from the current working tree. + +```bash +# remove HelloWorld.c +$ git rm HelloWorld.c + +# Remove a file from a nested dir +$ git rm /pather/to/the/file/HelloWorld.c +``` + +## Further Information + +* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1) + +* [git-scm - Video Tutorials](http://git-scm.com/videos) + +* [git-scm - Documentation](http://git-scm.com/docs) + +* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/) + +* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) + +* [GitGuys](http://www.gitguys.com/) diff --git a/haskell.html.markdown b/haskell.html.markdown index 840569fb..9847ef2a 100644 --- a/haskell.html.markdown +++ b/haskell.html.markdown @@ -1,7 +1,7 @@ --- language: haskell -author: Adit Bhargava -author_url: http://adit.io +contributors: + - ["Adit Bhargava", "http://adit.io"] --- Haskell was designed as a practical, purely functional programming language. It's famous for @@ -11,7 +11,7 @@ makes coding a real joy for me. ```haskell -- Single line comments start with two dashes. {- Multiline comments can be enclosed -in a block like this. +en a block like this. -} ---------------------------------------------------- @@ -131,7 +131,7 @@ add 1 2 -- 3 -- with backticks: 1 `add` 2 -- 3 --- You can also define functions that have no characters! This lets +-- You can also define functions that have no letters! This lets -- you define your own operators! Here's an operator that does -- integer division (//) a b = a `div` b @@ -269,7 +269,7 @@ foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 -- This is now the same as -(2 * 3 + (2 * 2 + (2 * 1 + 4) +(2 * 3 + (2 * 2 + (2 * 1 + 4))) ---------------------------------------------------- -- 7. Data Types @@ -281,19 +281,20 @@ data Color = Red | Blue | Green -- Now you can use it in a function: -say :: Color -> IO String -say Red = putStrLn "You are Red!" -say Blue = putStrLn "You are Blue!" -say Green = putStrLn "You are Green!" + +say :: Color -> String +say Red = "You are Red!" +say Blue = "You are Blue!" +say Green = "You are Green!" -- Your data types can have parameters too: data Maybe a = Nothing | Just a -- These are all of type Maybe -Nothing -Just "hello" -Just 1 +Just "hello" -- of type `Maybe String` +Just 1 -- of type `Maybe Int` +Nothing -- of type `Maybe a` for any `a` ---------------------------------------------------- -- 8. Haskell IO @@ -302,32 +303,78 @@ Just 1 -- While IO can't be explained fully without explaining monads, -- it is not hard to explain enough to get going. --- An `IO a` value is an IO action: you can chain them with do blocks +-- When a Haskell program is executed, the function `main` is +-- called. It must return a value of type `IO ()`. For example: + +main :: IO () +main = putStrLn $ "Hello, sky! " ++ (say Blue) +-- putStrLn has type String -> IO () + +-- It is easiest to do IO if you can implement your program as +-- a function from String to String. The function +-- interact :: (String -> String) -> IO () +-- inputs some text, runs a function on it, and prints out the +-- output. + +countLines :: String -> String +countLines = show . length . lines + +main' = interact countLines + +-- You can think of a value of type `IO ()` as representing a +-- sequence of actions for the computer to do, much like a +-- computer program written in an imperative language. We can use +-- the `do` notation to chain actions together. For example: + +sayHello :: IO () +sayHello = do + putStrLn "What is your name?" + name <- getLine -- this gets a line and gives it the name "input" + putStrLn $ "Hello, " ++ name + +-- Exercise: write your own version of `interact` that only reads +-- one line of input. + +-- The code in `sayHello` will never be executed, however. The only +-- action that ever gets executed is the value of `main`. +-- To run `sayHello` comment out the above definition of `main` +-- and replace it with: +-- main = sayHello + +-- Let's understand better how the function `getLine` we just +-- used works. Its type is: +-- getLine :: IO String +-- You can think of a value of type `IO a` as representing a +-- computer program that will generate a value of type `a` +-- when executed (in addition to anything else it does). We can +-- store and reuse this value using `<-`. We can also +-- make our own action of type `IO String`: + action :: IO String action = do putStrLn "This is a line. Duh" - input <- getLine -- this gets a line and gives it the name "input" + input1 <- getLine input2 <- getLine - return (input1 ++ "\n" ++ input2) -- This is the result of the whole action + -- The type of the `do` statement is that of its last line. + -- `return` is not a keyword, but merely a function + return (input1 ++ "\n" ++ input2) -- return :: String -> IO String --- This didn't actually do anything. When a haskell program is executed --- an IO action called "main" is read and interpreted. +-- We can use this just like we used `getLine`: -main = do - putStrLn "Our first program. How exciting!" - result <- action -- our defined action is just like the default ones +main'' = do + putStrLn "I will echo two lines!" + result <- action putStrLn result putStrLn "This was all, folks!" --- Haskell does IO through a monad because this allows it to be a purely --- functional language. Our `action` function had a type signature of `IO String`. --- In general any function that interacts with the outside world (i.e. does IO) --- gets marked as `IO` in its type signature. This lets us reason about what --- functions are "pure" (don't interact with the outside world or modify state) --- and what functions aren't. +-- The type `IO` is an example of a "monad". The way Haskell uses a monad to +-- do IO allows it to be a purely functional language. Any function that +-- interacts with the outside world (i.e. does IO) gets marked as `IO` in its +-- type signature. This lets us reason about what functions are "pure" (don't +-- interact with the outside world or modify state) and what functions aren't. --- This is a powerful feature, because it's easy to run pure functions concurrently --- so concurrency in Haskell is very easy. +-- This is a powerful feature, because it's easy to run pure functions +-- concurrently; so, concurrency in Haskell is very easy. ---------------------------------------------------- @@ -344,6 +391,14 @@ let foo = 5 >:t foo foo :: Integer + +-- You can also run any action of type `IO ()` + +> sayHello +What is your name? +Friend! +Hello, Friend! + ``` There's a lot more to Haskell, including typeclasses and monads. These are the big ideas that make Haskell such fun to code in. I'll leave you with one final Haskell example: an implementation of quicksort in Haskell: @@ -357,5 +412,6 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater Haskell is easy to install. Get it [here](http://www.haskell.org/platform/). -You can find a much gentler introduction from the excellent [Learn you a Haskell](http://learnyouahaskell.com/) - +You can find a much gentler introduction from the excellent +[Learn you a Haskell](http://learnyouahaskell.com/) or +[Real World Haskell](http://book.realworldhaskell.org/). diff --git a/java.html.markdown b/java.html.markdown index 8ba48d73..b4531635 100644 --- a/java.html.markdown +++ b/java.html.markdown @@ -1,11 +1,8 @@ --- language: java - -author: Jake Prather - -author_url: http://github.com/JakeHP - +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] filename: LearnJava.java --- @@ -18,6 +15,10 @@ Java is a general-purpose, concurrent, class-based, object-oriented computer pro /* Multi-line comments look like this. */ +/** +JavaDoc comments look like this. Used to describe the Class or various +attributes of a Class. +*/ // Import ArrayList class inside of the java.util package import java.util.ArrayList; @@ -62,11 +63,15 @@ public class LearnJava { // Long - 64-bit signed two's complement integer // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) long fooLong = 100000L; + // L is used to denote that this variable value is of type Long; + // anything without is treated as integer by default. - // (Java has no unsigned types) + // Note: Java has no unsigned types // Float - Single-precision 32-bit IEEE 754 Floating Point float fooFloat = 234.5f; + // f is used to denote that this variable value is of type float; + // otherwise it is treated as double. // Double - Double-precision 64-bit IEEE 754 Floating Point double fooDouble = 123.4; @@ -86,8 +91,11 @@ public class LearnJava { // \n is an escaped character that starts a new line String barString = "Printing on a new line?\nNo Problem!"; + // \t is an escaped character that adds a tab character + String bazString = "Do you want to add a tab?\tNo Problem!"; System.out.println(fooString); System.out.println(barString); + System.out.println(bazString); // Arrays //The array size must be decided upon declaration @@ -131,12 +139,12 @@ public class LearnJava { System.out.println("11%3 = "+(11 % 3)); // => 2 // Comparison operators - System.out.println("3 == 2? " + (3 == 2)); // => 0 (false) - System.out.println("3 != 2? " + (3 != 2)); // => 1 (true) - System.out.println("3 > 2? " + (3 > 2)); // => 1 - System.out.println("3 < 2? " + (3 < 2)); // => 0 - System.out.println("2 <= 2? " + (2 <= 2)); // => 1 - System.out.println("2 >= 2? " + (2 >= 2)); // => 1 + System.out.println("3 == 2? " + (3 == 2)); // => false + System.out.println("3 != 2? " + (3 != 2)); // => true + System.out.println("3 > 2? " + (3 > 2)); // => true + System.out.println("3 < 2? " + (3 < 2)); // => false + System.out.println("2 <= 2? " + (2 <= 2)); // => true + System.out.println("2 >= 2? " + (2 >= 2)); // => true // Bitwise operators! /* @@ -150,7 +158,7 @@ public class LearnJava { */ // Incrementations - int i=0; + int i = 0; System.out.println("\n->Inc/Dec-rementation"); System.out.println(i++); //i = 1. Post-Incrementation System.out.println(++i); //i = 2. Pre-Incrementation @@ -163,12 +171,13 @@ public class LearnJava { System.out.println("\n->Control Structures"); // If statements are c-like - if (false){ - System.out.println("I never run"); - }else if (false) { - System.out.println("I am also never run"); + int j = 10; + if (j == 10){ + System.out.println("I get printed"); + } else if (j > 10) { + System.out.println("I don't"); } else { - System.out.println("I print"); + System.out.println("I also don't"); } // While loop @@ -203,16 +212,24 @@ public class LearnJava { System.out.println("fooFor Value: " + fooFor); // Switch Case + // A switch works with the byte, short, char, and int data types. + // It also works with enumerated types (discussed in Enum Types), + // the String class, and a few special classes that wrap + // primitive types: Character, Byte, Short, and Integer. int month = 3; String monthString; switch (month){ - case 1: monthString = "January"; + case 1: + monthString = "January"; break; - case 2: monthString = "February"; + case 2: + monthString = "February"; break; - case 3: monthString = "March"; + case 3: + monthString = "March"; break; - default: monthString = "Some other month"; + default: + monthString = "Some other month"; break; } System.out.println("Switch Case Result: " + monthString); @@ -254,10 +271,10 @@ public class LearnJava { Bicycle trek = new Bicycle(); // Call object methods - trek.speedUp(3); + trek.speedUp(3); // You should always use setter and getter methods trek.setCadence(100); - // toString is a convention + // toString is a convention to display the value of this Object. System.out.println("trek info: " + trek.toString()); } // End main method @@ -269,15 +286,17 @@ public class LearnJava { // Class Declaration Syntax: // <public/private/protected> class <class name>{ -// //data fields, constructors, functions all inside +// //data fields, constructors, functions all inside. +// //functions are called as methods in Java. // } class Bicycle { // Bicycle's Fields/Variables public int cadence; // Public: Can be accessed from anywhere - private int speed; // Private: Only accessable from within the class + private int speed; // Private: Only accessible from within the class protected int gear; // Protected: Accessible from the class and subclasses + String name; // default: Only accessible from within this package // Constructors are a way of creating classes // This is a default constructor @@ -285,13 +304,15 @@ class Bicycle { gear = 1; cadence = 50; speed = 5; + name = "Bontrager"; } // This is a specified constructor (it contains arguments) - public Bicycle(int startCadence, int startSpeed, int startGear) { - gear = startGear; - cadence = startCadence; - speed = startSpeed; + public Bicycle(int startCadence, int startSpeed, int startGear, String name) { + this.gear = startGear; + this.cadence = startCadence; + this.speed = startSpeed; + this.name = name; } // Function Syntax: @@ -322,10 +343,21 @@ class Bicycle { speed -= decrement; } + public void setName(String newName) { + name = newName; + } + + public String getName() { + return name; + } + + //Method to display the attribute values of this Object. + @Override public String toString() { - return "gear: "+Integer.toString(gear)+ - " cadence: "+Integer.toString(cadence)+ - " speed: "+Integer.toString(speed); + return "gear: " + gear + + " cadence: " + cadence + + " speed: " + speed + + " name: " + name; } } // end class Bicycle @@ -336,10 +368,12 @@ class PennyFarthing extends Bicycle { public PennyFarthing(int startCadence, int startSpeed){ // Call the parent constructor with super - super(startCadence, startSpeed, 0); + super(startCadence, startSpeed, 0, "PennyFarthing"); } // You should mark a method you're overriding with an @annotation + // To learn more about what annotations are and their purpose + // check this out: http://docs.oracle.com/javase/tutorial/java/annotations/ @Override public void setGear(int gear) { gear = 0; @@ -351,13 +385,18 @@ class PennyFarthing extends Bicycle { ## Further Reading +The links provided here below are just to get an understanding of the topic, feel free to Google and find specific examples. + Other Topics To Research: -* [Inheritance](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) +* [Java Tutorial Trail from Sun / Oracle](http://docs.oracle.com/javase/tutorial/index.html) -* [Polymorphism](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) +* [Java Access level modifiers](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) -* [Abstraction](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) +* [Object-Oriented Programming Concepts](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): + * [Inheritance](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) + * [Polymorphism](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) + * [Abstraction](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) * [Exceptions](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) @@ -366,5 +405,3 @@ Other Topics To Research: * [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html) * [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html) - -* The links provided are just to get an understanding of the topic, feel free to google and find specific examples diff --git a/javascript.html.markdown b/javascript.html.markdown new file mode 100644 index 00000000..cc279b9a --- /dev/null +++ b/javascript.html.markdown @@ -0,0 +1,436 @@ +--- +language: javascript +author: Adam Brenecki +author_url: http://adam.brenecki.id.au +--- + +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 +Java in web frontends. + +JavaScript isn't just limited to web browsers, though: Node.js, a project that +provides a standalone runtime for Google Chrome's V8 JavaScript engine, is +becoming more and more popular. + +Feedback would be highly appreciated! You can reach me at +[@adambrenecki](https://twitter.com/adambrenecki), or +[adam@brenecki.id.au](mailto:adam@brenecki.id.au). + +```js +// Comments are like C. Single-line comments start with two slashes, +/* and multiline comments start with slash-star + and end with star-slash */ + +// Statements can be terminated by ; +doStuff(); + +// ... but they don't have to be, as semicolons are automatically inserted +// wherever there's a newline, except in certain cases. +doStuff() + +// We'll leave semicolons off here; whether you do or not will depend on your +// personal preference or your project's style guide. + +/////////////////////////////////// +// 1. Numbers, Strings and Operators + +// Javascript has one number type (which is a 64-bit IEEE 754 double). +3 // = 3 +1.5 // = 1.5 + +// All the basic arithmetic works as you'd expect. +1 + 1 // = 2 +8 - 1 // = 7 +10 * 2 // = 20 +35 / 5 // = 7 + +// Including uneven division. +5 / 2 // = 2.5 + +// Bitwise operations also work; when you perform a bitwise operation your float +// is converted to a signed int *up to* 32 bits. +1 << 2 // = 4 + +// Precedence is enforced with parentheses. +(1 + 3) * 2 // = 8 + +// There are three special not-a-real-number values: +Infinity // result of e.g. 1/0 +-Infinity // result of e.g. -1/0 +NaN // result of e.g. 0/0 + +// There's also a boolean type. +true +false + +// Strings are created with ' or ". +'abc' +"Hello, world" + +// Negation uses the ! symbol +!true // = false +!false // = true + +// Equality is == +1 == 1 // = true +2 == 1 // = false + +// Inequality is != +1 != 1 // = false +2 != 1 // = true + +// More comparisons +1 < 10 // = true +1 > 10 // = false +2 <= 2 // = true +2 >= 2 // = true + +// Strings are concatenated with + +"Hello " + "world!" // = "Hello world!" + +// and are compared with < and > +"a" < "b" // = true + +// Type coercion is performed for comparisons... +"5" == 5 // = true + +// ...unless you use === +"5" === 5 // = false + +// You can access characters in a string with charAt +"This is a string".charAt(0) + +// There's also null and undefined +null // used to indicate a deliberate non-value +undefined // used to indicate a value that hasn't been set yet + +// null, undefined, NaN, 0 and "" are falsy, and everything else is truthy. +// Note that 0 is falsy and "0" is truthy, even though 0 == "0". + +/////////////////////////////////// +// 2. Variables, Arrays and Objects + +// 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 + +// if you leave the var keyword off, you won't get an error... +someOtherVar = 10 + +// ...but your variable will be created in the global scope, not in the scope +// you defined it in. + +// Variables declared without being assigned to are set to undefined. +var someThirdVar // = undefined + +// There's shorthand for performing math operations on variables: +someVar += 5 // equivalent to someVar = someVar + 5; someVar is 10 now +someVar *= 10 // now someVar is 100 + +// and an even-shorter-hand for adding or subtracting 1 +someVar++ // now someVar is 101 +someVar-- // back to 100 + +// Arrays are ordered lists of values, of any type. +var myArray = ["Hello", 45, true] + +// Their members can be accessed using the square-brackets subscript syntax. +// Array indices start at zero. +myArray[1] // = 45 + +// JavaScript's objects are equivalent to 'dictionaries' or 'maps' in other +// languages: an unordered collection of key-value pairs. +{key1: "Hello", key2: "World"} + +// Keys are strings, but quotes aren't required if they're a valid +// JavaScript identifier. Values can be any type. +var myObj = {myKey: "myValue", "my other key": 4} + +// Object attributes can also be accessed using the subscript syntax, +myObj["my other key"] // = 4 + +// ... or using the dot syntax, provided the key is a valid identifier. +myObj.myKey // = "myValue" + +// Objects are mutable; values can be changed and new keys added. +myObj.myThirdKey = true + +// If you try to access a value that's not yet set, you'll get undefined. +myObj.myFourthKey // = undefined + +/////////////////////////////////// +// 3. Logic and Control Structures + +// The if structure works as you'd expect. +var count = 1 +if (count == 3){ + // evaluated if count is 3 +} else if (count == 4) { + // evaluated if count is 4 +} else { + // evaluated if it's not either 3 or 4 +} + +// As does while. +while (true) { + // An infinite loop! +} + +// Do-while loops are like while loops, except they always run at least once. +var input +do { + input = getInput() +} while (!isValid(input)) + +// the for loop is the same as C and Java: +// initialisation; continue condition; iteration. +for (var i = 0; i < 5; i++){ + // will run 5 times +} + +// && is logical and, || is logical or +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear" +} +if (colour == "red" || colour == "blue"){ + // colour is either red or blue +} + +// && and || "short circuit", which is useful for setting default values. +var name = otherName || "default" + +/////////////////////////////////// +// 4. Functions, Scope and Closures + +// JavaScript functions are declared with the function keyword. +function myFunction(thing){ + return thing.toUpperCase() +} +myFunction("foo") // = "FOO" + +// Functions can also be defined "anonymously" - without a name: +function(thing){ + return thing.toLowerCase() +} +// (we can't call our function, since we don't have a name to refer to it with) + +// JavaScript functions are first class objects, so they can be reassigned to +// different variable names and passed to other functions as arguments - for +// example, when supplying an event handler: +function myFunction(){ + // this code will be called in 5 seconds' time +} +setTimeout(myFunction, 5000) + +// You can even write the function statement directly in the call to the other +// function. + +setTimeout(function myFunction(){ + // this code will be called in 5 seconds' time +}, 5000) + +// JavaScript has function scope; functions get their own scope but other blocks +// do not. +if (true){ + var i = 5 +} +i // = 5 - not undefined as you'd expect in a block-scoped language + +// This has led to a common pattern of "immediately-executing anonymous +// functions", which prevent temporary variables from leaking into the global +// scope. +(function(){ + var temporary = 5 + // We can access the global scope by assiging to the 'global object', which + // in a web browser is always 'window'. The global object may have a + // different name in non-browser environments such as Node.js. + window.permanent = 10 + // Or, as previously mentioned, we can just leave the var keyword off. + permanent2 = 15 +})() +temporary // raises ReferenceError +permanent // = 10 +permanent2 // = 15 + +// One of JavaScript's most powerful features is closures. If a function is +// defined inside another function, the inner function has access to all the +// outer function's variables. +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!" + function inner(){ + alert(prompt) + } + setTimeout(inner, 5000) + // setTimeout is asynchronous, so this function will finish without waiting + // 5 seconds. However, once the 5 seconds is up, inner will still have + // access to the value of prompt. +} +sayHelloInFiveSeconds("Adam") // will open a popup with "Hello, Adam!" in 5s + +/////////////////////////////////// +// 5. More about Objects; Constructors and Prototypes + +// Objects can contain functions. +var myObj = { + myFunc: function(){ + return "Hello world!" + } +} +myObj.myFunc() // = "Hello world!" + +// When functions attached to an object are called, they can access the object +// they're attached to using the this keyword. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString + } +} +myObj.myFunc() // = "Hello world!" + +// What this is set to has to do with how the function is called, not where +// it's defined. So, our function doesn't work if it isn't called in the +// context of the object. +var myFunc = myObj.myFunc +myFunc() // = undefined + +// Inversely, a function can be assigned to the object and gain access to it +// through this, even if it wasn't attached when it was defined. +var myOtherFunc = function(){ + return this.myString.toUpperCase() +} +myObj.myOtherFunc = myOtherFunc +myObj.myOtherFunc() // = "HELLO WORLD!" + +// When you call a function with the new keyword, a new object is created, and +// made available to the function via this. Functions designed to be called +// like this are called constructors. + +var MyConstructor = function(){ + this.myNumber = 5 +} +myNewObj = new MyConstructor() // = {myNumber: 5} +myNewObj.myNumber // = 5 + +// Every JavaScript object has a 'prototype'. When you go to access a property +// on an object that doesn't exist on the actual object, the interpreter will +// look at its prototype. + +// Some JS implementations let you access an object's prototype on the magic +// property __proto__. While this is useful for explaining prototypes it's not +// part of the standard; we'll get to standard ways of using prototypes later. +var myObj = { + myString: "Hello world!", +} +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase() + } +} +myObj.__proto__ = myPrototype +myObj.meaningOfLife // = 42 + +// This works for functions, too. +myObj.myFunc() // = "hello world!" + +// Of course, if your property isn't on your prototype, the prototype's +// prototype is searched, and so on. +myPrototype.__proto__ = { + myBoolean: true +} +myObj.myBoolean // = true + +// There's no copying involved here; each object stores a reference to its +// prototype. This means we can alter the prototype and our changes will be +// reflected everywhere. +myPrototype.meaningOfLife = 43 +myObj.meaningOfLife // = 43 + +// We mentioned that __proto__ was non-standard, and there's no standard way to +// change the prototype of an existing object. However, there's two ways to +// create a new object with a given prototype. + +// The first is Object.create, which is a recent addition to JS, and therefore +// not available in all implementations yet. +var myObj = Object.create(myPrototype) +myObj.meaningOfLife // = 43 + +// The second way, which works anywhere, has to do with constructors. +// Constructors have a property called prototype. This is *not* the prototype of +// the constructor function itself; instead, it's the prototype that new objects +// are given when they're created with that constructor and the new keyword. +myConstructor.prototype = { + getMyNumber: function(){ + return this.myNumber + } +} +var myNewObj2 = new myConstructor() +myNewObj2.getMyNumber() // = 5 + +// Built-in types like strings and numbers also have constructors that create +// equivalent wrapper objects. +var myNumber = 12 +var myNumberObj = new Number(12) +myNumber == myNumberObj // = true + +// Except, they aren't exactly equivalent. +typeof(myNumber) // = 'number' +typeof(myNumberObj) // = 'object' +myNumber === myNumberObj // = false +if (0){ + // This code won't execute, because 0 is falsy. +} +if (Number(0)){ + // This code *will* execute, because Number(0) is truthy. +} + +// However, the wrapper objects and the regular builtins share a prototype, so +// you can actually add functionality to a string, for instance. +String.prototype.firstCharacter = function(){ + return this.charAt(0) +} +"abc".firstCharacter() // = "a" + +// This fact is often used in "polyfilling", which is implementing newer +// features of JavaScript in an older subset of JavaScript, so that they can be +// used in older environments such as outdated browsers. + +// For instance, we mentioned that Object.create isn't yet available in all +// implementations, but we can still use it with this polyfill: +if (Object.create === undefined){ // don't overwrite it if it exists + Object.create = function(proto){ + // make a temporary constructor with the right prototype + var Constructor = function(){} + Constructor.prototype = proto + // then use it to create a new, appropriately-prototyped object + return new Constructor() + } +} +``` + +## Further Reading + +The [Mozilla Developer +Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript) provides +excellent documentation for JavaScript as it's used in browsers. Plus, it's a +wiki, so as you learn more you can help others out by sharing your own +knowledge. + +MDN's [A re-introduction to +JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) +covers much of the concepts covered here in more detail. This guide has quite +deliberately only covered the JavaScript language itself; if you want to learn +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 +guide of all the counter-intuitive parts of the language. + +In addition to direct contributors to this article, some content is adapted +from Louie Dinh's Python tutorial on this site, and the [JS +Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) +on the Mozilla Developer Network. diff --git a/julia.html.markdown b/julia.html.markdown index 6c719b5c..1023e303 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -1,7 +1,7 @@ --- language: julia -author: Leah Hanson -author_url: http://leahhanson.us +contributors: + - ["Leah Hanson", "http://leahhanson.us"] filename: learnjulia.jl --- diff --git a/livescript.html.markdown b/livescript.html.markdown new file mode 100644 index 00000000..8e11439b --- /dev/null +++ b/livescript.html.markdown @@ -0,0 +1,345 @@ +--- +language: LiveScript +filename: learnLivescript.ls +contributors: + - ["Christina Whyte", "http://github.com/kurisuwhyte/"] +--- + +LiveScript is a functional compile-to-JavaScript language which shares +most of the underlying semantics with its host language. Nice additions +comes with currying, function composition, pattern matching and lots of +other goodies heavily borrowed from languages like Haskell, F# and +Scala. + +LiveScript is a fork of [Coco][], which is itself a fork of +[CoffeeScript][]. The language is stable, and a new version is in active +development to bring a plethora of new niceties! + +[Coco]: http://satyr.github.io/coco/ +[CoffeeScript]: http://coffeescript.org/ + +Feedback is always welcome, so feel free to reach me over at +[@kurisuwhyte](https://twitter.com/kurisuwhyte) :) + + +```coffeescript +# Just like its CoffeeScript cousin, LiveScript uses hash symbols for +# single-line comments. + +/* + Multi-line comments are written C-style. Use them if you want comments + to be preserved in the JavaScript output. + */ +``` +```coffeescript +# As far as syntax goes, LiveScript uses indentation to delimit blocks, +# rather than curly braces, and whitespace to apply functions, rather +# than parenthesis. + + +######################################################################## +## 1. Basic values +######################################################################## + +# Lack of value is defined by the keyword `void` instead of `undefined` +void # same as `undefined` but safer (can't be overridden) + +# No valid value is represented by Null. +null + + +# The most basic actual value is the logical type: +true +false + +# And it has a plethora of aliases that mean the same thing: +on; off +yes; no + + +# Then you get numbers. These are double-precision floats like in JS. +10 +0.4 # Note that the leading `0` is required + +# For readability, you may use underscores and letter suffixes in a +# number, and these will be ignored by the compiler. +12_344km + + +# Strings are immutable sequences of characters, like in JS: +"Christina" # apostrophes are okay too! +"""Multi-line + strings + are + okay + too.""" + +# Sometimes you want to encode a keyword, the backslash notation makes +# this easy: +\keyword # => 'keyword' + + +# Arrays are ordered collections of values. +fruits = + * \apple + * \orange + * \pear + +# They can be expressed more concisely with square brackets: +fruits = [ \apple, \orange, \pear ] + +# You also get a convenient way to create a list of strings, using +# white space to delimit the items. +fruits = <[ apple orange pear ]> + +# You can retrieve an item by their 0-based index: +fruits[0] # => "apple" + +# Objects are a collection of unordered key/value pairs, and a few other +# things (more on that later). +person = + name: "Christina" + likes: + * "kittens" + * "and other cute stuff" + +# Again, you can express them concisely with curly brackets: +person = {name: "Christina", likes: ["kittens", "and other cute stuff"]} + +# You can retrieve an item by their key: +person.name # => "Christina" +person["name"] # => "Christina" + + +# Regular expressions use the same syntax as JavaScript: +trailing-space = /\s$/ # dashed-words become dashedWords + +# Except you can do multi-line expressions too! +# (comments and whitespace just gets ignored) +funRE = // + function\s+(.+) # name + \s* \((.*)\) \s* # arguments + { (.*) } # body + // + + +######################################################################## +## 2. Basic operations +######################################################################## + +# Arithmetic operators are the same as JavaScript's: +1 + 2 # => 3 +2 - 1 # => 1 +2 * 3 # => 6 +4 / 2 # => 2 +3 % 2 # => 1 + + +# Comparisons are mostly the same too, except that `==` and `===` are +# inverted. +2 == 2 # => true +2 == "2" # => false +2 === "2" # => true + +# Other relational operators include <, <=, > and >= + +# Logical values can be combined through the logical operators `or`, +# `and` and `not` +true and false # => false +false or true # => true +not false # => true + + +# Collections also get some nice additional operators +[1, 2] ++ [3, 4] # => [1, 2, 3, 4] +'a' in <[ a b c ]> # => true +'name' of { name: 'Chris' } # => true + + +######################################################################## +## 3. Functions +######################################################################## + +# Since LiveScript is functional, you'd expect functions to get a nice +# treatment. In LiveScript it's even more apparent that functions are +# first class: +add = (left, right) -> left + right +add 1, 2 # => 3 + +# Functions which take no arguments are called with a bang! +two = -> 2 +two! + +# LiveScript uses function scope, just like JavaScript, and has proper +# closures too. Unlike JavaScript, the `=` works as a declaration +# operator, and will always declare the variable on the left hand side. + +# The `:=` operator is available to *reuse* a name from the parent +# scope. + + +# You can destructure arguments of a function to quickly get to +# interesting values inside a complex data structure: +tail = ([head, ...rest]) -> rest +tail [1, 2, 3] # => [2, 3] + +# You can also transform the arguments using binary or unary +# operators. Default arguments are also possible. +foo = (a = 1, b = 2) -> a + b +foo! # => 3 + +# You could use it to clone a particular argument to avoid side-effects, +# for example: +copy = (^^target, source) -> + for k,v of source => target[k] = v + target +a = { a: 1 } +copy a, { b: 2 } # => { a: 1, b: 2 } +a # => { a: 1 } + + +# A function may be curried by using a long arrow rather than a short +# one: +add = (left, right) --> left + right +add1 = add 1 +add1 2 # => 3 + +# Functions get an implicit `it` argument, even if you don't declare +# any. +identity = -> it +identity 1 # => 1 + +# Operators are not functions in LiveScript, but you can easily turn +# them into one! Enter the operator sectioning: +divide-by-2 = (/ 2) +[2, 4, 8, 16].map(divide-by-2) .reduce (+) + + +# Not only of function application lives LiveScript, as in any good +# functional language you get facilities for composing them: +double-minus-one = (- 1) . (* 2) + +# Other than the usual `f . g` mathematical formulae, you get the `>>` +# and `<<` operators, that describe how the flow of values through the +# functions. +double-minus-one = (* 2) >> (- 1) +double-minus-one = (- 1) << (* 2) + + +# And talking about flow of value, LiveScript gets the `|>` and `<|` +# operators that apply a value to a function: +map = (f, xs) --> xs.map f +[1 2 3] |> map (* 2) # => [2 4 6] + +# You can also choose where you want the value to be placed, just mark +# the place with an underscore (_): +reduce = (f, xs, initial) --> xs.reduce f, initial +[1 2 3] |> reduce (+), _, 0 # => 6 + + +# The underscore is also used in regular partial application, which you +# can use for any function: +div = (left, right) -> left / right +div-by-2 = div _, 2 +div-by-2 4 # => 2 + + +# Last, but not least, LiveScript has back-calls, which might help +# with some callback-based code (though you should try more functional +# approaches, like Promises): +readFile = (name, f) -> f name +a <- readFile 'foo' +b <- readFile 'bar' +console.log a + b + +# Same as: +readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b + + +######################################################################## +## 4. Patterns, guards and control-flow +######################################################################## + +# You can branch computations with the `if...else` expression: +x = if n > 0 then \positive else \negative + +# Instead of `then`, you can use `=>` +x = if n > 0 => \positive + else \negative + +# Complex conditions are better-off expressed with the `switch` +# expression, though: +y = {} +x = switch + | (typeof y) is \number => \number + | (typeof y) is \string => \string + | 'length' of y => \array + | otherwise => \object # `otherwise` and `_` always matches. + +# Function bodies, declarations and assignments get a free `switch`, so +# you don't need to type it again: +take = (n, [x, ...xs]) --> + | n == 0 => [] + | _ => [x] ++ take (n - 1), xs + + +######################################################################## +## 5. Comprehensions +######################################################################## + +# While the functional helpers for dealing with lists and objects are +# right there in the JavaScript's standard library (and complemented on +# the prelude-ls, which is a "standard library" for LiveScript), +# comprehensions will usually allow you to do this stuff faster and with +# a nice syntax: +oneToTwenty = [1 to 20] +evens = [x for x in oneToTwenty when x % 2 == 0] + +# `when` and `unless` can be used as filters in the comprehension. + +# Object comprehension works in the same way, except that it gives you +# back an object rather than an Array: +copy = { [k, v] for k, v of source } + + +######################################################################## +## 4. OOP +######################################################################## + +# While LiveScript is a functional language in most aspects, it also has +# some niceties for imperative and object oriented programming. One of +# them is class syntax and some class sugar inherited from CoffeeScript: +class Animal + (@name, kind) -> + @kind = kind + action: (what) -> "*#{@name} (a #{@kind}) #{what}*" + +class Cat extends Animal + (@name) -> super @name, 'cat' + purr: -> @action 'purrs' + +kitten = new Cat 'Mei' +kitten.purr! # => "*Mei (a cat) purrs*" + +# Besides the classical single-inheritance pattern, you can also provide +# as many mixins as you would like for a class. Mixins are just plain +# objects: +Huggable = + hug: -> @action 'is hugged' + +class SnugglyCat extends Cat implements Huggable + +kitten = new SnugglyCat 'Purr' +kitten.hug! # => "*Mei (a cat) is hugged*" +``` + +## Further reading + +There's just so much more to LiveScript, but this should be enough to +get you started writing little functional things in it. The +[official website](http://livescript.net/) has a lot of information on the +language, and a nice online compiler for you to try stuff out! + +You may also want to grab yourself some +[prelude.ls](http://gkz.github.io/prelude-ls/), and check out the `#livescript` +channel on the Freenode network. diff --git a/lua.html.markdown b/lua.html.markdown index 4df57a92..7325a1cf 100644 --- a/lua.html.markdown +++ b/lua.html.markdown @@ -1,7 +1,7 @@ --- language: lua -author: Tyler Neylon -author_url: http://tylerneylon.com/ +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] filename: learnlua.lua --- @@ -87,7 +87,7 @@ until num == 0 ---------------------------------------------------- function fib(n) - if n < 2 then return 1 end + if n < 2 then return n end return fib(n - 2) + fib(n - 1) end diff --git a/php.html.markdown b/php.html.markdown index f0c5c918..ce228870 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -1,14 +1,15 @@ --- language: php -author: Malcolm Fell -author_url: http://emarref.net/ +contributors: + - ["Malcolm Fell", "http://emarref.net/"] + - ["Trismegiste", "https://github.com/Trismegiste"] filename: learnphp.php --- This document describes PHP 5+. ```php -<?php // PHP code must be enclosed with <?php ? > tags +<?php // PHP code must be enclosed with <?php tags // If your php file only contains PHP code, it is best practise // to omit the php closing tag. @@ -30,7 +31,8 @@ echo "World\n"; // Prints "World" with a line break // (all statements must end with a semicolon) // Anything outside <?php tags is echoed automatically -?>Hello World Again! +?> +Hello World Again! <?php @@ -47,9 +49,9 @@ $boolean = true; // or TRUE or True $boolean = false; // or FALSE or False // Integers -$int1 = 19; // => 19 -$int2 = -19; // => -19 -$int3 = 019; // => 15 (a leading 0 denotes an octal number) +$int1 = 12; // => 12 +$int2 = -12; // => -12 +$int3 = 012; // => 10 (a leading 0 denotes an octal number) $int4 = 0x0F; // => 15 (a leading 0x denotes a hex literal) // Floats (aka doubles) @@ -100,6 +102,21 @@ echo 'This string ' . 'is concatenated'; /******************************** + * Constants + */ + +// A constant is defined by using define() +// and can never be changed during runtime! + +// a valid constant name starts with a letter or underscore, +// followed by any number of letters, numbers, or underscores. +define("FOO", "something"); + +// access to a constant is possible by direct using the choosen name +echo 'This outputs '.FOO; + + +/******************************** * Arrays */ @@ -380,9 +397,6 @@ echo $function_name(1, 2); // => 3 * Includes */ -/* -``` -```php <?php // PHP within included files must also begin with a PHP open tag. @@ -526,6 +540,12 @@ interface InterfaceTwo public function doSomethingElse(); } +// interfaces can be extended +interface InterfaceThree extends InterfaceTwo +{ + public function doAnotherContract(); +} + abstract class MyAbstractClass implements InterfaceOne { public $x = 'doSomething'; @@ -590,9 +610,6 @@ $cls->myTraitMethod(); // Prints "I have MyTrait" // This section is separate, because a namespace declaration // must be the first statement in a file. Let's pretend that is not the case -/* -``` -```php <?php // By default, classes exist in the global namespace, and can diff --git a/pt-br/python-pt.html.markdown b/pt-br/python-pt.html.markdown new file mode 100644 index 00000000..e08bb5a8 --- /dev/null +++ b/pt-br/python-pt.html.markdown @@ -0,0 +1,509 @@ +--- +language: python +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Vilson Vieira", "http://automata.cc"] +lang: pt-bf +filename: learnpython-pt.py +--- + +Python foi criado por Guido Van Rossum no começo dos anos 90. Atualmente é uma +das linguagens de programação mais populares. Eu me apaixonei por Python, por +sua clareza de sintaxe. É basicamente pseudocódigo executável. + +Comentários serão muito apreciados! Você pode me contactar em +[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [arroba] +[serviço de email do google] + +Nota: Este artigo usa Python 2.7 especificamente, mas deveria ser aplicável a +qualquer Python 2.x. Logo haverá uma versão abordando Python 3! + +```python +# Comentários de uma linha começam com cerquilha (ou sustenido) +""" Strings de várias linhas podem ser escritas + usando três ", e são comumente usadas + como comentários +""" + +#################################################### +## 1. Tipos de dados primitivos e operadores +#################################################### + +# Você usa números normalmente +3 #=> 3 + +# Operadores matemáticos são aqueles que você já está acostumado +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# A divisão é um pouco estranha. A divisão de números inteiros arredonda +# para baixo o resultado, automaticamente +5 / 2 #=> 2 + +# Para concertar a divisão, precisamos aprender sobre números de ponto +# flutuante (conhecidos como 'float'). +2.0 # Isso é um 'float' +11.0 / 4.0 #=> 2.75 ahhh... muito melhor + +# Forçamos a precedência de operadores usando parênteses +(1 + 3) * 2 #=> 8 + +# Valores booleanos (ou 'boolean') são também tipos primitivos +True +False + +# Negamos usando 'not' +not True #=> False +not False #=> True + +# Testamos igualdade usando '==' +1 == 1 #=> True +2 == 1 #=> False + +# E desigualdade com '!=' +1 != 1 #=> False +2 != 1 #=> True + +# Mais comparações +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# As comparações podem ser encadeadas! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Strings são criadas com " ou ' +"Isso é uma string." +'Isso também é uma string.' + +# Strings podem ser somadas (ou melhor, concatenadas)! +"Olá " + "mundo!" #=> "Olá mundo!" + +# Uma string pode ser tratada como uma lista de caracteres +"Esta é uma string"[0] #=> 'E' + +# O caractere % pode ser usado para formatar strings, desta forma: +"%s podem ser %s" % ("strings", "interpoladas") + +# Um jeito novo de formatar strings é usando o método 'format'. +# Esse método é o jeito mais usado +"{0} podem ser {1}".format("strings", "formatadas") +# Você pode usar palavras-chave (ou 'keywords') se você não quiser contar. +"{nome} quer comer {comida}".format(nome="João", comida="lasanha") + +# 'None' é um objeto +None #=> None + +# Não use o operador de igualdade `==` para comparar objetos com 'None' +# Ao invés disso, use `is` +"etc" is None #=> False +None is None #=> True + +# O operador 'is' teste a identidade de um objeto. Isso não é +# muito útil quando estamos lidando com valores primitivos, mas é +# muito útil quando lidamos com objetos. + +# None, 0, e strings/listas vazias são todas interpretadas como 'False'. +# Todos os outros valores são 'True' +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Variáveis e Coleções +#################################################### + +# Imprimir na tela é muito fácil +print "Eu sou o Python. Prazer em te conhecer!" + + +# Nós não precisamos declarar variáveis antes de usá-las, basta usar! +alguma_variavel = 5 # A convenção é usar caixa_baixa_com_sobrescritos +alguma_variavel #=> 5 + +# Acessar uma variável que não teve nenhum valor atribuído anteriormente é +# uma exceção. +# Veja a seção 'Controle' para aprender mais sobre tratamento de exceção. +outra_variavel # Gera uma exceção de erro de nome + +# 'if' pode ser usado como uma expressão +"uepa!" if 3 > 2 else 2 #=> "uepa!" + +# Listas armazenam sequências de elementos +lista = [] +# Você pode inicializar uma lista com valores +outra_lista = [4, 5, 6] + +# Adicione elementos no final da lista usando 'append' +lista.append(1) # lista é agora [1] +lista.append(2) # lista é agora [1, 2] +lista.append(4) # lista é agora [1, 2, 4] +lista.append(3) # lista é agora [1, 2, 4, 3] +# Remova elementos do fim da lista usando 'pop' +lista.pop() #=> 3 e lista é agora [1, 2, 4] +# Vamos adicionar o elemento novamente +lista.append(3) # lista agora é [1, 2, 4, 3] novamente. + +# Acesse elementos de uma lista através de seu índices +lista[0] #=> 1 +# Acesse o último elemento com índice negativo! +lista[-1] #=> 3 + +# Tentar acessar um elemento fora dos limites da lista gera uma exceção +# do tipo 'IndexError' +lista[4] # Gera uma exceção 'IndexError' + +# Você pode acessar vários elementos ao mesmo tempo usando a sintaxe de +# limites +# (Para quem gosta de matemática, isso é um limite fechado/aberto) +lista[1:3] #=> [2, 4] +# Você pode omitir o fim se quiser os elementos até o final da lista +lista[2:] #=> [4, 3] +# O mesmo para o início +lista[:3] #=> [1, 2, 4] + +# Remova um elemento qualquer de uma lista usando 'del' +del lista[2] # lista agora é [1, 2, 3] + +# Você pode somar listas (obs: as listas originais não são modificadas) +lista + outra_lista #=> [1, 2, 3, 4, 5, 6] + +# Você também pode concatenar usando o método 'extend' (lista será modificada!) +lista.extend(outra_lista) # Agora lista é [1, 2, 3, 4, 5, 6] + +# Para checar se um elemento pertence a uma lista, use 'in' +1 in lista #=> True + +# Saiba quantos elementos uma lista possui com 'len' +len(lista) #=> 6 + + +# Tuplas são iguais a listas, mas são imutáveis +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # Isso gera uma exceção do tipo TypeError + +# Você pode fazer nas tuplas todas aquelas coisas fez com a lista +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# Você pode 'desempacotar' tuplas (ou listas) em variáveis, associando cada +# elemento da tupla/lista a uma variável correspondente +a, b, c = (1, 2, 3) # a agora é 1, b agora é 2, c agora é 3 +# Tuplas são criadas por padrão, mesmo se você não usar parênteses +d, e, f = 4, 5, 6 +# Sabendo disso, veja só como é fácil trocar os valores de duas variáveis! +e, d = d, e # d agora é 5, e agora é 4 + + +# Dicionários armazenam 'mapeamentos' (do tipo chave-valor) +dicionario_vazio = {} +# Aqui criamos um dicionário já contendo valores +dicionario = {"um": 1, "dois": 2, "três": 3} + +# Acesse valores usando [] +dicionario["um"] #=> 1 + +# Retorna uma lista com todas as chaves do dicionário +dicionario.keys() #=> ["três", "dois", "um"] +# Nota: A ordem das chaves não é garantida. +# O resultado no seu interpretador não necessariamente será igual a esse. + +# Retorna uma lista com todos os valores do dicionário +dicionario.values() #=> [3, 2, 1] +# Nota: A mesma nota acima sobre a ordenação é válida aqui. + +# Veja se uma chave qualquer está em um dicionário usando 'in' +"um" in dicionario #=> True +1 in dicionario #=> False + +# Tentar acessar uma chave que não existe gera uma exceção do tipo 'KeyError' +dicionario["quatro"] # Gera uma exceção KeyError + +# Você pode usar o método 'get' para evitar gerar a exceção 'KeyError'. +# Ao invés de gerar essa exceção, irá retornar 'None' se a chave não existir. +dicionario.get("um") #=> 1 +dicionario.get("quatro") #=> None +# O método 'get' suporta um argumento que diz qual valor deverá ser +# retornado se a chave não existir (ao invés de 'None'). +dicionario.get("um", 4) #=> 1 +dicionario.get("quatro", 4) #=> 4 + +# O método 'setdefault' é um jeito seguro de adicionar um novo par +# chave-valor a um dicionário, associando um valor padrão imutável à uma chave +dicionario.setdefault("cinco", 5) # dicionario["cinco"] é definido como 5 +dicionario.setdefault("cinco", 6) # dicionario["cinco"] ainda é igual a 5 + + +# Conjuntos (ou sets) armazenam ... bem, conjuntos +# Nota: lembre-se que conjuntos não admitem elementos repetidos! +conjunto_vazio = set() +# Podemos inicializar um conjunto com valores +conjunto = set([1, 2, 2, 3, 4]) # conjunto é set([1, 2, 3, 4]), sem repetição! + +# Desde o Python 2.7, {} pode ser usado para declarar um conjunto +conjunto = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Adicione mais ítens a um conjunto com 'add' +conjunto.add(5) # conjunto agora é {1, 2, 3, 4, 5} + +# Calcule a intersecção de dois conjuntos com & +outro_conj = {3, 4, 5, 6} +conjunto & outro_conj #=> {3, 4, 5} + +# Calcule a união de dois conjuntos com | +conjunto | outro_conj #=> {1, 2, 3, 4, 5, 6} + +# E a diferença entre dois conjuntos com - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Veja se um elemento existe em um conjunto usando 'in' +2 in conjunto #=> True +10 in conjunto #=> False + + +#################################################### +## 3. Controle +#################################################### + +# Para começar, vamos apenas criar uma variável +alguma_var = 5 + +# Aqui está uma expressão 'if'. Veja como a identação é importante em Python! +# Esses comandos irão imprimir "alguma_var é menor que 10" +if alguma_var > 10: + print "some_var é maior que 10." +elif some_var < 10: # Esse 'elif' é opcional + print "some_var é menor que 10." +else: # Esse 'else' também é opcional + print "some_var é igual a 10." + + +""" +Laços (ou loops) 'for' iteram em listas. +Irá imprimir: + cachorro é um mamífero + gato é um mamífero + rato é um mamífero +""" +for animal in ["cachorro", "gato", "rato"]: + # Você pode usar % para interpolar strings formatadas + print "%s é um mamífero" % animal + +""" +A função `range(um número)` retorna uma lista de números +do zero até o número dado. +Irá imprimir: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +Laços 'while' executam enquanto uma condição dada for verdadeira. +Irá imprimir: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Isso é um atalho para a expressão x = x + 1 + +# Tratamos excessões usando o bloco try/except +# Funciona em Python 2.6 e versões superiores: + +try: + # Use 'raise' para gerar um erro + raise IndexError("Isso é um erro de índice") +except IndexError as e: + pass # Pass é um operador que não faz nada, deixa passar. + # Usualmente você iria tratar a exceção aqui... + + +#################################################### +## 4. Funções +#################################################### + +# Use 'def' para definir novas funções +def soma(x, y): + print "x é %s e y é %s" % (x, y) + return x + y # Retorne valores usando 'return' + +# Chamando funções com parâmetros +soma(5, 6) #=> imprime "x é 5 e y é 6" e retorna o valor 11 + +# Um outro jeito de chamar funções é especificando explicitamente os valores +# de cada parâmetro com chaves +soma(y=6, x=5) # Argumentos com chaves podem vir em qualquer ordem. + +# Você pode definir funções que recebem um número qualquer de argumentos +# (respeitando a sua ordem) +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Você também pode definir funções que recebem um número qualquer de argumentos +# com chaves +def args_com_chaves(**ch_args): + return ch_args + +# Vamos chamar essa função para ver o que acontece +args_com_chaves(pe="grande", lago="Ness") #=> {"pe": "grande", "lago": "Ness"} + +# Você pode fazer as duas coisas ao mesmo tempo, se desejar +def todos_args(*args, **ch_wargs): + print args + print ch_args +""" +todos_args(1, 2, a=3, b=4) imprime: + (1, 2) + {"a": 3, "b": 4} +""" + +# Quando você chamar funções, pode fazer o oposto do que fizemos até agora! +# Podemos usar * para expandir tuplas de argumentos e ** para expandir +# dicionários de argumentos com chave. +args = (1, 2, 3, 4) +ch_args = {"a": 3, "b": 4} +todos_args(*args) # equivalente a todos_args(1, 2, 3, 4) +todos_args(**ch_args) # equivalente a todos_args(a=3, b=4) +todos_args(*args, **ch_args) # equivalente a todos_args(1, 2, 3, 4, a=3, b=4) + +# Em Python, funções são elementos de primeira ordem (são como objetos, +# strings ou números) +def cria_somador(x): + def somador(y): + return x + y + return somador + +soma_10 = cria_somador(10) +soma_10(3) #=> 13 + +# Desta forma, existem também funções anônimas +(lambda x: x > 2)(3) #=> True + +# E existem funções de alta ordem por padrão +map(soma_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +reduce(lambda x, y: x + y, [3, 4, 5, 6, 7]) #=> 25 + +# Nós podemos usar compreensão de listas para mapear e filtrar também +[soma_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. Classes +#################################################### + +# Para criar uma nova classe, devemos herdar de 'object' +class Humano(object): + + # Um atributo de classe. Ele é compartilhado por todas as instâncias dessa + # classe + especie = "H. sapiens" + + # Definimos um inicializador básico + def __init__(self, nome): + # Atribui o valor de argumento dado a um atributo da instância + self.nome = nome + + # Um método de instância. Todos os métodos levam 'self' como primeiro + # argumento + def diga(self, msg): + return "%s: %s" % (self.nome, msg) + + # Um método de classe é compartilhado por todas as instâncias + # Eles são chamados passando o nome da classe como primeiro argumento + @classmethod + def get_especie(cls): + return cls.especie + + # Um método estático é chamado sem uma referência a classe ou instância + @staticmethod + def ronca(): + return "*arrrrrrr*" + + +# Instancie uma classe +i = Humano(nome="Ivone") +print i.diga("oi") # imprime "Ivone: oi" + +j = Human("Joel") +print j.say("olá") #prints out "Joel: olá" + +# Chame nosso método de classe +i.get_especie() #=> "H. sapiens" + +# Modifique um atributo compartilhado +Humano.especie = "H. neanderthalensis" +i.get_especie() #=> "H. neanderthalensis" +j.get_especie() #=> "H. neanderthalensis" + +# Chame o método estático +Humano.ronca() #=> "*arrrrrrr*" + + +#################################################### +## 6. Módulos +#################################################### + +# Você pode importar módulos +import math +print math.sqrt(16) #=> 4 + +# Você pode importar funções específicas de um módulo +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Você também pode importar todas as funções de um módulo +# Atenção: isso não é recomendado! +from math import * + +# Você pode usar apelidos para os módulos, encurtando seus nomes +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Módulos em Python são apenas arquivos Python. Você +# pode escrever o seu próprio módulo e importá-lo. O nome do +# módulo será o mesmo que o nome do arquivo. + +# Você pode descobrir quais funções e atributos +# estão definidos em um módulo qualquer. +import math +dir(math) + + +``` + +## Pronto para mais? + +### Online e gratuito + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Livros impressos + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/python.html.markdown b/python.html.markdown index e0851950..f0b74d08 100644 --- a/python.html.markdown +++ b/python.html.markdown @@ -1,12 +1,12 @@ --- language: python -author: Louie Dinh -author_url: http://ldinh.ca +contributors: + - ["Louie Dinh", "http://ldinh.ca"] filename: learnpython.py --- Python was created by Guido Van Rossum in the early 90's. It is now one of the most popular -languages in existence. I fell in love with Python for it's syntactic clarity. It's basically +languages in existence. I fell in love with Python for its syntactic clarity. It's basically executable pseudocode. Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service] @@ -67,7 +67,7 @@ not False #=> True 2 <= 2 #=> True 2 >= 2 #=> True -# Comparisons can be chained ! +# Comparisons can be chained! 1 < 2 < 3 #=> True 2 < 3 < 2 #=> False @@ -214,7 +214,7 @@ filled_dict.values() #=> [3, 2, 1] "one" in filled_dict #=> True 1 in filled_dict #=> False - # Looking up a non-existing key is a KeyError +# Looking up a non-existing key is a KeyError filled_dict["four"] # KeyError # Use get method to avoid the KeyError @@ -232,7 +232,7 @@ filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5 # Sets store ... well sets empty_set = set() # Initialize a set with a bunch of values -some_set = set([1,2,2,3,4]) # filled_set is now set([1, 2, 3, 4]) +some_set = set([1,2,2,3,4]) # some_set is now set([1, 2, 3, 4]) # Since Python 2.7, {} can be used to declare a set filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} @@ -263,7 +263,7 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6} some_var = 5 # Here is an if statement. Indentation is significant in python! -# prints "some var is smaller than 10" +# prints "some_var is smaller than 10" if some_var > 10: print "some_var is totally bigger than 10." elif some_var < 10: # This elif clause is optional. @@ -394,7 +394,7 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] # We subclass from object to get a class. class Human(object): - # A class attribute. It is shared by all instances of this class + # A class attribute. It is shared by all instances of this class species = "H. sapiens" # Basic initializer @@ -470,12 +470,19 @@ dir(math) ``` -## Further Reading +## Ready For More? -Still up for more? Try: +### Free Online * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) * [The Official Docs](http://docs.python.org/2.6/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) * [Python Module of the Week](http://pymotw.com/2/) + +### Dead Tree + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/r.html.markdown b/r.html.markdown index 535b9065..03aa1dd2 100644 --- a/r.html.markdown +++ b/r.html.markdown @@ -1,11 +1,12 @@ --- language: R -author: e99n09 -author_url: http://github.com/e99n09 +contributors: + - ["e99n09", "http://github.com/e99n09"] + - ["isomorphismes", "http://twitter.com/isomorphisms"] filename: learnr.r --- -R is a statistical computing language. It has lots of good built-in functions for uploading and cleaning data sets, running common statistical tests, and making graphs. You can also easily compile it within a LaTeX document. +R is a statistical computing language. It has lots of libraries for uploading and cleaning data sets, running statistical procedures, and making graphs. You can also run `R`commands within a LaTeX document. ```python @@ -14,63 +15,244 @@ R is a statistical computing language. It has lots of good built-in functions fo # You can't make a multi-line comment per se, # but you can stack multiple comments like so. -# Hit COMMAND-ENTER to execute a line +# in Windows, hit COMMAND-ENTER to execute a line + + +################################################################### +# Stuff you can do without understanding anything about programming +################################################################### + +data() # Browse pre-loaded data sets +data(rivers) # Lengths of Major North American Rivers +ls() # Notice that "rivers" appears in the workspace +head(rivers) # peek at the dataset +# 735 320 325 392 524 450 +length(rivers) # how many rivers were measured? +# 141 +summary(rivers) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 135.0 310.0 425.0 591.2 680.0 3710.0 +stem(rivers) #stem-and-leaf plot (like a histogram) +# +# The decimal point is 2 digit(s) to the right of the | +# +# 0 | 4 +# 2 | 011223334555566667778888899900001111223333344455555666688888999 +# 4 | 111222333445566779001233344567 +# 6 | 000112233578012234468 +# 8 | 045790018 +# 10 | 04507 +# 12 | 1471 +# 14 | 56 +# 16 | 7 +# 18 | 9 +# 20 | +# 22 | 25 +# 24 | 3 +# 26 | +# 28 | +# 30 | +# 32 | +# 34 | +# 36 | 1 + + +stem(log(rivers)) #Notice that the data are neither normal nor log-normal! Take that, Bell Curve fundamentalists. + +# The decimal point is 1 digit(s) to the left of the | +# +# 48 | 1 +# 50 | +# 52 | 15578 +# 54 | 44571222466689 +# 56 | 023334677000124455789 +# 58 | 00122366666999933445777 +# 60 | 122445567800133459 +# 62 | 112666799035 +# 64 | 00011334581257889 +# 66 | 003683579 +# 68 | 0019156 +# 70 | 079357 +# 72 | 89 +# 74 | 84 +# 76 | 56 +# 78 | 4 +# 80 | +# 82 | 2 + + +hist(rivers, col="#333333", border="white", breaks=25) #play around with these parameters +hist(log(rivers), col="#333333", border="white", breaks=25) #you'll do more plotting later + +#Here's another neat data set that comes pre-loaded. R has tons of these. data() +data(discoveries) +plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year") +plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", main="Number of important discoveries per year") + + +#rather than leaving the default ordering (by year) we could also sort to see what's typical +sort(discoveries) +# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 +# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 +# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 +# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 + +stem(discoveries, scale=2) +# +# The decimal point is at the | +# +# 0 | 000000000 +# 1 | 000000000000 +# 2 | 00000000000000000000000000 +# 3 | 00000000000000000000 +# 4 | 000000000000 +# 5 | 0000000 +# 6 | 000000 +# 7 | 0000 +# 8 | 0 +# 9 | 0 +# 10 | 0 +# 11 | +# 12 | 0 + +max(discoveries) +# 12 + +summary(discoveries) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 0.0 2.0 3.0 3.1 4.0 12.0 + + + + +#Basic statistical operations don't require any programming knowledge either + +#roll a die a few times +round(runif(7, min=.5, max=6.5)) +# 1 4 6 1 4 6 4 + +#your numbers will differ from mine unless we set the same random.seed(31337) + + +#draw from a standard Gaussian 9 times +rnorm(9) +# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 +# [7] -0.59975593 0.57629164 1.08455362 + + + + + + + + ######################### -# The absolute basics +# Basic programming stuff ######################### # NUMBERS -# We've got doubles! Behold the "numeric" class -5 # => [1] 5 -class(5) # => [1] "numeric" -# We've also got integers! They look suspiciously similar, -# but indeed are different -5L # => [1] 5 -class(5L) # => [1] "integer" +# "numeric" means double-precision floating-point numbers +5 # 5 +class(5) # "numeric" +5e4 # 50000 #handy when dealing with large,small,or variable orders of magnitude +6.02e23 # Avogadro's number +1.6e-35 # Planck length + +# long-storage integers are written with L +5L # 5 +class(5L) # "integer" + # Try ?class for more information on the class() function -# In fact, you can look up the documentation on just about anything with ? +# In fact, you can look up the documentation on `xyz` with ?xyz +# or see the source for `xyz` by evaluating xyz + +# Arithmetic +10 + 66 # 76 +53.2 - 4 # 49.2 +2 * 2.0 # 4 +3L / 4 # 0.75 +3 %% 2 # 1 + +# Weird number types +class(NaN) # "numeric" +class(Inf) # "numeric" +class(-Inf) # "numeric" #used in for example integrate( dnorm(x), 3, Inf ) -- which obviates Z-score tables + +# but beware, NaN isn't the only weird type... +class(NA) # see below +class(NULL) # NULL + + +# SIMPLE LISTS +c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 +c('alef', 'bet', 'gimmel', 'dalet', 'he') # "alef" "bet" "gimmel" "dalet" "he" +c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE + +#some more nice built-ins +5:15 # 5 6 7 8 9 10 11 12 13 14 15 + +seq(from=0, to=31337, by=1337) +# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 +# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 + +letters +# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" +# [20] "t" "u" "v" "w" "x" "y" "z" + +month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" + + +# Access the n'th element of a list with list.name[n] or sometimes list.name[[n]] +letters[18] # "r" +LETTERS[13] # "M" +month.name[9] # "September" +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 -# All the normal operations! -10 + 66 # => [1] 76 -53.2 - 4 # => [1] 49.2 -2 * 2.0 # => [1] 4 -3L / 4 # => [1] 0.75 -3 %% 2 # => [1] 1 -# Finally, we've got not-a-numbers! They're numerics too -class(NaN) # => [1] "numeric" # CHARACTERS -# We've (sort of) got strings! Behold the "character" class -"plugh" # => [1] "plugh" -class("plugh") # "character" # There's no difference between strings and characters in R +"Horatio" # "Horatio" +class("Horatio") # "character" +substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " +gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." + + + # LOGICALS -# We've got booleans! Behold the "logical" class -class(TRUE) # => [1] "logical" -class(FALSE) # => [1] "logical" +# booleans +class(TRUE) # "logical" +class(FALSE) # "logical" # Behavior is normal -TRUE == TRUE # => [1] TRUE -TRUE == FALSE # => [1] FALSE -FALSE != FALSE # => [1] FALSE -FALSE != TRUE # => [1] TRUE +TRUE == TRUE # TRUE +TRUE == FALSE # FALSE +FALSE != FALSE # FALSE +FALSE != TRUE # TRUE # Missing data (NA) is logical, too -class(NA) # => [1] "logical" +class(NA) # "logical" + + # FACTORS # The factor class is for categorical data -# It has an attribute called levels that describes all the possible categories -factor("dog") -# => -# [1] dog -# Levels: dog -# (This will make more sense once we start talking about vectors) +# which can be ordered (like childrens' grade levels) +# or unordered (like gender) +levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" + +factor(c("female", "female", "male", "NA", "female")) +# female female male NA female +# Levels: female male NA + +data(infert) #Infertility after Spontaneous and Induced Abortion +levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" + + # VARIABLES @@ -80,8 +262,8 @@ y <- "1" # this is preferred TRUE -> z # this works but is weird # We can use coerce variables to different classes -as.numeric(y) # => [1] 1 -as.character(x) # => [1] "5" +as.numeric(y) # 1 +as.character(x) # "5" # LOOPS @@ -115,14 +297,13 @@ if (4 > 3) { # FUNCTIONS # Defined like so: -myFunc <- function(x) { - x <- x * 4 - x <- x - 1 +jiggle <- function(x) { + x+ rnorm(x, sd=.1) #add in a bit of (controlled) noise return(x) } # Called like any other R function: -myFunc(5) # => [1] 19 +jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 ######################### # Fun with data: vectors, matrices, data frames, and arrays @@ -132,35 +313,35 @@ myFunc(5) # => [1] 19 # You can vectorize anything, so long as all components have the same type vec <- c(8, 9, 10, 11) -vec # => [1] 8 9 10 11 +vec # 8 9 10 11 # The class of a vector is the class of its components -class(vec) # => [1] "numeric" +class(vec) # "numeric" # If you vectorize items of different classes, weird coercions happen -c(TRUE, 4) # => [1] 1 4 -c("dog", TRUE, 4) # => [1] "dog" "TRUE" "4" +c(TRUE, 4) # 1 4 +c("dog", TRUE, 4) # "dog" "TRUE" "4" # We ask for specific components like so (R starts counting from 1) -vec[1] # => [1] 8 +vec[1] # 8 # We can also search for the indices of specific components, -which(vec %% 2 == 0) # => [1] 1 3 +which(vec %% 2 == 0) # 1 3 # or grab just the first or last entry in the vector -head(vec, 1) # => [1] 8 -tail(vec, 1) # => [1] 11 +head(vec, 1) # 8 +tail(vec, 1) # 11 # If an index "goes over" you'll get NA: -vec[6] # => [1] NA +vec[6] # NA # You can find the length of your vector with length() -length(vec) # => [1] 4 +length(vec) # 4 # You can perform operations on entire vectors or subsets of vectors -vec * 4 # => [1] 16 20 24 28 -vec[2:3] * 5 # => [1] 25 30 +vec * 4 # 16 20 24 28 +vec[2:3] * 5 # 25 30 # and there are many built-in functions to summarize vectors -mean(vec) # => [1] 9.5 -var(vec) # => [1] 1.666667 -sd(vec) # => [1] 1.290994 -max(vec) # => [1] 11 -min(vec) # => [1] 8 -sum(vec) # => [1] 38 +mean(vec) # 9.5 +var(vec) # 1.666667 +sd(vec) # 1.290994 +max(vec) # 11 +min(vec) # 8 +sum(vec) # 38 # TWO-DIMENSIONAL (ALL ONE CLASS) @@ -175,11 +356,11 @@ mat # Unlike a vector, the class of a matrix is "matrix", no matter what's in it class(mat) # => "matrix" # Ask for the first row -mat[1,] # => [1] 1 4 +mat[1,] # 1 4 # Perform operation on the first column -3 * mat[,1] # => [1] 3 6 9 +3 * mat[,1] # 3 6 9 # Ask for a specific cell -mat[3,2] # => [1] 6 +mat[3,2] # 6 # Transpose the whole matrix t(mat) # => @@ -196,7 +377,7 @@ mat2 # [2,] "2" "cat" # [3,] "3" "bird" # [4,] "4" "dog" -class(mat2) # => [1] matrix +class(mat2) # matrix # Again, note what happened! # Because matrices must contain entries all of the same class, # everything got converted to the character class @@ -216,7 +397,7 @@ mat3 # For columns of different classes, use the data frame dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) names(dat) <- c("number", "species") # name the columns -class(dat) # => [1] "data.frame" +class(dat) # "data.frame" dat # => # number species @@ -224,14 +405,14 @@ dat # 2 2 cat # 3 1 bird # 4 4 dog -class(dat$number) # => [1] "numeric" -class(dat[,2]) # => [1] "factor" +class(dat$number) # "numeric" +class(dat[,2]) # "factor" # The data.frame() function converts character vectors to factor vectors # There are many twisty ways to subset data frames, all subtly unalike -dat$number # => [1] 5 2 1 4 -dat[,1] # => [1] 5 2 1 4 -dat[,"number"] # => [1] 5 2 1 4 +dat$number # 5 2 1 4 +dat[,1] # 5 2 1 4 +dat[,"number"] # 5 2 1 4 # MULTI-DIMENSIONAL (ALL OF ONE CLASS) @@ -247,15 +428,17 @@ array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) # => # , , 1 # -# [,1] [,2] -# [1,] 1 4 -# [2,] 2 5 +# [,1] [,2] +# [1,] 2 8 +# [2,] 300 9 +# [3,] 4 0 # # , , 2 # # [,1] [,2] -# [1,] 8 1 -# [2,] 9 2 +# [1,] 5 66 +# [2,] 60 7 +# [3,] 0 847 # LISTS (MULTI-DIMENSIONAL, POSSIBLY RAGGED, OF DIFFERENT TYPES) diff --git a/racket.html.markdown b/racket.html.markdown new file mode 100644 index 00000000..adacd91d --- /dev/null +++ b/racket.html.markdown @@ -0,0 +1,607 @@ +--- + +language: racket +filename: learnracket.rkt +contributors: + - ["th3rac25", "https://github.com/voila"] + - ["Eli Barzilay", "https://github.com/elibarzilay"] + - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"] +--- + +Racket is a general purpose, multi-paradigm programming language in the Lisp/Scheme family. + +Feedback is appreciated! You can reach me at [@th3rac25](http://twitter.com/th3rac25) or th3rac25 [at] [google's email service] + + +```racket +#lang racket ; defines the language we are using + +;;; Comments + +;; Single line comments start with a semicolon + +#| Block comments + can span multiple lines and... + #| + they can be nested! + |# +|# + +;; S-expression comments discard the following expression, +;; useful to comment expressions when debugging +#; (this expression is discarded) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 1. Primitive Datatypes and Operators +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Numbers +9999999999999999999999 ; integers +#b111 ; binary => 7 +#o111 ; octal => 73 +#x111 ; hexadecimal => 273 +3.14 ; reals +6.02e+23 +1/2 ; rationals +1+2i ; complex numbers + +;; Function application is written (f x y z ...) +;; where f is a function and x, y, z, ... are operands +;; If you want to create a literal list of data, use ' to stop it from +;; being evaluated +'(+ 1 2) ; => (+ 1 2) +;; Now, some arithmetic operations +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(quotient 5 2) ; => 2 +(remainder 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(exact->inexact 1/3) ; => 0.3333333333333333 +(+ 1+2i 2-3i) ; => 3-1i + +;;; Booleans +#t ; for true +#f ; for false -- any value other than #f is true +(not #t) ; => #f +(and 0 #f (error "doesn't get here")) ; => #f +(or #f 0 (error "doesn't get here")) ; => 0 + +;;; Characters +#\A ; => #\A +#\λ ; => #\λ +#\u03BB ; => #\λ + +;;; Strings are fixed-length array of characters. +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ; backslash is an escaping character +"Foo\tbar\41\x21\u0021\a\r\n" ; includes C escapes, Unicode +"λx:(μα.α→α).xx" ; can include Unicode characters + +;; Strings can be added too! +(string-append "Hello " "world!") ; => "Hello world!" + +;; A string can be treated like a list of characters +(string-ref "Apple" 0) ; => #\A + +;; format can be used to format strings: +(format "~a can be ~a" "strings" "formatted") + +;; Printing is pretty easy +(printf "I'm Racket. Nice to meet you!\n") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. Variables +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; You can create a variable using define +;; a variable name can use any character except: ()[]{}",'`;#|\ +(define some-var 5) +some-var ; => 5 + +;; You can also use unicode characters +(define ⊆ subset?) +(⊆ (set 3 2) (set 1 2 3)) ; => #t + +;; Accessing a previously unassigned variable is an exception +; x ; => x: undefined ... + +;; Local binding: `me' is bound to "Bob" only within the (let ...) +(let ([me "Bob"]) + "Alice" + me) ; => "Bob" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Structs and Collections +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Structs +(struct dog (name breed age)) +(define my-pet + (dog "lassie" "collie" 5)) +my-pet ; => #<dog> +(dog? my-pet) ; => #t +(dog-name my-pet) ; => "lassie" + +;;; Pairs (immutable) +;; `cons' constructs pairs, `car' and `cdr' extract the first +;; and second elements +(cons 1 2) ; => '(1 . 2) +(car (cons 1 2)) ; => 1 +(cdr (cons 1 2)) ; => 2 + +;;; Lists + +;; Lists are linked-list data structures, made of `cons' pairs and end +;; with a `null' (or '()) to mark the end of the list +(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3) +;; `list' is a convenience variadic constructor for lists +(list 1 2 3) ; => '(1 2 3) +;; and a quote can also be used for a literal list value +'(1 2 3) ; => '(1 2 3) + +;; Can still use `cons' to add an item to the beginning of a list +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; Use `append' to add lists together +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; Lists are a very basic type, so there is a *lot* of functionality for +;; them, a few examples: +(map add1 '(1 2 3)) ; => '(2 3 4) +(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(filter even? '(1 2 3 4)) ; => '(2 4) +(count even? '(1 2 3 4)) ; => 2 +(take '(1 2 3 4) 2) ; => '(1 2) +(drop '(1 2 3 4) 2) ; => '(3 4) + +;;; Vectors + +;; Vectors are fixed-length arrays +#(1 2 3) ; => '#(1 2 3) + +;; Use `vector-append' to add vectors together +(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; Sets + +;; Create a set from a list +(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3) + +;; Add a member with `set-add' +;; (Functional: returns the extended set rather than mutate the input) +(set-add (set 1 2 3) 4) ; => (set 1 2 3 4) + +;; Remove one with `set-remove' +(set-remove (set 1 2 3) 1) ; => (set 2 3) + +;; Test for existence with `set-member?' +(set-member? (set 1 2 3) 1) ; => #t +(set-member? (set 1 2 3) 4) ; => #f + +;;; Hashes + +;; Create an immutable hash table (mutable example below) +(define m (hash 'a 1 'b 2 'c 3)) + +;; Retrieve a value +(hash-ref m 'a) ; => 1 + +;; Retrieving a non-present value is an exception +; (hash-ref m 'd) => no value found + +;; You can provide a default value for missing keys +(hash-ref m 'd 0) ; => 0 + +;; Use `hash-set' to extend an immutable hash table +;; (Returns the extended hash instdead of mutating it) +(define m2 (hash-set m 'd 4)) +m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3)) + +;; Remember, these hashes are immutable! +m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' + +;; Use `hash-remove' to remove keys (functional too) +(hash-remove m 'a) ; => '#hash((b . 2) (c . 3)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Use `lambda' to create functions. +;; A function always returns the value of its last expression +(lambda () "Hello World") ; => #<procedure> +;; Can also use a unicode `λ' +(λ () "Hello World") ; => same function + +;; Use parens to call all functions, including a lambda expression +((lambda () "Hello World")) ; => "Hello World" +((λ () "Hello World")) ; => "Hello World" + +;; Assign a function to a var +(define hello-world (lambda () "Hello World")) +(hello-world) ; => "Hello World" + +;; You can shorten this using the function definition syntatcic sugae: +(define (hello-world2) "Hello World") + +;; The () in the above is the list of arguments for the function +(define hello + (lambda (name) + (string-append "Hello " name))) +(hello "Steve") ; => "Hello Steve" +;; ... or equivalently, using a sugared definition: +(define (hello2 name) + (string-append "Hello " name)) + +;; You can have multi-variadic functions too, using `case-lambda' +(define hello3 + (case-lambda + [() "Hello World"] + [(name) (string-append "Hello " name)])) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" +;; ... or specify optional arguments with a default value expression +(define (hello4 [name "World"]) + (string-append "Hello " name)) + +;; Functions can pack extra arguments up in a list +(define (count-args . args) + (format "You passed ~a args: ~a" (length args) args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" +;; ... or with the unsugared `lambda' form: +(define count-args2 + (lambda args + (format "You passed ~a args: ~a" (length args) args))) + +;; You can mix regular and packed arguments +(define (hello-count name . args) + (format "Hello ~a, you passed ~a extra args" name (length args))) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" +;; ... unsugared: +(define hello-count2 + (lambda (name . args) + (format "Hello ~a, you passed ~a extra args" name (length args)))) + +;; And with keywords +(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args) + (format "~a ~a, ~a extra args" g name (length args))) +(hello-k) ; => "Hello World, 0 extra args" +(hello-k 1 2 3) ; => "Hello World, 3 extra args" +(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args" +(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args" +(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6) + ; => "Hi Finn, 6 extra args" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. Equality +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; for numbers use `=' +(= 3 3.0) ; => #t +(= 2 1) ; => #f + +;; for object identity use `eq?' +(eq? 3 3) ; => #t +(eq? 3 3.0) ; => #f +(eq? (list 3) (list 3)) ; => #f + +;; for collections use `equal?' +(equal? (list 'a 'b) (list 'a 'b)) ; => #t +(equal? (list 'a 'b) (list 'b 'a)) ; => #f + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. Control Flow +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Conditionals + +(if #t ; test expression + "this is true" ; then expression + "this is false") ; else expression +; => "this is true" + +;; In conditionals, all non-#f values are treated as true +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'yep + +;; `cond' chains a series of tests to select a result +(cond [(> 2 2) (error "wrong!")] + [(< 2 2) (error "wrong again!")] + [else 'ok]) ; => 'ok + +;;; Pattern Matching + +(define (fizzbuzz? n) + (match (list (remainder n 3) (remainder n 5)) + [(list 0 0) 'fizzbuzz] + [(list 0 _) 'fizz] + [(list _ 0) 'buzz] + [_ #f])) + +(fizzbuzz? 15) ; => 'fizzbuzz +(fizzbuzz? 37) ; => #f + +;;; Loops + +;; Looping can be done through (tail-) recursion +(define (loop i) + (when (< i 10) + (printf "i=~a\n" i) + (loop (add1 i)))) +(loop 5) ; => i=5, i=6, ... + +;; Similarly, with a named let +(let loop ((i 0)) + (when (< i 10) + (printf "i=~a\n" i) + (loop (add1 i)))) ; => i=0, i=1, ... + +;; See below how to add a new `loop' form, but Racket already has a very +;; flexible `for' form for loops: +(for ([i 10]) + (printf "i=~a\n" i)) ; => i=0, i=1, ... +(for ([i (in-range 5 10)]) + (printf "i=~a\n" i)) ; => i=5, i=6, ... + +;;; Iteration Over Other Sequences +;; `for' allows iteration over many other kinds of sequences: +;; lists, vectors, strings, sets, hash tables, etc... + +(for ([i (in-list '(l i s t))]) + (displayln i)) + +(for ([i (in-vector #(v e c t o r))]) + (displayln i)) + +(for ([i (in-string "string")]) + (displayln i)) + +(for ([i (in-set (set 'x 'y 'z))]) + (displayln i)) + +(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))]) + (printf "key:~a value:~a\n" k v)) + +;;; More Complex Iterations + +;; Parallel scan of multiple sequences (stops on shortest) +(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x 1:y 2:z + +;; Nested loops +(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z + +;; Conditions +(for ([i 1000] + #:when (> i 5) + #:unless (odd? i) + #:break (> i 10)) + (printf "i=~a\n" i)) +; => i=6, i=8, i=10 + +;;; Comprehensions +;; Very similar to `for' loops -- just collect the results + +(for/list ([i '(1 2 3)]) + (add1 i)) ; => '(2 3 4) + +(for/list ([i '(1 2 3)] #:when (even? i)) + i) ; => '(2) + +(for/list ([i 10] [j '(x y z)]) + (list i j)) ; => '((0 x) (1 y) (2 z)) + +(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10)) + i) ; => '(6 8 10) + +(for/hash ([i '(1 2 3)]) + (values i (number->string i))) +; => '#hash((1 . "1") (2 . "2") (3 . "3")) + +;; There are many kinds of other built-in ways to collect loop values: +(for/sum ([i 10]) (* i i)) ; => 285 +(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000 +(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t +(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t +;; And to use any arbitrary combination, use `for/fold' +(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10 +;; (This can often replace common imperative loops) + +;;; Exceptions + +;; To catch exceptions, use the `with-handlers' form +(with-handlers ([exn:fail? (lambda (exn) 999)]) + (+ 1 "2")) ; => 999 +(with-handlers ([exn:break? (lambda (exn) "no time")]) + (sleep 3) + "phew") ; => "phew", but if you break it => "no time" + +;; Use `raise' to throw exceptions or any other value +(with-handlers ([number? ; catch numeric values raised + identity]) ; return them as plain values + (+ 1 (raise 2))) ; => 2 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. Mutation +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Use `set!' to assign a new value to an existing variable +(define n 5) +(set! n (add1 n)) +n ; => 6 + +;; Use boxes for explicitly mutable values (similar to pointers or +;; references in other languages) +(define n* (box 5)) +(set-box! n* (add1 (unbox n*))) +(unbox n*) ; => 6 + +;; Many Racket datatypes are immutable (pairs, lists, etc), some come in +;; both mutable and immutable flavors (strings, vectors, hash tables, +;; etc...) + +;; Use `vector' or `make-vector' to create mutable vectors +(define vec (vector 2 2 3 4)) +(define wall (make-vector 100 'bottle-of-beer)) +;; Use vector-set! to update a slot +(vector-set! vec 0 1) +(vector-set! wall 99 'down) +vec ; => #(1 2 3 4) + +;; Create an empty mutable hash table and manipulate it +(define m3 (make-hash)) +(hash-set! m3 'a 1) +(hash-set! m3 'b 2) +(hash-set! m3 'c 3) +(hash-ref m3 'a) ; => 1 +(hash-ref m3 'd 0) ; => 0 +(hash-remove! m3 'a) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. Modules +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Modules let you organize code into multiple files and reusable +;; libraries; here we use sub-modules, nested in the whole module that +;; this text makes (starting from the "#lang" line) + +(module cake racket/base ; define a `cake' module based on racket/base + + (provide print-cake) ; function exported by the module + + (define (print-cake n) + (show " ~a " n #\.) + (show " .-~a-. " n #\|) + (show " | ~a | " n #\space) + (show "---~a---" n #\-)) + + (define (show fmt n ch) ; internal function + (printf fmt (make-string n ch)) + (newline))) + +;; Use `require' to get all `provide'd names from a module +(require 'cake) ; the ' is for a local submodule +(print-cake 3) +; (show "~a" 1 #\A) ; => error, `show' was not exported + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. Classes and Objects +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Create a class fish% (-% is idomatic for class bindings) +(define fish% + (class object% + (init size) ; initialization argument + (super-new) ; superclass initialization + ;; Field + (define current-size size) + ;; Public methods + (define/public (get-size) + current-size) + (define/public (grow amt) + (set! current-size (+ amt current-size))) + (define/public (eat other-fish) + (grow (send other-fish get-size))))) + +;; Create an instance of fish% +(define charlie + (new fish% [size 10])) + +;; Use `send' to call an object's methods +(send charlie get-size) ; => 10 +(send charlie grow 6) +(send charlie get-size) ; => 16 + +;; `fish%' is a plain "first class" value, which can get us mixins +(define (add-color c%) + (class c% + (init color) + (super-new) + (define my-color color) + (define/public (get-color) my-color))) +(define colored-fish% (add-color fish%)) +(define charlie2 (new colored-fish% [size 10] [color 'red])) +(send charlie2 get-color) +;; or, with no names: +(send (new (add-color fish%) [size 10] [color 'red]) get-color) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 9. Macros +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macros let you extend the syntax of the language + +;; Let's add a while loop +(define-syntax-rule (while condition body ...) + (let loop () + (when condition + body ... + (loop)))) + +(let ([i 0]) + (while (< i 10) + (displayln i) + (set! i (add1 i)))) + +;; Macros are hygienic, you cannot clobber existing variables! +(define-syntax-rule (swap! x y) ; -! is idomatic for mutation + (let ([tmp x]) + (set! x y) + (set! y tmp))) + +(define tmp 2) +(define other 3) +(swap! tmp other) +(printf "tmp = ~a; other = ~a\n" tmp other) +;; The variable `tmp` is renamed to `tmp_1` +;; in order to avoid name conflict +;; (let ([tmp_1 tmp]) +;; (set! tmp other) +;; (set! other tmp_1)) + +;; But they are still code transformations, for example: +(define-syntax-rule (bad-while condition body ...) + (when condition + body ... + (bad-while condition body ...))) +;; this macro is broken: it generates infinite code, if you try to use +;; it, the compiler will get in an infinite loop + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 10. Contracts +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Contracts impose constraints on values exported from modules + +(module bank-account racket + (provide (contract-out + [deposit (-> positive? any)] ; amounts are always positive + [balance (-> positive?)])) + + (define amount 0) + (define (deposit a) (set! amount (+ amount a))) + (define (balance) amount) + ) + +(require 'bank-account) +(deposit 5) + +(balance) ; => 5 + +;; Clients that attempt to deposit a non-positive amount are blamed +;; (deposit -5) ; => deposit: contract violation +;; expected: positive? +;; given: -5 +;; more details.... +``` + +## Further Reading + +Still up for more? Try [Getting Started with Racket](http://docs.racket-lang.org/getting-started/) diff --git a/ruby-ecosystem.html.markdown b/ruby-ecosystem.html.markdown new file mode 100644 index 00000000..a31f552d --- /dev/null +++ b/ruby-ecosystem.html.markdown @@ -0,0 +1,137 @@ +--- +category: tool +tool: ruby ecosystem +contributors: + - ["Jon Smock", "http://github.com/jonsmock"] + +--- + +People using ruby generally have a way to install different ruby versions, +manage their packages (or gems), and manage their gem dependencies. + +## Ruby Managers + +Some platforms have ruby pre-installed or available as a package. Most rubyists +do not use these, or if they do, they only use them to bootstrap another ruby +installer or implementation. Instead rubyists tend to install a ruby manager to +install and switch between many versions of ruby and their projects' ruby +environments. + +The following are the popular ruby/environment managers: + +* [RVM](https://rvm.io/) - Installs and switches between rubies. RVM also has + the concept of gemsets to isolate projects' environments completely. +* [ruby-build](https://github.com/sstephenson/ruby-build) - Only installs + rubies. Use this for finer control over your rubies' installations. +* [rbenv](https://github.com/sstephenson/rbenv) - Only switches between rubies. + Used with ruby-build. Use this for finer control over how rubies load. +* [chruby](https://github.com/postmodern/chruby) - Only switches between rubies. + Similar in spirit to rbenv. Unopinionated about how rubies are installed. + +## Ruby Versions + +Ruby was created by Yukihiro "Matz" Matsumoto, who remains somewhat of a +[BDFL](https://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life), although +that is changing recently. As a result, the reference implementation of ruby is +called MRI (Matz' Reference Implementation), and when you hear a ruby version, +it is referring to the release version of MRI. + +The three major version of ruby in use are: + +* 2.0.0 - Released in February 2013. Most major libraries and frameworks support + 2.0.0. +* 1.9.3 - Released in October 2011. This is the version most rubyists use + currently. +* 1.8.7 - Ruby 1.8.7 has been + [retired](http://www.ruby-lang.org/en/news/2013/06/30/we-retire-1-8-7/). + +The change between 1.8.7 to 1.9.x is a much larger change than 1.9.3 to 2.0.0. +For instance, the 1.9 series introduced encodings and a bytecode VM. There +are projects still on 1.8.7, but they are becoming a small minority, as most of +the community has moved to at least 1.9.2 or 1.9.3. + +## Ruby Implementations + +The ruby ecosystem enjoys many different implementations of ruby, each with +unique strengths and states of compatability. To be clear, the different +implementations are written in different languages, but *they are all ruby*. +Each implementation has special hooks and extra features, but they all run +normal ruby files well. For instance, JRuby is written in Java, but you do +not need to know Java to use it. + +Very mature/compatible: + +* MRI - Written in C, this is the reference implementation of ruby. By + definition it is 100% compatible (with itself). All other rubies +maintain capatability with MRI (see RubySpec below). +* JRuby - Written in Java and ruby, this robust implementation is quite fast. + Most importantly, JRuby's strength is JVM/Java interop, leveraging existing +JVM tools, projects, and languages. +* Rubinius - Written primarily in ruby itself with a C++ bytecode VM. Also + mature and fast. Because it is implemented in ruby itself, it exposes many VM +features into rubyland. + +Medium mature/compatible: + +* Maglev - Built on top of Gemstone, a Smalltalk VM. Smalltalk has some + impressive tooling, and this project tries to bring that into ruby +development. +* RubyMotion - Brings ruby to iOS development. + +Less mature/compatible: + +* Topaz - Written in RPython (using the PyPy toolchain), Topaz is fairly young + and not yet compatable. It shows promise to be a high-performance ruby +implementation. +* IronRuby - Written in C# targeting the .NET platform, work on IronRuby seems + to have stopped since Microsoft pulled their support. + +Ruby implementations may have their own release version numbers, but they always +target a specific version of MRI for compatability. Many implementations have +the ability to enter different modes (for example, 1.8 or 1.9 mode) to specify +which MRI version to target. + +## RubySpec + +Most ruby implementations rely heavily on (RubySpec)[http://rubyspec.org/]. Ruby +has no official specification, so the community has written executable specs in +ruby to test their implementations' compatability with MRI. + +## RubyGems + +(RubyGems)[http://rubygems.org/] is a community-run package manager for ruby. +RubyGems ships with ruby, so there is no need to download it separately. + +Ruby packages are called "gems," and they can be hosted by the community at +RubyGems.org. Each gem contains its source code and some metadata, including +things like version, dependencies, author(s), and license(s). + +## Bundler + +(Bundler)[http://bundler.io/] is a gem dependency resolver. It uses a project's +Gemfile to find dependencies, and then fetches those dependencies' dependencies +recursively. It does this until all dependencies are resolved and downloaded, or +it will stop if a conflict has been found. + +Bundler will raise an error if it finds conflicting dependencies. For example, +if gem A requires version 3 or greater of gem Z, but gem B requires version 2, +Bundler will notify you of the conflict. This becomes extremely helpful as many +gems refer to other gems (which refer to other gems), which can form a large +dependency graph to resolve. + +# Testing + +Testing is a large of ruby culture. Ruby comes with its own Unit-style testing +framework called minitest (Or TestUnit for ruby version 1.8.x). There are many +testing libraries with different goals. + +* TestUnit - Ruby 1.8's built-in "Unit-style" testing framework +* minitest - Ruby 1.9/2.0's built-in testing framework +* RSpec - A testing framework that focuses on expressivity +* Cucumber - A BDD testing framework that parses Gherkin formatted tests + +## Be Nice + +The ruby community takes pride in being an open, diverse, welcoming community. +Matz himself is extremely friendly, and the generosity of rubyists on the whole +is amazing. diff --git a/ruby.html.markdown b/ruby.html.markdown new file mode 100644 index 00000000..861a94ad --- /dev/null +++ b/ruby.html.markdown @@ -0,0 +1,374 @@ +--- +language: ruby +filename: learnruby.rb +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] +--- + +```ruby +# This is a comment + +=begin +This is a multiline comment +No-one uses them +You shouldn't either +=end + +# First and foremost: Everything is an object. + +# Numbers are objects + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# Some basic arithmetic +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# Arithmetic is just syntactic sugar +# for calling a method on an object +1.+(3) #=> 4 +10.* 5 #=> 50 + +# Special values are objects +nil # Nothing to see here +true # truth +false # falsehood + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# Equality +1 == 1 #=> true +2 == 1 #=> false + +# Inequality +1 != 1 #=> false +2 != 1 #=> true +!true #=> false +!false #=> true + +# apart from false itself, nil is the only other 'falsey' value + +!nil #=> true +!false #=> true +!0 #=> false + +# More comparisons +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# Strings are objects + +'I am a string'.class #=> String +"I am a string too".class #=> String + +placeholder = "use string interpolation" +"I can #{placeholder} when using double quoted strings" +#=> "I can use string interpolation when using double quoted strings" + + +# print to the output +puts "I'm printing!" + +# Variables +x = 25 #=> 25 +x #=> 25 + +# Note that assignment returns the value assigned +# This means you can do multiple assignment: + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# By convention, use snake_case for variable names +snake_case = true + +# Use descriptive variable names +path_to_project_root = '/good/name/' +path = '/bad/name/' + +# Symbols (are objects) +# Symbols are immutable, reusable constants represented internally by an +# integer value. They're often used instead of strings to efficiently convey +# specific, meaningful values + +:pending.class #=> Symbol + +status = :pending + +status == :pending #=> true + +status == 'pending' #=> false + +status == :approved #=> false + +# Arrays + +# This is an array +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# Arrays can contain different types of items + +array = [1, "hello", false] #=> => [1, "hello", false] + +# Arrays can be indexed +# From the front +array[0] #=> 1 +array[12] #=> nil + +# Like arithmetic, [var] access +# is just syntactic sugar +# for calling a method [] on an object +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# From the end +array[-1] #=> 5 + +# With a start and end index +array[2, 4] #=> [3, 4, 5] + +# Or with a range +array[1..3] #=> [2, 3, 4] + +# Add to an array like this +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# Hashes are Ruby's primary dictionary with keys/value pairs. +# Hashes are denoted with curly braces: +hash = {'color' => 'green', 'number' => 5} + +hash.keys #=> ['color', 'number'] + +# Hashes can be quickly looked up by key: +hash['color'] #=> 'green' +hash['number'] #=> 5 + +# Asking a hash for a key that doesn't exist returns nil: +hash['nothing here'] #=> nil + +# Iterate over hashes with the #each method: +hash.each do |k, v| + puts "#{k} is #{v}" +end + +# Since Ruby 1.9, there's a special syntax when using symbols as keys: + +new_hash = { defcon: 3, action: true} + +new_hash.keys #=> [:defcon, :action] + +# Tip: Both Arrays and Hashes are Enumerable +# They share a lot of useful methods such as each, map, count, and more + +# Control structures + +if true + "if statement" +elsif false + "else if, optional" +else + "else, also optional" +end + +for counter in 1..5 + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +# HOWEVER +# No-one uses for loops +# Use `each` instead, like this: + +(1..5).each do |counter| + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +counter = 1 +while counter <= 5 do + puts "iteration #{counter}" + counter += 1 +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +grade = 'B' + +case grade +when 'A' + puts "Way to go kiddo" +when 'B' + puts "Better luck next time" +when 'C' + puts "You can do better" +when 'D' + puts "Scraping through" +when 'F' + puts "You failed!" +else + puts "Alternative grading system, eh?" +end + +# Functions + +def double(x) + x * 2 +end + +# Functions (and all blocks) implcitly return the value of the last statement +double(2) #=> 4 + +# Parentheses are optional where the result is unambiguous +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x,y) + x + y +end + +# Method arguments are separated by a comma +sum 3, 4 #=> 7 + +sum sum(3,4), 5 #=> 12 + +# yield +# All methods have an implicit, optional block parameter +# it can be called with the 'yield' keyword + +def surround + puts "{" + yield + puts "}" +end + +surround { puts 'hello world' } + +# { +# hello world +# } + + +# Define a class with the class keyword +class Human + + # A class variable. It is shared by all instances of this class. + @@species = "H. sapiens" + + # Basic initializer + def initialize(name, age=0) + # Assign the argument to the "name" instance variable for the instance + @name = name + # If no age given, we will fall back to the default in the arguments list. + @age = age + end + + # Basic setter method + def name=(name) + @name = name + end + + # Basic getter method + def name + @name + end + + # A class method uses self to distinguish from instance methods. + # It can only be called on the class, not an instance. + def self.say(msg) + puts "#{msg}" + end + + def species + @@species + end + +end + + +# Instantiate a class +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# Let's call a couple of methods +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# Call the class method +Human.say("Hi") #=> "Hi" + +# Class also is object in ruby. So class can have instance variables. +# Class variable is shared among the class and all of its descendants. + +# base class +class Human + @@foo = 0 + + def self.foo + @@foo + end + + def self.foo=(value) + @@foo = value + end +end + +# derived class +class Worker < Human +end + +Human.foo # 0 +Worker.foo # 0 + +Human.foo = 2 # 2 +Worker.foo # 2 + +# Class instance variable is not shared by the class's descendants. + +class Human + @bar = 0 + + def self.bar + @bar + end + + def self.bar=(value) + @bar = value + end +end + +class Doctor < Human +end + +Human.bar # 0 +Doctor.bar # nil + +``` diff --git a/scala.html.markdown b/scala.html.markdown new file mode 100644 index 00000000..b1b3ecbf --- /dev/null +++ b/scala.html.markdown @@ -0,0 +1,418 @@ +--- +language: Scala +filename: learnscala.scala +contributors: + - ["George Petrov", "http://github.com/petrovg"] + - ["Dominic Bou-Samra", "http://dbousamra.github.com"] +filename: learn.scala +--- + +Scala - the scalable language + +```cpp + +/* + Set yourself up: + + 1) Download Scala - http://www.scala-lang.org/downloads + 2) unzip/untar in your favourite location and put the bin subdir on the path + 3) Start a scala REPL by typing scala. You should see the prompt: + + scala> + + This is the so called REPL. You can run commands in the REPL. Let's do just + that: +*/ + +println(10) // prints the integer 10 + +println("Boo!") // printlns the string Boo! + + +// Some basics + +// Printing, and forcing a new line on the next print +println("Hello world!") +// Printing, without forcing a new line on next print +print("Hello world") + +// Declaring values is done using either var or val +// val declarations are immutable, whereas var's are mutable. Immutablility is +// a good thing. +val x = 10 // x is now 10 +x = 20 // error: reassignment to val +var x = 10 +x = 20 // x is now 20 + +// Single line comments start with two forward slashes +/* +Multi line comments look like this. +*/ + +// Boolean values +true +false + +// Boolean operations +!true // false +!false // true +true == false // false +10 > 5 // true + +// Math is as per usual +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 + + +// Evaluating a command in the REPL gives you the type and value of the result + +1 + 7 + +/* The above line results in: + + scala> 1 + 7 + res29: Int = 8 + + This means the result of evaluating 1 + 7 is an object of type Int with a + value of 8 + + 1+7 will give you the same result +*/ + + +// Everything is an object, including a function. Type these in the REPL: + +7 // results in res30: Int = 7 (res30 is just a generated var name for the result) + +// The next line gives you a function that takes an Int and returns it squared +(x:Int) => x * x + +// You can assign this function to an identifier, like this: +val sq = (x:Int) => x * x + +/* The above says this + + sq: Int => Int = <function1> + + Which means that this time we gave an explicit name to the value - sq is a + function that take an Int and returns Int. + + sq can be executed as follows: +*/ + +sq(10) // Gives you this: res33: Int = 100. + +// Scala allows methods and functions to return, or take as parameters, other +// functions or methods. + +val add10: Int => Int = _ + 10 // A function taking an Int and returning an Int +List(1, 2, 3) map add10 // List(11, 12, 13) - add10 is applied to each element + +// Anonymous functions can be used instead of named functions: +List(1, 2, 3) map (x => x + 10) + +// And the underscore symbol, can be used if there is just one argument to the +// anonymous function. It gets bound as the variable +List(1, 2, 3) map (_ + 10) + +// If the anonymous block AND the function you are applying both take one +// argument, you can even omit the underscore +List("Dom", "Bob", "Natalia") foreach println + + + +// Data structures + +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21) // Throws an exception + +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle") // Throws an exception + +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") + +val s = Set(1, 3, 7) +s(0) +s(1) + +/* Look up the documentation of map here - + * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map + * and make sure you can read it + */ + + +// Tuples + +(1, 2) + +(4, 3, 2) + +(1, 2, "three") + +(a, 2, "three") + +// Why have this? +val divideInts = (x:Int, y:Int) => (x / y, x % y) + +divideInts(10,3) // The function divideInts gives you the result and the remainder + +// To access the elements of a tuple, use _._n where n is the 1-based index of +// the element +val d = divideInts(10,3) + +d._1 + +d._2 + + + +// Combinators + +s.map(sq) + +val sSquared = s. map(sq) + +sSquared.filter(_ < 10) + +sSquared.reduce (_+_) + +// The filter function takes a predicate (a function from A -> Boolean) and +// selects all elements which satisfy the predicate +List(1, 2, 3) filter (_ > 2) // List(3) +List( + Person(name = "Dom", age = 23), + Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) + + +// Scala a foreach method defined on certain collections that takes a type +// returning Unit (a void method) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println + + + + +// For comprehensions + +for { n <- s } yield sq(n) + +val nSquared2 = for { n <- s } yield sq(n) + +for { n <- nSquared2 if n < 10 } yield n + +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared + +/* NB Those were not for loops. The semantics of a for loop is 'repeat', whereas + a for-comprehension defines a relationship between two sets of data. */ + + + +// Loops and iteration + +1 to 5 +val r = 1 to 5 +r.foreach( println ) + +r foreach println +// NB: Scala is quite lenient when it comes to dots and brackets - study the +// rules separately. This helps write DSLs and APIs that read like English + +(5 to 1 by -1) foreach ( println ) + +// A while loops +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + +while (i < 10) { println("i " + i); i+=1 } // Yes, again. What happened? Why? + +i // Show the value of i. Note that while is a loop in the classical sense - + // it executes sequentially while changing the loop variable. while is very + // fast, faster that Java // loops, but using the combinators and + // comprehensions above is easier to understand and parallelize + +// A do while loop +do { + println("x is still less then 10"); + x += 1 +} while (x < 10) + +// Tail recursion is an idiomatic way of doing recurring things in Scala. +// Recursive functions need an explicit return type, the compiler can't infer it. +// Here it's Unit. +def showNumbersInRange(a:Int, b:Int):Unit = { + print(a) + if (a < b) + showNumbersInRange(a + 1, b) +} + + + +// Conditionals + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + + + +// Object oriented features + +// Classname is Dog +class Dog { + //A method called bark, returning a String + def bark: String = { + // the body of the method + "Woof, woof!" + } +} + +// Classes can contain nearly any other construct, including other classes, +// functions, methods, objects, case classes, traits etc. + + + +// Case classes + +case class Person(name:String, phoneNumber:String) + +Person("George", "1234") == Person("Kate", "1236") + + + + +// Pattern matching + +val me = Person("George", "1234") + +me match { case Person(name, number) => { + "We matched someone : " + name + ", phone : " + number }} + +me match { case Person(name, number) => "Match : " + name; case _ => "Hm..." } + +me match { case Person("George", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + +val kate = Person("Kate", "1234") + +kate match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + + + +// Regular expressions + +val email = "(.*)@(.*)".r // Invoking r on String makes it a Regex + +val email(user, domain) = "henry@zkpr.com" + +"mrbean@pyahoo.com" match { + case email(name, domain) => "I know your name, " + name +} + + + +// Strings + +"Scala strings are surrounded by double quotes" // +'a' // A Scala Char +'Single quote strings don't exist' // Error +"Strings have the usual Java methods defined on them".length +"They also have some extra Scala methods.".reverse + +// Seealso: scala.collection.immutable.StringOps + +println("ABCDEF".length) +println("ABCDEF".substring(2, 6)) +println("ABCDEF".replace("C", "3")) + +val n = 45 +println(s"We have $n apples") + +val a = Array(11, 9, 6) +println(s"My second daughter is ${a(2-1)} years old") + +// Some characters need to be 'escaped', e.g. a double quote inside a string: +val a = "They stood outside the \"Rose and Crown\"" + +// Triple double-quotes let strings span multiple rows and contain quotes + +val html = """<form id="daform"> + <p>Press belo', Joe</p> + | <input type="submit"> + </form>""" + + + +// Application structure and organization + +// Importing things +import scala.collection.immutable.List + +// Import all "sub packages" +import scala.collection.immutable._ + +// Import multiple classes in one statement +import scala.collection.immutable.{List, Map} + +// Rename an import using '=>' +import scala.collection.immutable{ List => ImmutableList } + +// Import all classes, except some. The following excludes Map and Set: +import scala.collection.immutable.{Map => _, Set => _, _} + +// Your programs entry point is defined in an scala file using an object, with a +// single method, main: +object Application { + def main(args: Array[String]): Unit = { + // stuff goes here. + } +} + +// Files can contain multiple classes and objects. Compile with scalac + + + + +// Input and output + +// To read a file line by line +import scala.io.Source +for(line <- Source.fromPath("myfile.txt").getLines()) + println(line) + +// To write a file use Java's PrintWriter + + +``` + +## Further resources + +[Scala for the impatient](http://horstmann.com/scala/) + +[Twitter Scala school](http://twitter.github.io/scala_school/) + +[The scala documentation](http://docs.scala-lang.org/) + +[Try Scala in your browser](http://scalatutorials.com/tour/) + +Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) + diff --git a/visualbasic.html.markdown b/visualbasic.html.markdown new file mode 100644 index 00000000..fbfa500d --- /dev/null +++ b/visualbasic.html.markdown @@ -0,0 +1,281 @@ +--- +language: Visual Basic +contributors: + - ["Brian Martin", "http://brianmartin.biz"] +filename: learnvisualbasic.vb +--- + +```vb +Module Module1 + + Sub Main() + ' A Quick Overview of Visual Basic Console Applications before we dive + ' in to the deep end. + ' Apostrophe starts comments. + ' To Navigate this tutorial within the Visual Basic Complier, I've put + ' together a navigation system. + ' This navigation system is explained however as we go deeper into this + ' tutorial, you'll understand what it all means. + Console.Title = ("Learn X in Y Minutes") + Console.WriteLine("NAVIGATION") 'Display + Console.WriteLine("") + Console.ForegroundColor = ConsoleColor.Green + Console.WriteLine("1. Hello World Output") + Console.WriteLine("2. Hello World Input") + Console.WriteLine("3. Calculating Whole Numbers") + Console.WriteLine("4. Calculating Decimal Numbers") + Console.WriteLine("5. Working Calculator") + Console.WriteLine("6. Using Do While Loops") + Console.WriteLine("7. Using For While Loops") + Console.WriteLine("8. Conditional Statements") + Console.WriteLine("9. Select A Drink") + Console.WriteLine("50. About") + Console.WriteLine("Please Choose A Number From The Above List") + Dim selection As String = Console.ReadLine + Select Case selection + Case "1" 'HelloWorld Output + Console.Clear() 'Clears the application and opens the private sub + HelloWorldOutput() 'Name Private Sub, Opens Private Sub + Case "2" 'Hello Input + Console.Clear() + HelloWorldInput() + Case "3" 'Calculating Whole Numbers + Console.Clear() + CalculatingWholeNumbers() + Case "4" 'Calculting Decimal Numbers + Console.Clear() + CalculatingDecimalNumbers() + Case "5" 'Working Calcculator + Console.Clear() + WorkingCalculator() + Case "6" 'Using Do While Loops + Console.Clear() + UsingDoWhileLoops() + Case "7" 'Using For While Loops + Console.Clear() + UsingForLoops() + Case "8" 'Conditional Statements + Console.Clear() + ConditionalStatement() + Case "9" 'If/Else Statement + Console.Clear() + IfElseStatement() 'Select a drink + Case "50" 'About msg box + Console.Clear() + Console.Title = ("Learn X in Y Minutes :: About") + MsgBox("This tutorial is by Brian Martin (@BrianMartinn") + Console.Clear() + Main() + Console.ReadLine() + + End Select + End Sub + + 'One - I'm using numbers to help with the above navigation when I come back + 'later to build it. + + 'We use private subs to seperate different sections of the program. + Private Sub HelloWorldOutput() + 'Title of Console Application + Console.Title = "Hello World Ouput | Learn X in Y Minutes" + 'Use Console.Write("") or Console.WriteLine("") to print outputs. + 'Followed by Console.Read() alternatively Console.Readline() + 'Console.ReadLine() prints the output to the console. + Console.WriteLine("Hello World") + Console.ReadLine() + End Sub + + 'Two + Private Sub HelloWorldInput() + Console.Title = "Hello World YourName | Learn X in Y Minutes" + ' Variables + ' Data entered by a user needs to be stored. + ' Variables also start with a Dim and end with an As VariableType. + + ' In this tutorial, we want to know what your name, and make the program + ' respond to what is said. + Dim username As String + 'We use string as string is a text based variable. + Console.WriteLine("Hello, What is your name? ") 'Ask the user their name. + username = Console.ReadLine() 'Stores the users name. + Console.WriteLine("Hello " + username) 'Output is Hello 'Their name' + Console.ReadLine() 'Outsputs the above. + 'The above will ask you a question followed by printing your answer. + 'Other variables include Integer and we use Integer for whole numbers. + End Sub + + 'Three + Private Sub CalculatingWholeNumbers() + Console.Title = "Calculating Whole Numbers | Learn X in Y Minutes" + Console.Write("First number: ") 'Enter a whole number, 1, 2, 50, 104 ect + Dim a As Integer = Console.ReadLine() + Console.Write("Second number: ") 'Enter second whole number. + Dim b As Integer = Console.ReadLine() + Dim c As Integer = a + b + Console.WriteLine(c) + Console.ReadLine() + 'The above is a simple calculator + End Sub + + 'Four + Private Sub CalculatingDecimalNumbers() + Console.Title = "Calculating with Double | Learn X in Y Minutes" + 'Of course we would like to be able to add up decimals. + 'Therefore we could change the above from Integer to Double. + + 'Enter a whole number, 1.2, 2.4, 50.1, 104.9 ect + Console.Write("First number: ") + Dim a As Double = Console.ReadLine + Console.Write("Second number: ") 'Enter second whole number. + Dim b As Double = Console.ReadLine + Dim c As Double = a + b + Console.WriteLine(c) + Console.ReadLine() + 'Therefore the above program can add up 1.1 - 2.2 + End Sub + + 'Five + Private Sub WorkingCalculator() + Console.Title = "The Working Calculator| Learn X in Y Minutes" + 'However if you'd like the calculator to subtract, divide, multiple and + 'add up. + 'Copy and paste the above again. + Console.Write("First number: ") + Dim a As Double = Console.ReadLine + Console.Write("Second number: ") 'Enter second whole number. + Dim b As Integer = Console.ReadLine + Dim c As Integer = a + b + Dim d As Integer = a * b + Dim e As Integer = a - b + Dim f As Integer = a / b + + 'By adding the below lines we are able to calculate the subtract, + 'multply as well as divide the a and b values + Console.Write(a.ToString() + " + " + b.ToString()) + 'We want to pad the answers to the left by 3 spaces. + Console.WriteLine(" = " + c.ToString.PadLeft(3)) + Console.Write(a.ToString() + " * " + b.ToString()) + Console.WriteLine(" = " + d.ToString.PadLeft(3)) + Console.Write(a.ToString() + " - " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.Write(a.ToString() + " / " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.ReadLine() + + End Sub + + 'Six + Private Sub UsingDoWhileLoops() + 'Just as the previous private sub + 'This Time We Ask If The User Wishes To Continue (Yes or No?) + 'We're using Do While Loop as we're unsure if the user wants to use the + 'program more than once. + Console.Title = "UsingDoWhileLoops | Learn X in Y Minutes" + Dim answer As String 'We use the variable "String" as the answer is text + Do 'We start the program with + Console.Write("First number: ") + Dim a As Double = Console.ReadLine + Console.Write("Second number: ") + Dim b As Integer = Console.ReadLine + Dim c As Integer = a + b + Dim d As Integer = a * b + Dim e As Integer = a - b + Dim f As Integer = a / b + + Console.Write(a.ToString() + " + " + b.ToString()) + Console.WriteLine(" = " + c.ToString.PadLeft(3)) + Console.Write(a.ToString() + " * " + b.ToString()) + Console.WriteLine(" = " + d.ToString.PadLeft(3)) + Console.Write(a.ToString() + " - " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.Write(a.ToString() + " / " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) + Console.ReadLine() + 'Ask the question, does the user wish to continue? Unfortunately it + 'is case sensitive. + Console.Write("Would you like to continue? (yes / no)") + 'The program grabs the variable and prints and starts again. + answer = Console.ReadLine + 'The command for the variable to work would be in this case "yes" + Loop While answer = "yes" + + End Sub + + 'Seven + Private Sub UsingForLoops() + 'Sometimes the program only needs to run once. + 'In this program we'll be counting down from 10. + + Console.Title = "Using For Loops | Learn X in Y Minutes" + 'Declare Variable and what number it should count down in Step -1, + 'Step -2, Step -3 ect. + For i As Integer = 10 To 0 Step -1 + Console.WriteLine(i.ToString) 'Print the value of the counter + Next i 'Calculate new value + Console.WriteLine("Start") 'Lets start the program baby!! + Console.ReadLine() 'POW!! - Perhaps I got a little excited then :) + End Sub + + 'Eight + Private Sub ConditionalStatement() + Console.Title = "Conditional Statements | Learn X in Y Minutes" + Dim userName As String = Console.ReadLine + Console.WriteLine("Hello, What is your name? ") 'Ask the user their name. + userName = Console.ReadLine() 'Stores the users name. + If userName = "Adam" Then + Console.WriteLine("Hello Adam") + Console.WriteLine("Thanks for creating this useful site") + Console.ReadLine() + Else + Console.WriteLine("Hello " + userName) + Console.WriteLine("Have you checked out www.learnxinyminutes.com") + Console.ReadLine() 'Ends and prints the above statement. + End If + End Sub + + 'Nine + Private Sub IfElseStatement() + Console.Title = "If / Else Statement | Learn X in Y Minutes" + 'Sometimes its important to consider more than two alternatives. + 'Sometimes there are a good few others. + 'When this is the case, more than one if statement would be required. + 'An if statement is great for vending machines. Where the user enters a code. + 'A1, A2, A3, ect to select an item. + 'All choices can be combined into a single if statement. + + Dim selection As String = Console.ReadLine 'Value for selection + Console.WriteLine("A1. for 7Up") + Console.WriteLine("A2. for Fanta") + Console.WriteLine("A3. for Dr. Pepper") + Console.WriteLine("A4. for Diet Coke") + Console.ReadLine() + If selection = "A1" Then + Console.WriteLine("7up") + Console.ReadLine() + ElseIf selection = "A2" Then + Console.WriteLine("fanta") + Console.ReadLine() + ElseIf selection = "A3" Then + Console.WriteLine("dr. pepper") + Console.ReadLine() + ElseIf selection = "A4" Then + Console.WriteLine("diet coke") + Console.ReadLine() + Else + Console.WriteLine("Please select a product") + Console.ReadLine() + End If + + End Sub + +End Module + +``` + +## References + +I learnt Visual Basic in the console application. It allowed me to understand the principles of computer programming to go on to learn other programming languages easily. + +I created a more indepth <a href="http://www.vbbootcamp.co.uk/" Title="Visual Basic Tutorial">Visual Basic tutorial</a> for those who would like to learn more. + +The entire syntax is valid. Copy the and paste in to the Visual Basic compiler and run (F5) the program. diff --git a/whip.html.markdown b/whip.html.markdown new file mode 100644 index 00000000..b8852ecb --- /dev/null +++ b/whip.html.markdown @@ -0,0 +1,238 @@ +--- +language: whip +contributors: + - ["Tenor Biel", "http://github.com/L8D"] +author: Tenor Biel +author_url: http://github.com/L8D +filename: whip.lisp +--- + +Whip is a LISP-dialect made for scripting and simplified concepts. +It has also borrowed a lot of functions and syntax from Haskell(a non-related language). + +These docs were written by the creator of the language himself. So is this line. + +```scheme +; Comments are like LISP. Semi-colons... + +; Majority of first-level statements are inside "forms" +; which are just things inside parens separated by whitespace +not_in_form +(in_form) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 1. Numbers, Strings, and Operators + +; Whip has one number type (which is a 64-bit IEEE 754 double, from JavaScript). +3 ; => 3 +1.5 ; => 1.5 + +; Functions are called if they are the first element in a form +(called_function args) + +; Majority of operations are done with functions +; All the basic arihmetic is pretty straight forward +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 +; even modulo +(% 9 4) ; => 1 +; JavaScript-style uneven division. +(/ 5 2) ; => 2.5 + +; Nesting forms works as you expect. +(* 2 (+ 1 3)) ; => 8 + +; There's a boolean type. +true +false + +; String are created with ". +"Hello, world" + +; Single chars are created with '. +'a' + +; Negation uses the 'not' function. +(not true) ; => false +(not false) ; => true + +; But the majority of non-haskell functions have shortcuts +; not's shortcut is a '!'. +(! (! true)) ; => true + +; Equality is `equal` or `=`. +(= 1 1) ; => true +(equal 2 1) ; => false + +; For example, inequality would be combinding the not and equal functions. +(! (= 2 1)) ; => true + +; More comparisons +(< 1 10) ; => true +(> 1 10) ; => false +; and their word counterpart. +(lesser 1 10) ; => true +(greater 1 10) ; => false + +; Strings can be concatenated with +. +(+ "Hello " "world!") ; => "Hello world!" + +; You can use JavaScript's comparative abilities. +(< 'a' 'b') ; => true +; ...and type coercion +(= '5' 5) + +; The `at` or @ function will access characters in strings, starting at 0. +(at 0 'a') ; => 'a' +(@ 3 "foobar") ; => 'b' + +; There is also the `null` and `undefined` variables. +null ; used to indicate a deliberate non-value +undefined ; user to indicate a value that hasn't been set + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 2. Vairbles, Lists, and Dicts + +; Variables are declared with the `def` or `let` functions. +; Variab;es that haven't been set will be `undefined`. +(def some_var 5) +; `def` will keep the variable in the global context. +; `let` will only have the variable inside it's context, and has a wierder syntax. +(let ((a_var 5)) (+ a_var 5)) ; => 10 +(+ a_var 5) ; = undefined + 5 => undefined + +; Lists are arrays of values of any type. +; They basically are just forms without functions at the beginning. +(1 2 3) ; => [1, 2, 3] (JavaScript syntax) + +; Dictionaries are Whip's equivalent to JavaScript 'objects' or Python 'dicts' +; or Ruby 'hashes': an unordered collection of key-value pairs. +{"key1":"value1" "key2":2 3:3} + +; Keys are just values, either identifier, number, or string. +(def my_dict {my_key:"my_value" "my other key":4}) +; But in Whip, dictionaries get parsed like: value, colon, value; +; with whitespace between each. So that means +{"key": "value" +"another key" +: 1234 +} +; is evaluated to the same as +{"key":"value" "another key":1234} + +; Dictionary definitions can be accessed used the `at` function +; (like strings and lists.) +(@ "my other key" my_dict) ; => 4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 3. Logic and Control sequences + +; The `if` function is pretty simple, though different than most imperitave langs. +(if true "returned if first arg is true" "returned if first arg is false") +; => "returned if first arg is true" + +; And for the sake of ternary operator legacy +; `?` is if's unused shortcut. +(? false true false) ; => false + +; `both` is a logical 'and' statement, and `either` is a logical 'or'. +(both true true) ; => true +(both true false) ; => false +(either true false) ; => true +(either false false) ; => false +; And their shortcuts are +; & => both +; ^ => either +(& true true) ; => true +(^ false true) ; => true + +;;;;;;;;; +; Lambdas + +; Lambdas in Whip are declared with the `lambda` or `->` function. +; And functions are really just lambdas with names. +(def my_function (-> (x y) (+ (x y) 10))) +; | | | | +; | | | returned value(with scope containing argument vars) +; | | arguments +; | lambda declaration function +; | +; name of the to-be-decalred lambda + +(my_function 10 10) ; = (+ (+ 10 10) 10) => 30 + +; Obiously, all lambdas by definition are anonymous and +; technically always used anonymouesly. Redundancy. +((lambda (x) x) 10) ; => 10 + +;;;;;;;;;;;;;;;; +; Comprehensions + +; `range` or `..` generates a list of numbers for +; each number between it's two args. +(range 1 5) ; => (1 2 3 4 5) +(.. 0 2) ; => (0 1 2) + +; `map` applies it's first arg(which should be a lambda/function) +; to each item in the following arg(which should be a list) +(map (-> (x) (+ x 1)) (1 2 3)) ; => (2 3 4) + +; Reduce +(reduce + (.. 1 5)) +; equivalent to +((+ (+ (+ 1 2) 3) 4) 5) + +; Note: map and reduce don't have shortcuts + +; `slice` or `\` is just like JavaScript's .slice() +; But do note, it takes the list as the first argument, not the last. +(slice (.. 1 5) 2) ; => (3 4 5) +(\ (.. 0 100) -5) ; => (96 97 98 99 100) + +; `append` or `<<` is self expanatory +(append 4 (1 2 3)) ; => (1 2 3 4) +(<< "bar" ("foo")) ; => ("foo" "bar") + +; Length is self explanatory. +(length (1 2 3)) ; => 3 +(_ "foobar") ; => 6 + +;;;;;;;;;;;;;;; +; Haskell fluff + +; First item in list +(head (1 2 3)) ; => 1 +; List from second to last elements in list +(tail (1 2 3)) ; => (2 3) +; Last item in list +(last (1 2 3)) ; => 3 +; Reverse of `tail` +(init (1 2 3)) ; => (1 2) +; List from first to specified elements in list +(take 1 (1 2 3 4)) ; (1 2) +; Reverse of `take` +(drop 1 (1 2 3 4)) ; (3 4) +; Lowest value in list +(min (1 2 3 4)) ; 1 +; Highest value in list +(max (1 2 3 4)) ; 4 +; If value is in list or object +(elem 1 (1 2 3)) ; true +(elem "foo" {"foo":"bar"}) ; true +(elem "bar" {"foo":"bar"}) ; false +; Reverse list order +(reverse (1 2 3 4)) ; => (4 3 2 1) +; If value is even or odd +(even 1) ; => false +(odd 1) ; => true +; Split string into list of strings by whitespace +(words "foobar nachos cheese") ; => ("foobar" "nachos" "cheese") +; Join list of strings together. +(unwords ("foo" "bar")) ; => "foobar" +(pred 21) ; => 20 +(succ 20) ; => 21 +``` + +For more info, check out the [repo](http://github.com/L8D/whip) diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown new file mode 100755 index 00000000..b4bff8fc --- /dev/null +++ b/zh-cn/c-cn.html.markdown @@ -0,0 +1,395 @@ +--- +language: c +filename: learnc-cn.c +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Chenbo Li", "http://binarythink.net/"] +lang: zh-cn +--- + +C语言在今天仍然是高性能计算的主要选择。 + +C大概是大多数程序员用到的最接近底层的语言了,但是C语言本身不仅可以用来提升程序运行的速度 +注意看看C语言的文档,你就会知道C语言在内存管理方面的强大也是其他语言无法比拟的。 + +```c +// 用“//”来实现单行注释 + +/* +多行注释是这个样子的 +*/ + +// 用#include来导入头文件 +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// 函数的标签(signature)应该放在.h文件中,并且引入到程序顶部 +// 也可以直接放到你的.c文件的最上面 +void function_1(); +void function_2(); + +// c程序的入口是一个返回值为int型的函数,名字叫做main +int main() { + +// 用printf来实现标准输出,这种输出也可以用格式来控制 +// %d 代表一个整数, \n 代表一个新行 +printf("%d\n", 0); // => 输出 0 +// 所有的语句都要以分号结束 + +/////////////////////////////////////// +// 类型 +/////////////////////////////////////// + +// 在使用变量之前我们必须先声明它们。 +// 变量在声明时需要指明其类型,而类型能够告诉系统这个变量所占用的空间 + +// int型(整型)变量一般占用4个字节 +int x_int = 0; + +// short型(短整型)变量一般占用2个字节 +short x_short = 0; + +// char型(字符型)变量会占用1个字节 +char x_char = 0; +char y_char = 'y'; // 字符变量的字面值需要用单引号包住 + +// long型(长整型)一般需要4个字节到8个字节; 而long long型则至少需要8个字节(64位) + +long x_long = 0; +long long x_long_long = 0; + +// float一般是用32位表示的浮点数字 +float x_float = 0.0; + +// double一般是用64位表示的浮点数字 +double x_double = 0.0; + +// 整数类型也可以有无符号的类型表示。这样这些变量就无法表示负数 +// 但是无符号整数所能表示的范围就可以比原来的整数大一些 + +unsigned char ux_char; +unsigned short ux_short; +unsigned int ux_int; +unsigned long long ux_long_long; + +// char类型一定会占用1个字节,但是其他的类型却会因具体机器的不同而各异 +// sizeof(T) 可以返回T类型在运行的机器上占用多少个字节 +// 这样你的代码就可以在各处正确运行了 +// 比如 +printf("%lu\n", sizeof(int)); // => 4 (字长为4的机器上) + +// 数组必须要在开始被初始化为特定的长度 +char my_char_array[20]; // 这个数组占据 1 * 20 = 20 个字节 +int my_int_array[20]; // 这个数组占据 4 * 20 = 80 个字节 + // (这里我们假设字长为4) + + +// 可以用下面的方法把数组初始化为0: +char my_array[20] = {0}; + +// 对数组任意存取就像其他语言的方式 -- 其实是其他的语言像C +my_array[0]; // => 0 + +// 数组是可变的,其实就是内存的映射! +my_array[1] = 2; +printf("%d\n", my_array[1]); // => 2 + +// 字符串就是以 NUL (0x00) 这个字符结尾的字符数组, +// 这个字符可以用'\0'来表示. +// (在字符串字面值中我们不必输入这个字符,编译器会自动添加的) +char a_string[20] = "This is a string"; +printf("%s\n", a_string); // %s 可以对字符串进行格式化 + +/* +也许你会注意到 a_string 实际上只有16个字节长. +第17个字节是一个空字符(NUL) +而第18, 19 和 20 个字符的值是不确定的。 +*/ + +printf("%d\n", a_string[16]); // => 0 + +/////////////////////////////////////// +// 操作符 +/////////////////////////////////////// + +int i1 = 1, i2 = 2; // 多个变量声明的简写 +float f1 = 1.0, f2 = 2.0; + +// 算数运算 +i1 + i2; // => 3 +i2 - i1; // => 1 +i2 * i1; // => 2 +i1 / i2; // => 0 (0.5 会被化整为 0) + +f1 / f2; // => 0.5, 也许会有很小的误差 + +// 取余运算 +11 % 3; // => 2 + +// 比较操作符我们也很熟悉, 但是有一点,C中没有布尔类型 +// 而是用整形替代 +// 0 就是 false, 其他的就是 true. (比较操作符的返回值则仅有0和1) +3 == 2; // => 0 (false) +3 != 2; // => 1 (true) +3 > 2; // => 1 +3 < 2; // => 0 +2 <= 2; // => 1 +2 >= 2; // => 1 + +// 逻辑运算符需要作用于整数 +!3; // => 0 (非) +!0; // => 1 +1 && 1; // => 1 (且) +0 && 1; // => 0 +0 || 1; // => 1 (或) +0 || 0; // => 0 + +// 位运算 +~0x0F; // => 0xF0 (取反) +0x0F & 0xF0; // => 0x00 (和) +0x0F | 0xF0; // => 0xFF (或) +0x04 ^ 0x0F; // => 0x0B (异或) +0x01 << 1; // => 0x02 (左移1位) +0x02 >> 1; // => 0x01 (右移1位) + +/////////////////////////////////////// +// 控制结构 +/////////////////////////////////////// + +if (0) { + printf("I am never run\n"); +} else if (0) { + printf("I am also never run\n"); +} else { + printf("I print\n"); +} + +// While循环 +int ii = 0; +while (ii < 10) { + printf("%d, ", ii++); // ii++ 在取值过后自增 +} // => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +int kk = 0; +do { + printf("%d, ", kk); +} while (++kk < 10); // ++kk 先自增,在被取值 +// => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +// For 循环 +int jj; +for (jj=0; jj < 10; jj++) { + printf("%d, ", jj); +} // => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + +printf("\n"); + +/////////////////////////////////////// +// 类型转换 +/////////////////////////////////////// + +// 在C中每个变量都有类型,你可以将变量的类型进行转换 + +int x_hex = 0x01; // 可以用16进制赋值 + +// 在类型转换时,数字本身的值会被保留下来 +printf("%d\n", x_hex); // => 输出 1 +printf("%d\n", (short) x_hex); // => 输出 1 +printf("%d\n", (char) x_hex); // => 输出 1 + +// 类型转换时可能会造成溢出,而且不会抛出警告 +printf("%d\n", (char) 257); // => 1 (char的最大值为255) + +// 整数型和浮点型可以互相转换 +printf("%f\n", (float)100); // %f 表示单精度浮点 +printf("%lf\n", (double)100); // %lf 表示双精度浮点 +printf("%d\n", (char)100.0); + +/////////////////////////////////////// +// 指针 +/////////////////////////////////////// + +// 指针变量是用来储存内存地址的变量 +// 指针变量的定义也会告诉你指向的地址的变量的类型 +// 你也可以得到某个变量的地址,并对它们进行操作 + +int x = 0; +printf("%p\n", &x); // 用 & 来获取变量的地址 +// (%p 表示一个指针) +// => 输出某个内存地址 + +// 指针类型在定义是需要以*结束 +int* px; // px是一个指向int型的指针 +px = &x; // 把x的地址保存到px中 +printf("%p\n", px); // => 输出内存中的某个地址 + +// 要得到某个指针指向的内容的值,可以在指针前加一个*来取得(去引用) +printf("%d\n", *px); // => 输出 0, 即x的值 + +// 你也可以改变指针所指向的值 +// 此时你需要在*运算符后添加一个括号,因为++比*的优先级更高 +(*px)++; // 把px所指向的值增加2 +printf("%d\n", *px); // => 输出 1 +printf("%d\n", x); // => 输出 1 + +int x_array[20]; // 数组是分配一系列连续空间的常用方式 +int xx; +for (xx=0; xx<20; xx++) { + x_array[xx] = 20 - xx; +} // 初始化 x_array 为 20, 19, 18,... 2, 1 + +// 生命一个变量为指向整型的指针类型,并初始化为指向x_array +int* x_ptr = x_array; +// x_ptr现在指向了数组的第一个元素(即整数20). + +// 事实上数组本身就是指向它的第一个元素的指针 +printf("%d\n", *(x_ptr)); // => 输出 20 +printf("%d\n", x_array[0]); // => 输出 20 + +// 指针的增减多少是依据它本身的类型而定的 +printf("%d\n", *(x_ptr + 1)); // => 输出 19 +printf("%d\n", x_array[1]); // => 输出 19 + +// 你也可以通过标准库函数malloc来实现动态分配 +// 这个函数接受一个代表容量的参数 +// 系统会从堆区分配指定容量字节大小的空间 +int* my_ptr = (int*) malloc(sizeof(int) * 20); +for (xx=0; xx<20; xx++) { + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx 也可以 +} // 初始化内存为 20, 19, 18, 17... 2, 1 (as ints) + +// 如果对一些未分配的内存取值则会得到未知的结果 +printf("%d\n", *(my_ptr + 21)); // => 谁知道会输出什么 + +// 当你通过malloc得到一块区域后,你需要释放它 +// 否则没人能够再次使用这块内存,直到程序结束为止 +free(my_ptr); + +// 字符串通常是字符数组,但是经常用字符指针表示 +// 指针: +char* my_str = "This is my very own string"; + +printf("%c\n", *my_str); // => 'T' + +function_1(); +} // main函数结束 + +/////////////////////////////////////// +// 函数 +/////////////////////////////////////// + +// 函数声明语法: +// <返回值类型> <函数名称>(<参数>) + +int add_two_ints(int x1, int x2){ + return x1 + x2; // 用return来返回一个值 +} + +/* +函数是按值传递的, 但是你可以通过传递参数来传递引用,这样函数就可以更改值 + +例子:字符串本身翻转 +*/ + +// 类型为void的函数没有返回值 +void str_reverse(char* str_in){ + char tmp; + int ii=0, len = strlen(str_in); // Strlen 是C标准库函数 + for(ii=0; ii<len/2; ii++){ + tmp = str_in[ii]; + str_in[ii] = str_in[len - ii - 1]; // 从倒数第ii个开始 + str_in[len - ii - 1] = tmp; + } +} + +/* +char c[] = "This is a test."; +str_reverse(c); +printf("%s\n", c); // => ".tset a si sihT" +*/ + +/////////////////////////////////////// +// 用户自定义类型和结构 +/////////////////////////////////////// + +// Typedefs可以创建类型别名 +typedef int my_type; +my_type my_type_var = 0; + +// 结构是一系列数据的集合 +struct rectangle { + int width; + int height; +}; + + +void function_1(){ + + struct rectangle my_rec; + + // 通过 . 来访问结构中的数据 + my_rec.width = 10; + my_rec.height = 20; + + // 你也可以声明指向结构体的指针 + struct rectangle* my_rec_ptr = &my_rec; + + // 通过取值来改变结构体的成员... + (*my_rec_ptr).width = 30; + + // ... 或者用 -> 操作符作为简写 + my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; +} + +// 你也可以用typedef来给一个结构体起一个别名 +typedef struct rectangle rect; + +int area(rect r){ + return r.width * r.height; +} + +/////////////////////////////////////// +// 函数指针 +/////////////////////////////////////// +/* +在运行时,函数本身也被存放到某块内存区域当中 +函数指针就像其他指针一样, 但却可以被用来直接调用函数, +并且可以被四处传递(就像回调函数那样) +但是,定义的语法有可能在一开始会有些误解 + +例子:通过指针调用str_reverse +*/ +void str_reverse_through_pointer(char * str_in) { + // 定义一个函数指针 f. + void (*f)(char *); // 签名一定要与目标函数相同 + f = &str_reverse; // 将函数的地址在运行时赋给指针 + (*f)(str_in); // 通过指针调用函数 + // f(str_in); // 等价于这种调用方式 +} + +/* +只要函数签名是正确的,任何时候都能将正确的函数赋给某个函数指针 +为了可读性和简洁性,函数指针经常和typedef搭配使用: +*/ + +typedef void (*my_fnp_type)(char *); + +// 实际声明函数指针会这么用: +// ... +// my_fnp_type f; + +``` + +## 更多阅读 + +最好找一本 [K&R, aka "The C Programming Language", “C程序设计语言”](https://en.wikipedia.org/wiki/The_C_Programming_Language) + +其他一些比较好的资源 [Learn C the hard way](http://c.learncodethehardway.org/book/) + +除了这些,多多Google吧 diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown new file mode 100644 index 00000000..6a6562bc --- /dev/null +++ b/zh-cn/dart-cn.html.markdown @@ -0,0 +1,499 @@ +--- +language: dart +lang: zh-cn +filename: learndart-cn.dart +contributors: + - ["Joao Pedrosa", "https://github.com/jpedrosa/"] +translators: + - ["Guokai Han", "https://github.com/hanguokai/"] +--- + +Dart 是编程语言王国的新人。 +它借鉴了许多其他主流语言,并且不会偏离它的兄弟语言 JavaScript 太多。 +就像 JavaScript 一样,Dart 的目标是提供良好的浏览器集成。 + +Dart 最有争议的特性必然是它的可选类型。 + +```javascript +import "dart:collection"; +import "dart:math" as DM; + +// 欢迎进入15分钟的 Dart 学习。 http://www.dartlang.org/ +// 这是一个可实际执行的向导。你可以用 Dart 运行它 +// 或者在线执行! 可以把代码复制/粘贴到这个网站。 http://try.dartlang.org/ + +// 函数声明和方法声明看起来一样。 +// 函数声明可以嵌套。声明使用这种 name() {} 的形式, +// 或者 name() => 单行表达式; 的形式。 +// 右箭头的声明形式会隐式地返回表达式的结果。 +example1() { + example1nested1() { + example1nested2() => print("Example1 nested 1 nested 2"); + example1nested2(); + } + example1nested1(); +} + +// 匿名函数没有函数名。 +example2() { + example2nested1(fn) { + fn(); + } + example2nested1(() => print("Example2 nested 1")); +} + +// 当声明函数类型的参数的时候,声明中可以包含 +// 函数参数需要的参数,指定所需的参数名即可。 +example3() { + example3nested1(fn(informSomething)) { + fn("Example3 nested 1"); + } + example3planB(fn) { // 或者不声明函数参数的参数 + fn("Example3 plan B"); + } + example3nested1((s) => print(s)); + example3planB((s) => print(s)); +} + +// 函数有可以访问到外层变量的闭包。 +var example4Something = "Example4 nested 1"; +example4() { + example4nested1(fn(informSomething)) { + fn(example4Something); + } + example4nested1((s) => print(s)); +} + +// 下面这个包含 sayIt 方法的类声明,同样有一个可以访问外层变量的闭包, +// 就像前面的函数一样。 +var example5method = "Example5 sayIt"; +class Example5Class { + sayIt() { + print(example5method); + } +} +example5() { + // 创建一个 Example5Class 类的匿名实例, + // 并调用它的 sayIt 方法。 + new Example5Class().sayIt(); +} + +// 类的声明使用这种形式 class name { [classBody] }. +// classBody 中可以包含实例方法和变量, +// 还可以包含类方法和变量。 +class Example6Class { + var example6InstanceVariable = "Example6 instance variable"; + sayIt() { + print(example6InstanceVariable); + } +} +example6() { + new Example6Class().sayIt(); +} + +// 类方法和变量使用 static 关键词声明。 +class Example7Class { + static var example7ClassVariable = "Example7 class variable"; + static sayItFromClass() { + print(example7ClassVariable); + } + sayItFromInstance() { + print(example7ClassVariable); + } +} +example7() { + Example7Class.sayItFromClass(); + new Example7Class().sayItFromInstance(); +} + +// 字面量非常方便,但是对于在函数/方法的外层的字面量有一个限制, +// 类的外层或外面的字面量必需是常量。 +// 字符串和数字默认是常量。 +// 但是 array 和 map 不是。他们需要用 "const" 声明为常量。 +var example8A = const ["Example8 const array"], + example8M = const {"someKey": "Example8 const map"}; +example8() { + print(example8A[0]); + print(example8M["someKey"]); +} + +// Dart 中的循环使用标准的 for () {} 或 while () {} 的形式, +// 以及更加现代的 for (.. in ..) {} 的形式, 或者 +// 以 forEach 开头并具有许多特性支持的函数回调的形式。 +var example9A = const ["a", "b"]; +example9() { + for (var i = 0; i < example9A.length; i++) { + print("Example9 for loop '${example9A[i]}'"); + } + var i = 0; + while (i < example9A.length) { + print("Example9 while loop '${example9A[i]}'"); + i++; + } + for (var e in example9A) { + print("Example9 for-in loop '${e}'"); + } + example9A.forEach((e) => print("Example9 forEach loop '${e}'")); +} + +// 遍历字符串中的每个字符或者提取其子串。 +var example10S = "ab"; +example10() { + for (var i = 0; i < example10S.length; i++) { + print("Example10 String character loop '${example10S[i]}'"); + } + for (var i = 0; i < example10S.length; i++) { + print("Example10 substring loop '${example10S.substring(i, i + 1)}'"); + } +} + +// 支持两种数字格式 int 和 double 。 +example11() { + var i = 1 + 320, d = 3.2 + 0.01; + print("Example11 int ${i}"); + print("Example11 double ${d}"); +} + +// DateTime 提供了日期/时间的算法。 +example12() { + var now = new DateTime.now(); + print("Example12 now '${now}'"); + now = now.add(new Duration(days: 1)); + print("Example12 tomorrow '${now}'"); +} + +// 支持正则表达式。 +example13() { + var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); + match(s) { + if (re.hasMatch(s)) { + print("Example13 regexp matches '${s}'"); + } else { + print("Example13 regexp doesn't match '${s}'"); + } + } + match(s1); + match(s2); +} + +// 布尔表达式必需被解析为 true 或 false, +// 因为不支持隐式转换。 +example14() { + var v = true; + if (v) { + print("Example14 value is true"); + } + v = null; + try { + if (v) { + // 不会执行 + } else { + // 不会执行 + } + } catch (e) { + print("Example14 null value causes an exception: '${e}'"); + } +} + +// try/catch/finally 和 throw 语句用于异常处理。 +// throw 语句可以使用任何对象作为参数。 +example15() { + try { + try { + throw "Some unexpected error."; + } catch (e) { + print("Example15 an exception: '${e}'"); + throw e; // Re-throw + } + } catch (e) { + print("Example15 catch exception being re-thrown: '${e}'"); + } finally { + print("Example15 Still run finally"); + } +} + +// 要想有效地动态创建长字符串, +// 应该使用 StringBuffer。 或者 join 一个字符串的数组。 +example16() { + var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; + for (e in a) { sb.write(e); } + print("Example16 dynamic string created with " + "StringBuffer '${sb.toString()}'"); + print("Example16 join string array '${a.join()}'"); +} + +// 字符串连接只需让相邻的字符串字面量挨着, +// 不需要额外的操作符。 +example17() { + print("Example17 " + "concatenate " + "strings " + "just like that"); +} + +// 字符串使用单引号或双引号做分隔符,二者并没有实际的差异。 +// 这种灵活性可以很好地避免内容中需要转义分隔符的情况。 +// 例如,字符串内容里的 HTML 属性使用了双引号。 +example18() { + print('Example18 <a href="etc">' + "Don't can't I'm Etc" + '</a>'); +} + +// 用三个单引号或三个双引号表示的字符串 +// 可以跨越多行,并且包含行分隔符。 +example19() { + print('''Example19 <a href="etc"> +Example19 Don't can't I'm Etc +Example19 </a>'''); +} + +// 字符串可以使用 $ 字符插入内容。 +// 使用 $ { [expression] } 的形式,表达式的值会被插入到字符串中。 +// $ 跟着一个变量名会插入变量的值。 +// 如果要在字符串中插入 $ ,可以使用 \$ 的转义形式代替。 +example20() { + var s1 = "'\${s}'", s2 = "'\$s'"; + print("Example20 \$ interpolation ${s1} or $s2 works."); +} + +// 可选类型允许作为 API 的标注,并且可以辅助 IDE, +// 这样 IDE 可以更好地提供重构、自动完成和错误检测功能。 +// 目前为止我们还没有声明任何类型,并且程序运行地很好。 +// 事实上,类型在运行时会被忽略。 +// 类型甚至可以是错的,并且程序依然可以执行, +// 好像和类型完全无关一样。 +// 有一个运行时参数可以让程序进入检查模式,它会在运行时检查类型错误。 +// 这在开发时很有用,但是由于增加了额外的检查会使程序变慢, +// 因此应该避免在部署时使用。 +class Example21 { + List<String> _names; + Example21() { + _names = ["a", "b"]; + } + List<String> get names => _names; + set names(List<String> list) { + _names = list; + } + int get length => _names.length; + void add(String name) { + _names.add(name); + } +} +void example21() { + Example21 o = new Example21(); + o.add("c"); + print("Example21 names '${o.names}' and length '${o.length}'"); + o.names = ["d", "e"]; + print("Example21 names '${o.names}' and length '${o.length}'"); +} + +// 类的继承形式是 class name extends AnotherClassName {} 。 +class Example22A { + var _name = "Some Name!"; + get name => _name; +} +class Example22B extends Example22A {} +example22() { + var o = new Example22B(); + print("Example22 class inheritance '${o.name}'"); +} + +// 类也可以使用 mixin 的形式 : +// class name extends SomeClass with AnotherClassName {}. +// 必需继承某个类才能 mixin 另一个类。 +// 当前 mixin 的模板类不能有构造函数。 +// Mixin 主要是用来和辅助的类共享方法的, +// 这样单一继承就不会影响代码复用。 +// Mixin 声明在类定义的 "with" 关键词后面。 +class Example23A {} +class Example23Utils { + addTwo(n1, n2) { + return n1 + n2; + } +} +class Example23B extends Example23A with Example23Utils { + addThree(n1, n2, n3) { + return addTwo(n1, n2) + n3; + } +} +example23() { + var o = new Example23B(), r1 = o.addThree(1, 2, 3), + r2 = o.addTwo(1, 2); + print("Example23 addThree(1, 2, 3) results in '${r1}'"); + print("Example23 addTwo(1, 2) results in '${r2}'"); +} + +// 类的构造函数名和类名相同,形式为 +// SomeClass() : super() {}, 其中 ": super()" 的部分是可选的, +// 它用来传递参数给父类的构造函数。 +class Example24A { + var _value; + Example24A({value: "someValue"}) { + _value = value; + } + get value => _value; +} +class Example24B extends Example24A { + Example24B({value: "someOtherValue"}) : super(value: value); +} +example24() { + var o1 = new Example24B(), + o2 = new Example24B(value: "evenMore"); + print("Example24 calling super during constructor '${o1.value}'"); + print("Example24 calling super during constructor '${o2.value}'"); +} + +// 对于简单的类,有一种设置构造函数参数的快捷方式。 +// 只需要使用 this.parameterName 的前缀, +// 它就会把参数设置为同名的实例变量。 +class Example25 { + var value, anotherValue; + Example25({this.value, this.anotherValue}); +} +example25() { + var o = new Example25(value: "a", anotherValue: "b"); + print("Example25 shortcut for constructor '${o.value}' and " + "'${o.anotherValue}'"); +} + +// 可以在大括号 {} 中声明命名参数。 +// 大括号 {} 中声明的参数的顺序是随意的。 +// 在中括号 [] 中声明的参数也是可选的。 +example26() { + var _name, _surname, _email; + setConfig1({name, surname}) { + _name = name; + _surname = surname; + } + setConfig2(name, [surname, email]) { + _name = name; + _surname = surname; + _email = email; + } + setConfig1(surname: "Doe", name: "John"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); + setConfig2("Mary", "Jane"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); +} + +// 使用 final 声明的变量只能被设置一次。 +// 在类里面,final 实例变量可以通过常量的构造函数参数设置。 +class Example27 { + final color1, color2; + // 更灵活一点的方法是在冒号 : 后面设置 final 实例变量。 + Example27({this.color1, color2}) : color2 = color2; +} +example27() { + final color = "orange", o = new Example27(color1: "lilac", color2: "white"); + print("Example27 color is '${color}'"); + print("Example27 color is '${o.color1}' and '${o.color2}'"); +} + +// 要导入一个库,使用 import "libraryPath" 的形式,或者如果要导入的是 +// 核心库使用 import "dart:libraryName" 。还有一个称为 "pub" 的包管理工具, +// 它使用 import "package:packageName" 的约定形式。 +// 看下这个文件顶部的 import "dart:collection"; 语句。 +// 导入语句必需在其它代码声明之前出现。IterableBase 来自于 dart:collection 。 +class Example28 extends IterableBase { + var names; + Example28() { + names = ["a", "b"]; + } + get iterator => names.iterator; +} +example28() { + var o = new Example28(); + o.forEach((name) => print("Example28 '${name}'")); +} + +// 对于控制流语句,我们有: +// * 必需带 break 的标准 switch 语句 +// * if-else 和三元操作符 ..?..:.. +// * 闭包和匿名函数 +// * break, continue 和 return 语句 +example29() { + var v = true ? 30 : 60; + switch (v) { + case 30: + print("Example29 switch statement"); + break; + } + if (v < 30) { + } else if (v > 30) { + } else { + print("Example29 if-else statement"); + } + callItForMe(fn()) { + return fn(); + } + rand() { + v = new DM.Random().nextInt(50); + return v; + } + while (true) { + print("Example29 callItForMe(rand) '${callItForMe(rand)}'"); + if (v != 30) { + break; + } else { + continue; + } + // 不会到这里。 + } +} + +// 解析 int,把 double 转成 int,或者使用 ~/ 操作符在除法计算时仅保留整数位。 +// 让我们也来场猜数游戏吧。 +example30() { + var gn, tooHigh = false, + n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0; + top = top ~/ 6; + gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive + print("Example30 Guess a number between 0 and ${top}"); + guessNumber(i) { + if (n == gn) { + print("Example30 Guessed right! The number is ${gn}"); + } else { + tooHigh = n > gn; + print("Example30 Number ${n} is too " + "${tooHigh ? 'high' : 'low'}. Try again"); + } + return n == gn; + } + n = (top - bottom) ~/ 2; + while (!guessNumber(n)) { + if (tooHigh) { + top = n - 1; + } else { + bottom = n + 1; + } + n = bottom + ((top - bottom) ~/ 2); + } +} + +// 程序的唯一入口点是 main 函数。 +// 在程序开始执行 main 函数之前,不期望执行任何外层代码。 +// 这样可以帮助程序更快地加载,甚至仅惰性加载程序启动时需要的部分。 +main() { + print("Learn Dart in 15 minutes!"); + [example1, example2, example3, example4, example5, example6, example7, + example8, example9, example10, example11, example12, example13, example14, + example15, example16, example17, example18, example19, example20, + example21, example22, example23, example24, example25, example26, + example27, example28, example29, example30 + ].forEach((ef) => ef()); +} + +``` + +## 延伸阅读 + +Dart 有一个综合性网站。它涵盖了 API 参考、入门向导、文章以及更多, +还包括一个有用的在线试用 Dart 页面。 +http://www.dartlang.org/ +http://try.dartlang.org/ + + + diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown new file mode 100755 index 00000000..d303c2e8 --- /dev/null +++ b/zh-cn/elisp-cn.html.markdown @@ -0,0 +1,344 @@ +---
+language: elisp
+contributors:
+ - ["Bastien Guerry", "http://bzg.fr"]
+translators:
+ - ["Chenbo Li", "http://binarythink.net"]
+filename: learn-emacs-lisp-zh.el
+lang: zh-cn
+---
+
+```scheme
+;; 15分钟学会Emacs Lisp (v0.2a)
+;;(作者:bzg,https://github.com/bzg
+;; 译者:lichenbo,http://douban.com/people/lichenbo)
+;;
+;; 请先阅读Peter Norvig的一篇好文:
+;; http://norvig.com/21-days.html
+;; (译者注:中文版请见http://blog.youxu.info/21-days/)
+;;
+;; 之后安装GNU Emacs 24.3:
+;;
+;; Debian: apt-get install emacs (视具体发行版而定)
+;; MacOSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
+;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
+;;
+;; 更多信息可以在这里找到:
+;; http://www.gnu.org/software/emacs/#Obtaining
+
+;; 很重要的警告:
+;;
+;; 按照这个教程来学习并不会对你的电脑有任何损坏
+;; 除非你自己在学习的过程中愤怒地把它砸了
+;; 如果出现了这种情况,我不会承担任何责任
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 打开emacs
+;;
+;; 按'q'消除欢迎界面
+;;
+;; 现在请注意窗口底部的那一个灰色长条
+;;
+;; "*scratch*" 是你现在编辑界面的名字。
+;; 这个编辑界面叫做一个"buffer"。
+;;
+;; 每当你打开Emacs时,都会默认打开这个scratch buffer
+;; 此时你并没有在编辑任何文件,而是在编辑一个buffer
+;; 之后你可以将这个buffer保存到一个文件中。
+;;
+;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
+;;
+;; Emacs在每个buffer中都有一组内置的命令
+;; 而当你激活某种特定的模式时,就可以使用相应的命令
+;; 这里我们使用`lisp-interaction-mode',
+;; 这样我们就可以使用内置的Emacs Lisp(以下简称Elisp)命令了。
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 分号是注释开始的标志
+;;
+;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
+(+ 2 2)
+
+;; 这个s式的意思是 "对2进行加2操作".
+
+;; s式周围有括号,而且也可以嵌套:
+(+ 2 (+ 1 1))
+
+;; 一个s式可以包含原子符号或者其他s式
+;; 在上面的例子中,1和2是原子符号
+;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
+
+;; 在 `lisp-interaction-mode' 中你可以计算s式.
+;; 把光标移到闭括号后,之后按下ctrl+j(以后简写为'C-j')
+
+(+ 3 (+ 1 2))
+;; ^ 光标放到这里
+;; 按下`C-j' 就会输出 6
+
+;; `C-j' 会在buffer中插入当前运算的结果
+
+;; 而`C-xC-e' 则会在emacs最底部显示结果,也就是被称作"minibuffer"的区域
+;; 为了避免把我们的buffer填满无用的结果,我们以后会一直用`C-xC-e'
+
+;; `setq' 可以将一个值赋给一个变量
+(setq my-name "Bastien")
+;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
+
+;; `insert' 会在光标处插入字符串:
+(insert "Hello!")
+;; `C-xC-e' 输出 "Hello!"
+
+;; 在这里我们只传给了insert一个参数"Hello!", 但是
+;; 我们也可以传给它更多的参数,比如2个:
+
+(insert "Hello" " world!")
+;; `C-xC-e' 输出 "Hello world!"
+
+;; 你也可以用变量名来代替字符串
+(insert "Hello, I am " my-name)
+;; `C-xC-e' 输出 "Hello, I am Bastien"
+
+;; 你可以把s式嵌入函数中
+(defun hello () (insert "Hello, I am " my-name))
+;; `C-xC-e' 输出 hello
+
+;; 现在执行这个函数
+(hello)
+;; `C-xC-e' 输出 Hello, I am Bastien
+
+;; 函数中空括号的意思是我们不需要接受任何参数
+;; 但是我们不能一直总是用my-name这个变量
+;; 所以我们现在使我们的函数接受一个叫做"name"的参数
+
+(defun hello (name) (insert "Hello " name))
+;; `C-xC-e' 输出 hello
+
+;; 现在我们调用这个函数,并且将"you"作为参数传递
+
+(hello "you")
+;; `C-xC-e' 输出 "Hello you"
+
+;; 成功!
+
+;; 现在我们可以休息一下
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
+
+(switch-to-buffer-other-window "*test*")
+;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
+
+;; 用鼠标单击上面的buffer就会使光标移回。
+;; 或者你可以使用 `C-xo' 是的光标跳到另一个窗口中
+
+;; 你可以用 `progn'命令将s式结合起来:
+(progn
+ (switch-to-buffer-other-window "*test*")
+ (hello "you"))
+;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
+
+;; 现在为了简洁,我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
+
+;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
+
+;; 清除当前buffer也是常用操作之一:
+(progn
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ (hello "there"))
+
+;; 也可以回到其他的窗口中
+(progn
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ (hello "you")
+ (other-window 1))
+
+;; 你可以用 `let' 将一个值和一个局部变量绑定:
+(let ((local-name "you"))
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ (hello local-name)
+ (other-window 1))
+
+;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
+
+;; 格式化字符串的方法:
+(format "Hello %s!\n" "visitor")
+
+;; %s 是字符串占位符,这里被"visitor"替代.
+;; \n 是换行符。
+
+;; 现在我们用格式化的方法再重写一下我们的函数:
+(defun hello (name)
+ (insert (format "Hello %s!\n" name)))
+
+(hello "you")
+
+;; 我们再用`let'新建另一个函数:
+(defun greeting (name)
+ (let ((your-name "Bastien"))
+ (insert (format "Hello %s!\n\nI am %s."
+ name ; the argument of the function
+ your-name ; the let-bound variable "Bastien"
+ ))))
+
+;; 之后执行:
+(greeting "you")
+
+;; 有些函数可以和用户交互:
+(read-from-minibuffer "Enter your name: ")
+
+;; 这个函数会返回在执行时用户输入的信息
+
+;; 现在我们让`greeting'函数显示你的名字:
+(defun greeting (from-name)
+ (let ((your-name (read-from-minibuffer "Enter your name: ")))
+ (insert (format "Hello!\n\nI am %s and you are %s."
+ from-name ; the argument of the function
+ your-name ; the let-bound var, entered at prompt
+ ))))
+
+(greeting "Bastien")
+
+;; 我们让结果在另一个窗口中显示:
+(defun greeting (from-name)
+ (let ((your-name (read-from-minibuffer "Enter your name: ")))
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ (insert (format "Hello %s!\n\nI am %s." your-name from-name))
+ (other-window 1)))
+
+;; 测试一下:
+(greeting "Bastien")
+
+;; 第二节结束,休息一下吧。
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 我们将一些名字存到列表中;
+(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
+
+;; 用 `car'来取得第一个名字:
+(car list-of-names)
+
+;; 用 `cdr'取得剩下的名字:
+(cdr list-of-names)
+
+;; 用 `push'把名字添加到列表的开头:
+(push "Stephanie" list-of-names)
+
+;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
+;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car')
+;; 但还有一些却是有的 (比如 `push').
+
+;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
+(mapcar 'hello list-of-names)
+
+;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
+(defun greeting ()
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ (mapcar 'hello list-of-names)
+ (other-window 1))
+
+(greeting)
+
+;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
+;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
+
+;; 现在我们对显示的buffer中的内容进行一些更改:
+
+(defun replace-hello-by-bonjour ()
+ (switch-to-buffer-other-window "*test*")
+ (goto-char (point-min))
+ (while (search-forward "Hello")
+ (replace-match "Bonjour"))
+ (other-window 1))
+
+;; (goto-char (point-min)) 将光标移到buffer的开始
+;; (search-forward "Hello") 查找字符串"Hello"
+;; (while x y) 当x返回某个值时执行y这个s式
+;; 当x返回`nil' (空), 退出循环
+
+(replace-hello-by-bonjour)
+
+;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
+
+;; 你也会得到以下错误提示: "Search failed: Hello".
+;;
+;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
+;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
+
+;; (search-forward "Hello" nil t) 可以达到这个要求:
+
+;; `nil' 参数的意思是 : 查找并不限于某个范围内
+;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
+
+;; 在下面的函数中,我们用到了s式,并且不给出任何错误提示:
+
+(defun hello-to-bonjour ()
+ (switch-to-buffer-other-window "*test*")
+ (erase-buffer)
+ ;; 为`list-of-names'中的每个名字调用hello
+ (mapcar 'hello list-of-names)
+ (goto-char (point-min))
+ ;; 将"Hello" 替换为"Bonjour"
+ (while (search-forward "Hello" nil t)
+ (replace-match "Bonjour"))
+ (other-window 1))
+
+(hello-to-bonjour)
+
+;; 给这些名字上个色:
+
+(defun boldify-names ()
+ (switch-to-buffer-other-window "*test*")
+ (goto-char (point-min))
+ (while (re-search-forward "Bonjour \\(.+\\)!" nil t)
+ (add-text-properties (match-beginning 1)
+ (match-end 1)
+ (list 'face 'bold)))
+ (other-window 1))
+
+;; 这个函数使用了 `re-search-forward':
+;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
+
+;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
+;; 字符串 "Bonjour ", 之后跟着
+;; 一组 | \\( ... \\) 结构
+;; 任意字符 | . 的含义
+;; 有可能重复的 | + 的含义
+;; 之后跟着 "!" 这个字符串
+
+;; 准备好了?试试看。
+
+(boldify-names)
+
+;; `add-text-properties' 可以添加文字属性, 比如文字样式
+
+;; 好的,我们成功了!
+
+;; 如果你想对一个变量或者函数有更多的了解:
+;;
+;; C-h v 变量 回车
+;; C-h f 函数 回车
+;;
+;; 阅读Emacs Lisp官方文档:
+;;
+;; C-h i m elisp 回车
+;;
+;; 在线阅读Emacs Lisp文档:
+;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
+
+;; 感谢以下同学的建议和反馈:
+;; - Wes Hardaker
+;; - notbob
+;; - Kevin Montuori
+;; - Arne Babenhauserheide
+;; - Alan Schmitt
+```
+
diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown new file mode 100755 index 00000000..86952eba --- /dev/null +++ b/zh-cn/git-cn.html.markdown @@ -0,0 +1,374 @@ +--- +category: tool +tool: git +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +lang: zh-cn +--- + +Git是一个分布式版本控制及源代码管理工具 + +Git可以为你的项目保存若干快照,以此来对整个项目进行版本管理 + +## 版本 + +### 什么是版本控制 + +版本控制系统就是根据时间来记录一个或多个文件的更改情况的系统。 + +### 集中式版本控制 VS 分布式版本控制 + +* 集中式版本控制的主要功能为同步,跟踪以及备份文件 +* 分布式版本控制则更注重共享更改。每一次更改都有唯一的标识 +* 分布式系统没有预定的结构。你也可以用git很轻松的实现SVN风格的集中式系统控制 + +[更多信息](http://git-scm.com/book/en/Getting-Started-About-Version-Control) + +### 为什么要使用Git + +* 可以离线工作 +* 和他人协同工作变得简单 +* 分支很轻松 +* 合并很容易 +* Git系统速度快,也很灵活 + +## Git 架构 + + +### 版本库 + +一系列文件,目录,历史记录,提交记录和头指针。 +可以把它视作每个源代码文件都带有历史记录属性数据结构 + +一个Git版本库包括一个 .git 目录和其工作目录 + +### .git 目录(版本库的一部分) + +.git 目录包含所有的配置、日志、分支信息、头指针等 +[详细列表](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### 工作目录 (版本库的一部分) + +版本库中的目录和文件,可以看做就是你工作时的目录 + +### 索引(.git 目录) + +索引就是git中的 staging 区. 可以算作是把你的工作目录与Git版本库分割开的一层 +这使得开发者能够更灵活的决定要将要在版本库中添加什么内容 + +### 提交 + +一个 git 提交就是一组更改或者对工作目录操作的快照 +比如你添加了5个文件,删除了2个文件,那么这些变化就会被写入一个提交比如你添加了5个文件,删除了2个文件,那么这些变化就会被写入一个提交中 +而这个提交之后也可以被决定是否推送到另一个版本库中 + +### 分支 + +分支其实就是一个指向你最后一次的提交的指针 +当你提交时,这个指针就会自动指向最新的提交 + +### 头指针 与 头(.git 文件夹的作用) + +头指针是一个指向当前分支的指针,一个版本库只有一个当前活动的头指针 +而头则可以指向版本库中任意一个提交,每个版本库也可以有多个头 + +### 其他形象化解释 + +* [给计算机科学家的解释](http://eagain.net/articles/git-for-computer-scientists/) +* [给设计师的解释](http://hoth.entp.com/output/git_for_designers.html) + + +## 命令 + + +### 初始化 + +创建一个新的git版本库。这个版本库的配置、存储等信息会被保存到.git文件夹中 + +```bash +$ git init +``` + +### 配置 + +更改设置。可以是版本库的设置,也可以是系统的或全局的 + + +```bash +# 输出、设置基本的全局变量 +$ git config --global user.email +$ git config --global user.name + +$ git config --global user.email "MyEmail@Zoho.com" +$ git config --global user.name "My Name" +``` + +[关于git的更多设置](http://git-scm.com/docs/git-config) + +### 帮助 + +git内置了对命令非常详细的解释,可以供我们快速查阅 + +```bash +# 查找可用命令 +$ git help + +# 查找所有可用命令 +$ git help -a + +# 在文档当中查找特定的命令 +# git help <命令> +$ git help add +$ git help commit +$ git help init +``` + +### 状态 + +显示索引文件(也就是当前工作空间)和当前的头指针指向的提交的不同 + + +```bash +# 显示分支,为跟踪文件,更改和其他不同 +$ git status + +# 查看其他的git status的用法 +$ git help status +``` + +### 添加 + +添加文件到当前工作空间中。如果你不使用 `git add` 将文件添加进去, +那么这些文件也不会添加到之后的提交之中 + +```bash +# 添加一个文件 +$ git add HelloWorld.java + +# 添加一个子目录中的文件 +$ git add /path/to/file/HelloWorld.c + +# 支持正则表达式 +$ git add ./*.java +``` + +### 分支 + +管理分支,可以通过下列命令对分支进行增删改查 + +```bash +# 查看所有的分支和远程分支 +$ git branch -a + +# 创建一个新的分支 +$ git branch myNewBranch + +# 删除一个分支 +$ git branch -d myBranch + +# 重命名分支 +# git branch -m <旧名称> <新名称> +$ git branch -m myBranchName myNewBranchName + +# 编辑分支的介绍 +$ git branch myBranchName --edit-description +``` + +### 检出 + +将当前工作空间更新到索引所标识的或者某一特定的工作空间 + +```bash +# 检出一个版本库,默认将更新到master分支 +$ git checkout +# 检出到一个特定的分支 +$ git checkout branchName +# 新建一个分支,并且切换过去,相当于"git branch <名字>; git checkout <名字>" +$ git checkout -b newBranch +``` + +### clone + +这个命令就是将一个版本库拷贝到另一个目录中,同时也将 +分支都拷贝到新的版本库中。这样就可以在新的版本库中提交到远程分支 + +```bash +# clone learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git +``` + +### commit + +将当前索引的更改保存为一个新的提交,这个提交包括用户做出的更改与信息 + +```bash +# 提交时附带提交信息 +$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" +``` + +### diff + +显示当前工作空间和提交的不同 + +```bash +# 显示工作目录和索引的不同 +$ git diff + +# 显示索引和最近一次提交的不同 +$ git diff --cached + +# 显示宫缩目录和最近一次提交的不同 +$ git diff HEAD +``` + +### grep + +可以在版本库中快速查找 + +可选配置: + +```bash +# 感谢Travis Jeffery提供的以下用法: +# 在搜索结果中显示行号 +$ git config --global grep.lineNumber true + +# 是搜索结果可读性更好 +$ git config --global alias.g "grep --break --heading --line-number" +``` + +```bash +# 在所有的java中查找variableName +$ git grep 'variableName' -- '*.java' + +# 搜索包含 "arrayListName" 和, "add" 或 "remove" 的所有行 +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +更多的例子可以查看: +[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) + +### log + +显示这个版本库的所有提交 + +```bash +# 显示所有提交 +$ git log + +# 显示某几条提交信息 +$ git log -n 10 + +# 仅显示合并提交 +$ git log --merges +``` + +### merge + +合并就是将外部的提交合并到自己的分支中 + +```bash +# 将其他分支合并到当前分支 +$ git merge branchName + +# 在合并时创建一个新的合并后的提交 +$ git merge --no-ff branchName +``` + +### mv + +重命名或移动一个文件 + +```bash +# 重命名 +$ git mv HelloWorld.c HelloNewWorld.c + +# 移动 +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# 强制重命名或移动 +# 这个文件已经存在,将要覆盖掉 +$ git mv -f myFile existingFile +``` + +### pull + +从远端版本库合并到当前分支 + +```bash +# 从远端origin的master分支更新版本库 +# git pull <远端> <分支> +$ git pull origin master +``` + +### push + +把远端的版本库更新 + +```bash +# 把本地的分支更新到远端origin的master分支上 +# git push <远端> <分支> +# git push 相当于 git push origin master +$ git push origin master +``` + +### rebase (谨慎使用) + +将一个分支上所有的提交历史都应用到另一个分支上 +*不要在一个已经公开的远端分支上使用rebase*. + +```bash +# 将experimentBranch应用到master上面 +# git rebase <basebranch> <topicbranch> +$ git rebase master experimentBranch +``` + +[更多阅读](http://git-scm.com/book/en/Git-Branching-Rebasing) + +### reset (谨慎使用) + +将当前的头指针复位到一个特定的状态。这样可以使你撤销merge、pull、commits、add等 +这是个很强大的命令,但是在使用时一定要清楚其所产生的后果 + +```bash +# 使 staging 区域恢复到上次提交时的状态,不改变现在的工作目录 +$ git reset + +# 使 staging 区域恢复到上次提交时的状态,覆盖现在的工作目录 +$ git reset --hard + +# 将当前分支恢复到某次提交,不改变现在的工作目录 +# 在工作目录中所有的改变仍然存在 +$ git reset 31f2bb1 + +# 将当前分支恢复到某次提交,覆盖现在的工作目录 +# 并且删除所有未提交的改变和指定提交之后的所有提交 +$ git reset --hard 31f2bb1 +``` + +### rm + +和add相反,从工作空间中去掉某个文件爱你 + +```bash +# 移除 HelloWorld.c +$ git rm HelloWorld.c + +# 移除子目录中的文件 +$ git rm /pather/to/the/file/HelloWorld.c +``` + +## 更多阅读 + +* [tryGit - 学习Git的有趣方式](http://try.github.io/levels/1/challenges/1) + +* [git-scm - 视频教程](http://git-scm.com/videos) + +* [git-scm - 文档](http://git-scm.com/docs) + +* [Atlassian Git - 教程与工作流程](https://www.atlassian.com/git/) + +* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) + +* [GitGuys](http://www.gitguys.com/) diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown new file mode 100755 index 00000000..8d51f144 --- /dev/null +++ b/zh-cn/haskell-cn.html.markdown @@ -0,0 +1,407 @@ +--- +language: haskell +filename: learn-haskell-zh.hs +contributors: + - ["Adit Bhargava", "http://adit.io"] +translators: + - ["Peiyong Lin", ""] +lang: zh-cn +--- + +Haskell 被设计成一种实用的纯函数式编程语言。它因为 monads 及其类型系统而出名,但是我回归到它本身因为。Haskell 使得编程对于我而言是一种真正的快乐。 + +```haskell +-- 单行注释以两个破折号开头 +{- 多行注释像这样 + 被一个闭合的块包围 +-} + +---------------------------------------------------- +-- 1. 简单的数据类型和操作符 +---------------------------------------------------- + +-- 你有数字 +3 -- 3 +-- 数学计算就像你所期待的那样 +1 + 1 -- 2 +8 - 1 -- 7 +10 * 2 -- 20 +35 / 5 -- 7.0 + +-- 默认除法不是整除 +35 / 4 -- 8.75 + +-- 整除 +35 `div` 4 -- 8 + +-- 布尔值也简单 +True +False + +-- 布尔操作 +not True -- False +not False -- True +1 == 1 -- True +1 /= 1 -- False +1 < 10 -- True + +-- 在上述的例子中,`not` 是一个接受一个值的函数。 +-- Haskell 不需要括号来调用函数。。。所有的参数 +-- 都只是在函数名之后列出来。因此,通常的函数调用模式是: +-- func arg1 arg2 arg3... +-- 查看关于函数的章节以获得如何写你自己的函数的相关信息。 + +-- 字符串和字符 +"This is a string." +'a' -- 字符 +'对于字符串你不能使用单引号。' -- 错误! + +-- 连结字符串 +"Hello " ++ "world!" -- "Hello world!" + +-- 一个字符串是一系列字符 +"This is a string" !! 0 -- 'T' + + +---------------------------------------------------- +-- 列表和元组 +---------------------------------------------------- + +-- 一个列表中的每一个元素都必须是相同的类型 +-- 下面两个列表一样 +[1, 2, 3, 4, 5] +[1..5] + +-- 在 Haskell 你可以拥有含有无限元素的列表 +[1..] -- 一个含有所有自然数的列表 + +-- 因为 Haskell 有“懒惰计算”,所以无限元素的列表可以正常运作。这意味着 +-- Haskell 可以只在它需要的时候计算。所以你可以请求 +-- 列表中的第1000个元素,Haskell 会返回给你 + +[1..] !! 999 -- 1000 + +-- Haskell 计算了列表中 1 - 1000 个元素。。。但是 +-- 这个无限元素的列表中剩下的元素还不存在! Haskell 不会 +-- 真正地计算它们知道它需要。 + +<FS>- 连接两个列表 +[1..5] ++ [6..10] + +-- 往列表头增加元素 +0:[1..5] -- [0, 1, 2, 3, 4, 5] + +-- 列表中的下标 +[0..] !! 5 -- 5 + +-- 更多列表操作 +head [1..5] -- 1 +tail [1..5] -- [2, 3, 4, 5] +init [1..5] -- [1, 2, 3, 4] +last [1..5] -- 5 + +-- 列表推导 +[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] + +-- 附带条件 +[x*2 | x <-[1..5], x*2 > 4] -- [6, 8, 10] + +-- 元组中的每一个元素可以是不同类型的,但是一个元组 +-- 的长度是固定的 +-- 一个元组 +("haskell", 1) + +-- 获取元组中的元素 +fst ("haskell", 1) -- "haskell" +snd ("haskell", 1) -- 1 + +---------------------------------------------------- +-- 3. 函数 +---------------------------------------------------- +-- 一个接受两个变量的简单函数 +add a b = a + b + +-- 注意,如果你使用 ghci (Hakell 解释器) +-- 你将需要使用 `let`,也就是 +-- let add a b = a + b + +-- 使用函数 +add 1 2 -- 3 + +-- 你也可以把函数放置在两个参数之间 +-- 附带倒引号: +1 `add` 2 -- 3 + +-- 你也可以定义不带字符的函数!这使得 +-- 你定义自己的操作符!这里有一个操作符 +-- 来做整除 +(//) a b = a `div` b +35 // 4 -- 8 + +-- 守卫:一个简单的方法在函数里做分支 +fib x + | x < 2 = x + | otherwise = fib (x - 1) + fib (x - 2) + +-- 模式匹配是类型的。这里有三种不同的 fib +-- 定义。Haskell 将自动调用第一个 +-- 匹配值的模式的函数。 +fib 1 = 1 +fib 2 = 2 +fib x = fib (x - 1) + fib (x - 2) + +-- 元组的模式匹配: +foo (x, y) = (x + 1, y + 2) + +-- 列表的模式匹配。这里 `x` 是列表中第一个元素, +-- 并且 `xs` 是列表剩余的部分。我们可以写 +-- 自己的 map 函数: +myMap func [] = [] +myMap func (x:xs) = func x:(myMap func xs) + +-- 编写出来的匿名函数带有一个反斜杠,后面跟着 +-- 所有的参数。 +myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] + +-- 使用 fold (在一些语言称为`inject`)随着一个匿名的 +-- 函数。foldl1 意味着左折叠(fold left), 并且使用列表中第一个值 +-- 作为累加器的初始化值。 +foldl1 (\acc x -> acc + x) [1..5] -- 15 + +---------------------------------------------------- +-- 4. 更多的函数 +---------------------------------------------------- + +-- 柯里化(currying):如果你不传递函数中所有的参数, +-- 它就变成“柯里化的”。这意味着,它返回一个接受剩余参数的函数。 + +add a b = a + b +foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数 +foo 5 -- 15 + +-- 另外一种方式去做同样的事 +foo = (+10) +foo 5 -- 15 + +-- 函数组合 +-- (.) 函数把其它函数链接到一起 +-- 举个列子,这里 foo 是一个接受一个值的函数。它对接受的值加 10, +-- 并对结果乘以 5,之后返回最后的值。 +foo = (*5) . (+10) + +-- (5 + 10) * 5 = 75 +foo 5 -- 75 + +-- 修复优先级 +-- Haskell 有另外一个函数称为 `$`。它改变优先级 +-- 使得其左侧的每一个操作先计算然后应用到 +-- 右侧的每一个操作。你可以使用 `.` 和 `$` 来除去很多 +-- 括号: + +-- before +(even (fib 7)) -- true + +-- after +even . fib $ 7 -- true + +---------------------------------------------------- +-- 5. 类型签名 +---------------------------------------------------- + +-- Haskell 有一个非常强壮的类型系统,一切都有一个类型签名。 + +-- 一些基本的类型: +5 :: Integer +"hello" :: String +True :: Bool + +-- 函数也有类型。 +-- `not` 接受一个布尔型返回一个布尔型: +-- not :: Bool -> Bool + +-- 这是接受两个参数的函数: +-- add :: Integer -> Integer -> Integer + +-- 当你定义一个值,在其上写明它的类型是一个好实践: +double :: Integer -> Integer +double x = x * 2 + +---------------------------------------------------- +-- 6. 控制流和 If 语句 +---------------------------------------------------- + +-- if 语句 +haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome" + +-- if 语句也可以有多行,缩进是很重要的 +haskell = if 1 == 1 + then "awesome" + else "awful" + +-- case 语句:这里是你可以怎样去解析命令行参数 +case args of + "help" -> printHelp + "start" -> startProgram + _ -> putStrLn "bad args" + +-- Haskell 没有循环因为它使用递归取代之。 +-- map 应用一个函数到一个数组中的每一个元素 + +map (*2) [1..5] -- [2, 4, 6, 8, 10] + +-- 你可以使用 map 来编写 for 函数 +for array func = map func array + +-- 然后使用它 +for [0..5] $ \i -> show i + +-- 我们也可以像这样写: +for [0..5] show + +-- 你可以使用 foldl 或者 foldr 来分解列表 +-- foldl <fn> <initial value> <list> +foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 + +-- 这和下面是一样的 +(2 * (2 * (2 * 4 + 1) + 2) + 3) + +-- foldl 是左手边的,foldr 是右手边的- +foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 + +-- 这和下面是一样的 +(2 * 3 + (2 * 2 + (2 * 1 + 4))) + +---------------------------------------------------- +-- 7. 数据类型 +---------------------------------------------------- + +-- 这里展示在 Haskell 中你怎样编写自己的数据类型 + +data Color = Red | Blue | Green + +-- 现在你可以在函数中使用它: + + +say :: Color -> String +say Red = "You are Red!" +say Blue = "You are Blue!" +say Green = "You are Green!" + +-- 你的数据类型也可以有参数: + +data Maybe a = Nothing | Just a + +-- 类型 Maybe 的所有 +Just "hello" -- of type `Maybe String` +Just 1 -- of type `Maybe Int` +Nothing -- of type `Maybe a` for any `a` + +---------------------------------------------------- +-- 8. Haskell IO +---------------------------------------------------- + +-- 虽然在没有解释 monads 的情况下 IO不能被完全地解释, +-- 着手解释到位并不难。 + +-- 当一个 Haskell 程序被执行,函数 `main` 就被调用。 +-- 它必须返回一个类型 `IO ()` 的值。举个列子: + +main :: IO () +main = putStrLn $ "Hello, sky! " ++ (say Blue) +-- putStrLn has type String -> IO () + +-- 如果你能实现你的程序依照函数从 String 到 String,那样编写 IO 是最简单的。 +-- 函数 +-- interact :: (String -> String) -> IO () +-- 输入一些文本,在其上运行一个函数,并打印出输出 + +countLines :: String -> String +countLines = show . length . lines + +main' = interact countLines + +-- 你可以考虑一个 `IO()` 类型的值,当做一系列计算机所完成的动作的代表, +-- 就像一个以命令式语言编写的计算机程序。我们可以使用 `do` 符号来把动作链接到一起。 +-- 举个列子: + +sayHello :: IO () +sayHello = do + putStrLn "What is your name?" + name <- getLine -- this gets a line and gives it the name "input" + putStrLn $ "Hello, " ++ name + +-- 练习:编写只读取一行输入的 `interact` + +-- 然而,`sayHello` 中的代码将不会被执行。唯一被执行的动作是 `main` 的值。 +-- 为了运行 `sayHello`,注释上面 `main` 的定义,并代替它: +-- main = sayHello + +-- 让我们来更好地理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: +-- getLine :: IO String +-- 你可以考虑一个 `IO a` 类型的值,代表一个当被执行的时候 +-- 将产生一个 `a` 类型的值的计算机程序(除了它所做的任何事之外)。我们可以保存和重用这个值通过 `<-`。 +-- 我们也可以写自己的 `IO String` 类型的动作: + +action :: IO String +action = do + putStrLn "This is a line. Duh" + input1 <- getLine + input2 <- getLine + -- The type of the `do` statement is that of its last line. + -- `return` is not a keyword, but merely a function + return (input1 ++ "\n" ++ input2) -- return :: String -> IO String + +-- 我们可以使用这个动作就像我们使用 `getLine`: + +main'' = do + putStrLn "I will echo two lines!" + result <- action + putStrLn result + putStrLn "This was all, folks!" + +-- `IO` 类型是一个 "monad" 的例子。Haskell 使用一个 monad 来做 IO的方式允许它是一门纯函数式语言。 +-- 任何与外界交互的函数(也就是 IO) 都在它的类型签名处做一个 `IO` 标志 +-- 着让我们推出 什么样的函数是“纯洁的”(不与外界交互,不修改状态) 和 什么样的函数不是 “纯洁的” + +-- 这是一个强有力的特征,因为并发地运行纯函数是简单的;因此,Haskell 中并发是非常简单的。 + + +---------------------------------------------------- +-- 9. The Haskell REPL +---------------------------------------------------- + +-- 键入 `ghci` 开始 repl。 +-- 现在你可以键入 Haskell 代码。 +-- 任何新值都需要通过 `let` 来创建: + +let foo = 5 + +-- 你可以查看任何值的类型,通过命令 `:t`: + +>:t foo +foo :: Integer + +-- 你也可以运行任何 `IO ()`类型的动作 + +> sayHello +What is your name? +Friend! +Hello, Friend! + +``` + +还有很多关于 Haskell,包括类型类和 monads。这些是使得编码 Haskell 是如此有趣的主意。我用一个最后的 Haskell 例子来结束:一个 Haskell 的快排实现: + +```haskell +qsort [] = [] +qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater + where lesser = filter (< p) xs + greater = filter (>= p) xs +``` + +安装 Haskell 是简单的。你可以从[这里](http://www.haskell.org/platform/)获得它。 + +你可以从优秀的 +[Learn you a Haskell](http://learnyouahaskell.com/) 或者 +[Real World Haskell](http://book.realworldhaskell.org/) +找到优雅不少的入门介绍。 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown new file mode 100755 index 00000000..9422ac2f --- /dev/null +++ b/zh-cn/java-cn.html.markdown @@ -0,0 +1,405 @@ +--- +name: java +category: language +language: java +lang: zh-cn +filename: LearnJava-zh.java +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +--- + +Java是一个通用的程序语言, 包含并发, 基于类的面向对象等特性 +[阅读更多](http://docs.oracle.com/javase/tutorial/java/index.html) + +```java +// 单行注释 +/* +多行注释 +*/ +/** +JavaDoc(Java文档)注释是这样的。可以用来描述类和类的属性。 +*/ + +// 导入 java.util中的 ArrayList 类 +import java.util.ArrayList; +// 导入 java.security 包中的所有类 +import java.security.*; + +// 每个 .java 文件都包含一个public类,这个类的名字必须和这个文件名一致。 +public class LearnJava { + + // 每个程序都需要有一个main函数作为入口 + public static void main (String[] args) { + + // 使用 System.out.println 来输出到标准输出 + System.out.println("Hello World!"); + System.out.println( + "Integer: " + 10 + + " Double: " + 3.14 + + " Boolean: " + true); + + // 如果要在输出后不自动换行,可以使用System.out.print方法。 + System.out.print("Hello "); + System.out.print("World"); + + + /////////////////////////////////////// + // 类型与变量 + /////////////////////////////////////// + + // 用 <type> <name> 来声明变量 + // 字节类型 - 8位补码表示 + // (-128 <= 字节 <= 127) + byte fooByte = 100; + + // 短整型 - 16位补码表示 + // (-32,768 <= 短整型 <= 32,767) + short fooShort = 10000; + + // 整型 - 32位补码表示 + // (-2,147,483,648 <= 整型 <= 2,147,483,647) + int fooInt = 1; + + // 长整型 - 64位补码表示 + // (-9,223,372,036,854,775,808 <= 长整型 <= 9,223,372,036,854,775,807) + long fooLong = 100000L; + // L可以用来表示一个数字是长整型的。 + // 其他的数字都默认为整型。 + + // 注意:Java中没有无符号类型 + + // 浮点型 - 即 IEEE 754 规定的32位单精度浮点类型 + float fooFloat = 234.5f; + // f用来表示一个数字是浮点型的。 + // 否则会被默认当做是双精度浮点型。 + + // 双精度浮点型 - 即 IEEE 754 规定的64位双精度浮点类型 + double fooDouble = 123.4; + + // 布尔类型 - true 与 false + boolean fooBoolean = true; + boolean barBoolean = false; + + // 字符类型 - 16位 Unicode编码字符 + char fooChar = 'A'; + + // 用 final 可以使一个常量不可更改 + final int HOURS_I_WORK_PER_WEEK = 9001; + + // 字符串 + String fooString = "My String Is Here!"; + + // \n 代表一个新的换行 + String barString = "Printing on a new line?\nNo Problem!"; + // \t 代表一个新的制表符 + String bazString = "Do you want to add a tab?\tNo Problem!"; + System.out.println(fooString); + System.out.println(barString); + System.out.println(bazString); + + // 数组 + // 数组在声明时大小必须已经确定 + // 数组的声明格式: + //<数据类型> [] <变量名> = new <数据类型>[<数组大小>]; + int [] intArray = new int[10]; + String [] stringArray = new String[1]; + boolean [] booleanArray = new boolean[100]; + + // 声明并初始化数组也可以这样: + int [] y = {9000, 1000, 1337}; + + // 随机访问数组中的元素 + System.out.println("intArray @ 0: " + intArray[0]); + + // 数组下标从0开始并且可以被更改 + intArray[1] = 1; + System.out.println("intArray @ 1: " + intArray[1]); // => 1 + + // 其他数据类型 + // ArrayLists - 类似于数组,但是功能更多,并且大小也可以改变 + // LinkedLists + // Maps + // HashMaps + + /////////////////////////////////////// + // 操作符 + /////////////////////////////////////// + System.out.println("\n->Operators"); + + int i1 = 1, i2 = 2; // 多重声明可以简化 + + // 算数运算 + System.out.println("1+2 = " + (i1 + i2)); // => 3 + System.out.println("2-1 = " + (i2 - i1)); // => 1 + System.out.println("2*1 = " + (i2 * i1)); // => 2 + System.out.println("1/2 = " + (i1 / i2)); // => 0 (0.5 truncated down) + + // 取余 + System.out.println("11%3 = "+(11 % 3)); // => 2 + + // 比较操作符 + System.out.println("3 == 2? " + (3 == 2)); // => false + System.out.println("3 != 2? " + (3 != 2)); // => true + System.out.println("3 > 2? " + (3 > 2)); // => true + System.out.println("3 < 2? " + (3 < 2)); // => false + System.out.println("2 <= 2? " + (2 <= 2)); // => true + System.out.println("2 >= 2? " + (2 >= 2)); // => true + + // 位运算操作符 + /* + ~ 补 + << 带符号左移 + >> 带符号右移 + >>> 无符号右移 + & 和 + ^ 异或 + | 相容或 + */ + + // 自增 + int i = 0; + System.out.println("\n->Inc/Dec-rementation"); + System.out.println(i++); //i = 1 后自增 + System.out.println(++i); //i = 2 前自增 + System.out.println(i--); //i = 1 后自减 + System.out.println(--i); //i = 0 前自减 + + /////////////////////////////////////// + // 控制结构 + /////////////////////////////////////// + System.out.println("\n->Control Structures"); + + // If语句和C的类似 + int j = 10; + if (j == 10){ + System.out.println("I get printed"); + } else if (j > 10) { + System.out.println("I don't"); + } else { + System.out.println("I also don't"); + } + + // While循环 + int fooWhile = 0; + while(fooWhile < 100) + { + //System.out.println(fooWhile); + //增加计数器 + //遍历99次, fooWhile 0->99 + fooWhile++; + } + System.out.println("fooWhile Value: " + fooWhile); + + // Do While循环 + int fooDoWhile = 0; + do + { + //System.out.println(fooDoWhile); + //增加计数器 + //遍历99次, fooDoWhile 0->99 + fooDoWhile++; + }while(fooDoWhile < 100); + System.out.println("fooDoWhile Value: " + fooDoWhile); + + // For 循环 + int fooFor; + //for 循环结构 => for(<起始语句>; <循环进行的条件>; <步长>) + for(fooFor=0; fooFor<10; fooFor++){ + //System.out.println(fooFor); + //遍历 10 次, fooFor 0->9 + } + System.out.println("fooFor Value: " + fooFor); + + // Switch Case 语句 + // switch可以用来处理 byte, short, char, 和 int 数据类型 + // 也可以用来处理枚举类型,字符串类,和原始数据类型的包装类: + // Character, Byte, Short, 和 Integer + int month = 3; + String monthString; + switch (month){ + case 1: + monthString = "January"; + break; + case 2: + monthString = "February"; + break; + case 3: + monthString = "March"; + break; + default: + monthString = "Some other month"; + break; + } + System.out.println("Switch Case Result: " + monthString); + + + /////////////////////////////////////// + // 类型转换 + /////////////////////////////////////// + + // 数据转换 + + // 将字符串转换为整型 + Integer.parseInt("123");//返回整数123 + + // 将整型转换为字符串 + Integer.toString(123);//返回字符串"123" + + // 其他的数据也可以进行互相转换: + // Double + // Long + // String + + // 类型转换 + // 你也可以对java对象进行类型转换, 但其中会牵扯到很多概念 + // 在这里可以查看更详细的信息: + // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html + + + /////////////////////////////////////// + // 类与函数 + /////////////////////////////////////// + + System.out.println("\n->Classes & Functions"); + + // (Bicycle类定义如下) + + // 用new来实例化一个类 + Bicycle trek = new Bicycle(); + + // 调用对象的方法 + trek.speedUp(3); // 需用getter和setter方法 + trek.setCadence(100); + + // toString 可以把对象转换为字符串 + System.out.println("trek info: " + trek.toString()); + + } // main 方法结束 +} // LearnJava 类结束 + + +// 你也可以把其他的非public类放入到.java文件中 + + +// 类定义的语法: +// <public/private/protected> class <类名>{ +// //成员变量, 构造函数, 函数 +// //Java中函数被称作方法 +// } + +class Bicycle { + + // Bicycle 类的成员变量和方法 + public int cadence; // Public: 任意位置均可访问 + private int speed; // Private: 只在同类中可以访问 + protected int gear; // Protected: 可以在同类与子类中可以访问 + String name; // default: 可以在包内中可以访问 + + // 构造函数是初始化一个对象的方式 + // 以下是一个默认构造函数 + public Bi450635425cycle() { + gear = 1; + cadence = 50; + speed = 5; + name = "Bontrager"; + } + + // 一下是一个含有参数的构造函数 + public Bicycle(int startCadence, int startSpeed, int startGear, String name) { + this.gear = startGear; + this.cadence = startCadence; + this.speed = startSpeed; + this.name = name; + } + + // 函数语法: + // <public/private/protected> <返回值类型> <函数名称>(<参数列表>) + + // Java类中经常会用getter和setter来对成员变量进行操作 + + // 方法声明的语法: + // <作用域> <返回值类型> <方法名>(<参数列表>) + public int getCadence() { + retur450635425n cadence; + } + + // void返450635425回值函数没有返回值 + public void setCadence(int newValue) { + cadence = newValue; + } + + public void setGear(int newValue) { + gear = newValue; + } + + public void speedUp(int increment) { + speed += increment; + } + + public void slowDown(int decrement) { + speed -= decrement; + } + + public void setName(String newName) { + name = newName; + } + + public String getName() { + return name; + } + + //返回对象属性的方法 + @Override + public String toString() { + return "gear: " + gear + + " cadence: " + cadence + + " speed: " + speed + + " name: " + name; + } +} // Bicycle 类结束 + +// PennyFarthing 是 Bicycle 的子类 +class PennyFarthing extends Bicycle { + // (Penny Farthings 是前轮很大的 Bicycle, 并且没有齿轮) + + public PennyFarthing(int startCadence, int startSpeed){ + // 通过super调用父类的构造函数 + super(startCadence, startSpeed, 0, "PennyFarthing"); + } + + // 你可以用@注释来表示需要重载的方法 + // 了解更多的注释使用方法,可以访问下面的地址: + // http://docs.oracle.com/javase/tutorial/java/annotations/ + @Override + public void setGear(int gear) { + gear = 0; + } + +} + +``` + +## 更多阅读 + +下面的链接只是为了便于大家理解这些主题而给出的,对于具体的例子请大家自行Google + +其他主题: + +* [Java 官方教程](http://docs.oracle.com/javase/tutorial/index.html) + +* [Java 访问修饰符](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) + +* [面向对象程序设计概念](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): + * [继承](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) + * [多态](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) + * [抽象](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) + +* [异常](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) + +* [接口](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) + +* [泛型](http://docs.oracle.com/javase/tutorial/java/generics/index.html) + +* [Java代码规范](http://www.oracle.com/technetwork/java/codeconv-138413.html) diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown new file mode 100755 index 00000000..89fc256e --- /dev/null +++ b/zh-cn/javascript-cn.html.markdown @@ -0,0 +1,419 @@ +--- +language: javascript +category: language +name: javascript +filename: javascript-zh.js +contributors: + - ["Adam Brenecki", "http://adam.brenecki.id.au"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +lang: zh-cn +--- + +Javascript于1995年由网景公司的Brendan Eich发明。 +最初发明的目的是作为一个简单的网站脚本语言,来作为 +复杂网站应用java的补充。但由于javascript和网站结合度很高 +所以javascript逐渐变得比java在前端更为流行了。 + +JavaScript 不仅仅只可以用于浏览器, 也可用于 Node.js 等后台环境。 + +很欢迎来自您的反馈,您可以通过下列方式联系到我: +[@adambrenecki](https://twitter.com/adambrenecki), 或者 +[adam@brenecki.id.au](mailto:adam@brenecki.id.au). + +```js +// 注释方式和C很像,这是单行注释 +/* 这是多行 + 注释 */ + +// 语句可以以分号结束 +doStuff(); + +// ... 但是分号也可以省略,每当遇到一个新行时,分号会自动插入 +doStuff() + +// 我们在这里会去掉分号,但是否添加最后的分号取决于你个人的习惯 +// 及你所在团队的编程风格 + +/////////////////////////////////// +// 1. 数字、字符串与操作符 + +// Javascript 只有一种数字类型 (即 64位 IEEE 754 双精度浮点). +3 // = 3 +1.5 // = 1.5 + +// 所有基本的算数运算 +1 + 1 // = 2 +8 - 1 // = 7 +10 * 2 // = 20 +35 / 5 // = 7 + +// 包括无法整除的除法 +5 / 2 // = 2.5 + +// 位运算也和其他语言一样。当你对浮点数进行位运算时, +// 浮点数会转换为至多 32 位的无符号整数 +1 << 2 // = 4 + +// 括号可以决定优先级 +(1 + 3) * 2 // = 8 + +// 有三种非数字的数字类型 +Infinity // 1/0 的结果 +-Infinity // -1/0 的结果 +NaN // 0/0 的结果 + +// 也有布尔值 +true +false + +// 可以通过单引号或双引号来构造字符串 +'abc' +"Hello, world" + +// 用!来取非 +!true // = false +!false // = true + +// 相等 == +1 == 1 // = true +2 == 1 // = false + +// 不等 != +1 != 1 // = false +2 != 1 // = true + +// 更多的比较操作符 +1 < 10 // = true +1 > 10 // = false +2 <= 2 // = true +2 >= 2 // = true + +// 字符串用+连接 +"Hello " + "world!" // = "Hello world!" + +// 字符串也可以用 < 、> 来比较 +"a" < "b" // = true + +// 比较时会进行类型转换... +"5" == 5 // = true + +// ...除非你是用 === +"5" === 5 // = false + +// 你可以用charAt来得到字符串中的字符 +"This is a string".charAt(0) + +// 还有两个特殊的值:null和undefined +null // 用来表示刻意设置成的空值 +undefined // 用来表示还没有设置的值 + +// null, undefined, NaN, 0 和 "" 都是假的(false),其他的都视作逻辑真 +// 注意 0 是逻辑假而 "0"是逻辑真, 尽管 0 == "0". + +/////////////////////////////////// +// 2. 变量、数组和对象 + +// 变量需要用 var 这个关键字声明. Javascript是动态类型语言 +// 所以你在声明时无需指定类型。 赋值需要用 = +var someVar = 5 + +// 如果你在声明时没有加var关键字,你也不会得到错误 +someOtherVar = 10 + +// ...但是此时这个变量就会拥有全局的作用域,而非当前作用域 + +// 没有被赋值的变量都会返回undefined这个值 +var someThirdVar // = undefined + +// 对变量进行数学运算有一些简写法 +someVar += 5 // 等价于 someVar = someVar + 5; someVar 现在是 10 +someVar *= 10 // 现在 someVar 是 100 + +// 自增和自减也有简写 +someVar++ // someVar 是 101 +someVar-- // 回到 100 + +// 数组是任意类型组成的有序列表 +var myArray = ["Hello", 45, true] + +// 数组的元素可以用方括号下标来访问 +// 数组的索引从0开始 +myArray[1] // = 45 + +// javascript中的对象相当于其他语言中的字典或映射:是键-值的集合 +{key1: "Hello", key2: "World"} + +// 键是字符串,但是引号也并非是必须的,如果键本身是合法的js标识符 +// 而值则可以是任意类型的值 +var myObj = {myKey: "myValue", "my other key": 4} + +// 对象的访问可以通过下标 +myObj["my other key"] // = 4 + +// ... 或者也可以用 . ,如果属性是合法的标识符 +myObj.myKey // = "myValue" + +// 对象是可变的,键和值也可以被更改或增加 +myObj.myThirdKey = true + +// 如果你想要访问一个还没有被定义的属性,那么会返回undefined +myObj.myFourthKey // = undefined + +/////////////////////////////////// +// 3. 逻辑与控制结构 + +// if语句和其他语言中一样 +var count = 1 +if (count == 3){ + // count 是 3 时执行 +} else if (count == 4) { + // count 是 4 时执行 +} else { + // 其他情况下执行 +} + +// while循环 +while (true) { + // 无限循环 +} + +// Do-while 和 While 循环很像 ,但前者会至少执行一次 +var input +do { + input = getInput() +} while (!isValid(input)) + +// for循环和C、Java中的一样 +// 初始化; 继续执行的条件; 遍历后执行. +for (var i = 0; i < 5; i++){ + // 遍历5次 +} + +// && 是逻辑与, || 是逻辑或 +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear" +} +if (colour == "red" || colour == "blue"){ + // colour是red或者blue时执行 +} + +// && 和 || 是“短路”语句,在初始化值时会变得有用 +var name = otherName || "default" + +/////////////////////////////////// +// 4. 函数、作用域、闭包 + +// JavaScript 函数由function关键字定义 +function myFunction(thing){ + return thing.toUpperCase() +} +myFunction("foo") // = "FOO" + +// 函数也可以是匿名的: +function(thing){ + return thing.toLowerCase() +} +// (我们无法调用此函数,因为我们不知道这个函数的名字) + +// javascript中的函数也是对象,所以函数也能够赋给一个变量,并且被传递 +// 比如一个事件处理函数: +function myFunction(){ + // this code will be called in 5 seconds' time +} +setTimeout(myFunction, 5000) + +// 你甚至可以直接把一个函数写到另一个函数的参数中 + +setTimeout(function myFunction(){ + // 5秒之后会执行这里的代码 +}, 5000) + +// JavaScript 仅有函数作用于,而其他的语句则没有作用域 +if (true){ + var i = 5 +} +i // = 5 - 并非我们在其他语言中所得到的undefined + +// 这就导致了人们经常用一种叫做“即使执行匿名函数”的模式 +// 这样可以避免一些临时变量扩散到外边去 +function(){ + var temporary = 5 + // 我们可以访问一个全局对象来访问全局作用域 + // 在浏览器中是 'window' 这个对象。 + // 在Node.js中这个对象的名字可能会不同。 + window.permanent = 10 + // 或者,我们也可以把var去掉就行了 + permanent2 = 15 +}() +temporary // 抛出引用异常 +permanent // = 10 +permanent2 // = 15 + +// javascript最强大的功能之一就是闭包 +// 如果一个函数在另一个函数中定义,那么这个函数就拥有外部函数的所有访问权 +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!" + function inner(){ + alert(prompt) + } + setTimeout(inner, 5000) + // setTimeout 是异步的,所以这个函数会马上终止不会等待。 + // 然而,在5秒结束后,inner函数仍然会弹出prompt信息。 +} +sayHelloInFiveSeconds("Adam") // 会在5秒后弹出 "Hello, Adam!" + +/////////////////////////////////// +// 5. 对象、构造函数与原型 + +// 对象包含方法 +var myObj = { + myFunc: function(){ + return "Hello world!" + } +} +myObj.myFunc() // = "Hello world!" + +// 当对象中的函数被调用时,这个函数就可以通过this关键字访问这个对象 +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString + } +} +myObj.myFunc() // = "Hello world!" + +// 但这个函数访问的其实是其运行时环境,而非定义时环境 +// 所以如果函数所在的环境不在当前对象的环境中运行时,就运行不成功了 +var myFunc = myObj.myFunc +myFunc() // = undefined + +// 相应的,一个函数也可以被指定为一个对象的方法,并且用过this可以访问 +// 这个对象的成员,即使在定义时并没有绑定任何值 +var myOtherFunc = function(){ + return this.myString.toUpperCase() +} +myObj.myOtherFunc = myOtherFunc +myObj.myOtherFunc() // = "HELLO WORLD!" + +// 当你通过new关键字调用一个函数时,就会生成一个对象 +// 而对象的成员需要通过this来定义。 +// 这样的函数就叫做构造函数 + +var MyConstructor = function(){ + this.myNumber = 5 +} +myNewObj = new MyConstructor() // = {myNumber: 5} +myNewObj.myNumber // = 5 + +// 每一个js对象都有一个原型,当你要访问一个没有定义过的成员时, +// 解释器就回去找这个对象的原型 + +// 有一些JS实现会让你通过一个对象的__proto__方法访问这个原型。 +// 这虽然对理解这个对象很有用,但是这并不是标准的一部分 +// 我们之后会通过标准方式来访问原型。 +var myObj = { + myString: "Hello world!", +} +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase() + } +} +myObj.__proto__ = myPrototype +myObj.meaningOfLife // = 42 + +// This works for functions, too. +myObj.myFunc() // = "hello world!" + +// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型。 +myPrototype.__proto__ = { + myBoolean: true +} +myObj.myBoolean // = true + +// 这其中并没有对象的拷贝。每个对象的原型实际上是持有原型对象的引用 +// 这说明当我们改变对象的原型时,会影响到其他以这个原型为原型的对象 +myPrototype.meaningOfLife = 43 +myObj.meaningOfLife // = 43 + +// 我们知道 __proto__ 并非标准规定,实际上也没有办法更改已经指定好的原型。 +// 但是,我们有两种方式可以为新的对象指定原型。 + +// 第一种方式是 Object.create,这个方法是在最近才被添加到Js中的 +// 也因此并不是所有的JS实现都有这个放啊 +var myObj = Object.create(myPrototype) +myObj.meaningOfLife // = 43 + +// 第二种方式可以在任意版本中使用,不过需要通过构造函数。 +// 构造函数有一个属性prototype。但是这 *不是* 构造函数本身的函数 +// 而是通过构造函数和new关键字生成新对象时自动生成的。 +myConstructor.prototype = { + getMyNumber: function(){ + return this.myNumber + } +} +var myNewObj2 = new myConstructor() +myNewObj2.getMyNumber() // = 5 + +// 字符串和数字等内置类型也有通过构造函数来创建的包装类型 +var myNumber = 12 +var myNumberObj = new Number(12) +myNumber == myNumberObj // = true + +// 但是它们并非严格等价 +typeof(myNumber) // = 'number' +typeof(myNumberObj) // = 'object' +myNumber === myNumberObj // = false +if (0){ + // 这段代码不会执行,因为0代表假 +} +if (Number(0)){ + // 这段代码会执行,因为Number(0)代表真 +} + +// 但是,包装类型和内置类型共享一个原型 +// 这样你就可以给内置类型也增加一些功能 +String.prototype.firstCharacter = function(){ + return this.charAt(0) +} +"abc".firstCharacter() // = "a" + +// 这个技巧可以用来用老版本的javascript子集来是实现新版本js的功能 +// 这样就可以在老的浏览器中使用新功能了。 + +// 比如,我们知道Object.create并没有在所有的版本中都实现 +// 但是我们仍然可以通过这个技巧来使用 +if (Object.create === undefined){ // 如果存在则不覆盖 + Object.create = function(proto){ + // 用正确的原型来创建一个临时构造函数 + var Constructor = function(){} + Constructor.prototype = proto + // 之后用它来创建一个新的对象 + return new Constructor() + } +} +``` + +## 更多阅读 + +[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) +覆盖了这里提到的绝大多数话题,大多数只是Javascript这个语言本身。 +如果你想了解Javascript是如何在网页中被应用的,那么可以查看 +[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/) 是一个深入 +讲解所有Javascript反直觉部分的一本书 + +除了这篇文章的直接贡献者之外,这篇文章也参考了这个网站上 +Louie Dinh 的 Python 教程,以及 Mozilla开发者网络上的[JS +Tutorial](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 new file mode 100755 index 00000000..c6ebb515 --- /dev/null +++ b/zh-cn/php-cn.html.markdown @@ -0,0 +1,636 @@ +--- +language: php +contributors: + - ["Malcolm Fell", "http://emarref.net/"] + - ["Trismegiste", "https://github.com/Trismegiste"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: learnphp-zh.php +lang: zh-cn +--- + +这份教程所使用的版本是 PHP 5+. + +```php +<?php // PHP必须被包围于 <?php ? > 之中 + +// 如果你的文件中只有php代码,那么最好省略结束括号标记 + +// 这是单行注释的标志 + +# 井号也可以,但是//更常见 + +/* + 这是多行注释 +*/ + +// 使用 "echo" 或者 "print" 来输出信息到标准输出 +print('Hello '); // 输出 "Hello " 并且没有换行符 + +// () 对于echo和print是可选的 +echo "World\n"; // 输出 "World" 并且换行 +// (每个语句必须以分号结尾) + +// 在 <?php 标签之外的语句都被自动输出到标准输出 +?>Hello World Again! +<?php + + +/************************************ + * 类型与变量 + */ + +// 变量以$开始 +// 变量可以以字母或者下划线开头,后面可以跟着数字、字母和下划线 + +// 布尔值是大小写无关的 +$boolean = true; // 或 TRUE 或 True +$boolean = false; // 或 FALSE 或 False + +// 整型 +$int1 = 12; // => 12 +$int2 = -12; // => -12 +$int3 = 012; // => 10 (0开头代表八进制数) +$int4 = 0x0F; // => 15 (0x开头代表十六进制数) + +// 浮点型 (即双精度浮点型) +$float = 1.234; +$float = 1.2e3; +$float = 7E-10; + +// 算数运算 +$sum = 1 + 1; // 2 +$difference = 2 - 1; // 1 +$product = 2 * 2; // 4 +$quotient = 2 / 1; // 2 + +// 算数运算的简写 +$number = 0; +$number += 1; // $number 自增1 +echo $number++; // 输出1 (运算后自增) +echo ++$number; // 输出3 (自增后运算) +$number /= $float; // 先除后赋值给 $number + +// 字符串需要被包含在单引号之中 +$sgl_quotes = '$String'; // => '$String' + +// 如果需要在字符串中引用变量,就需要使用双引号 +$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.' + +// 特殊字符只有在双引号中有用 +$escaped = "This contains a \t tab character."; +$unescaped = 'This just contains a slash and a t: \t'; + +// 可以把变量包含在一对大括号中 +$money = "I have $${number} in the bank."; + +// 自 PHP 5.3 开始, nowdocs 可以被用作多行非计算型字符串 +$nowdoc = <<<'END' +Multi line +string +END; + +// 而Heredocs则可以用作多行计算型字符串 +$heredoc = <<<END +Multi line +$sgl_quotes +END; + +// 字符串需要用 . 来连接 +echo 'This string ' . 'is concatenated'; + + +/******************************** + * 数组 + */ + +// PHP 中的数组都是关联型数组,也就是某些语言中的哈希表或字典 + +// 在所有PHP版本中均适用: +$associative = array('One' => 1, 'Two' => 2, 'Three' => 3); + +// PHP 5.4 中引入了新的语法 +$associative = ['One' => 1, 'Two' => 2, 'Three' => 3]; + +echo $associative['One']; // 输出 1 + +// 声明为列表实际上是给每个值都分配了一个整数键(key) +$array = ['One', 'Two', 'Three']; +echo $array[0]; // => "One" + + +/******************************** + * 输出 + */ + +echo('Hello World!'); +// 输出到标准输出 +// 此时标准输出就是浏览器中的网页 + +print('Hello World!'); // 和echo相同 + +// echo和print实际上也属于这个语言本身,所以我们省略括号 +echo 'Hello World!'; +print 'Hello World!'; + +$paragraph = 'paragraph'; + +echo 100; // 直接输出标量 +echo $paragraph; // 或者输出变量 + +// 如果你配置了短标签,或者使用5.4.0及以上的版本 +// 你就可以使用简写的echo语法 +?> +<p><?= $paragraph ?></p> +<?php + +$x = 1; +$y = 2; +$x = $y; // $x 现在和 $y 的值相同 +$z = &$y; +// $z 现在持有 $y 的引用. 现在更改 $z 的值也会更改 $y 的值,反之亦然 +// 但是改变 $y 的值不会改变 $x 的值 + +echo $x; // => 2 +echo $z; // => 2 +$y = 0; +echo $x; // => 2 +echo $z; // => 0 + + +/******************************** + * 逻辑 + */ +$a = 0; +$b = '0'; +$c = '1'; +$d = '1'; + +// 如果assert的参数为假,就会抛出警告 + +// 下面的比较都为真,不管它们的类型是否匹配 +assert($a == $b); // 相等 +assert($c != $a); // 不等 +assert($c <> $a); // 另一种不等的表示 +assert($a < $c); +assert($c > $b); +assert($a <= $b); +assert($c >= $d); + +// 下面的比较只有在类型相同、值相同的情况下才为真 +assert($c === $d); +assert($a !== $d); +assert(1 == '1'); +assert(1 !== '1'); + +// 变量可以根据其使用来进行类型转换 + +$integer = 1; +echo $integer + $integer; // => 2 + +$string = '1'; +echo $string + $string; // => 2 (字符串在此时被转化为整数) + +$string = 'one'; +echo $string + $string; // => 0 +// 输出0,因为'one'这个字符串无法被转换为整数 + +// 类型转换可以将一个类型视作另一种类型 + +$boolean = (boolean) 1; // => true + +$zero = 0; +$boolean = (boolean) $zero; // => false + +// 还有一些专用的函数来进行类型转换 +$integer = 5; +$string = strval($integer); + +$var = null; // 空值 + + +/******************************** + * 控制结构 + */ + +if (true) { + print 'I get printed'; +} + +if (false) { + print 'I don\'t'; +} else { + print 'I get printed'; +} + +if (false) { + print 'Does not get printed'; +} elseif(true) { + print 'Does'; +} + +// 三目运算符 +print (false ? 'Does not get printed' : 'Does'); + +$x = 0; +if ($x === '0') { + print 'Does not print'; +} elseif($x == '1') { + print 'Does not print'; +} else { + print 'Does print'; +} + + + +// 下面的语法常用语模板中: +?> + +<?php if ($x): ?> +This is displayed if the test is truthy. +<?php else: ?> +This is displayed otherwise. +<?php endif; ?> + +<?php + +// 用switch来实现相同的逻辑 +switch ($x) { + case '0': + print 'Switch does type coercion'; + break; // 在case中必须使用一个break语句, + // 否则在执行完这个语句后会直接执行后面的语句 + case 'two': + case 'three': + // 如果$variable是 'two' 或 'three',执行这里的语句 + break; + default: + // 其他情况 +} + +// While, do...while 和 for 循环 +$i = 0; +while ($i < 5) { + echo $i++; +}; // 输出 "01234" + +echo "\n"; + +$i = 0; +do { + echo $i++; +} while ($i < 5); // 输出 "01234" + +echo "\n"; + +for ($x = 0; $x < 10; $x++) { + echo $x; +} // 输出 "0123456789" + +echo "\n"; + +$wheels = ['bicycle' => 2, 'car' => 4]; + +// Foreach 循环可以遍历数组 +foreach ($wheels as $wheel_count) { + echo $wheel_count; +} // 输出 "24" + +echo "\n"; + +// 也可以同时遍历键和值 +foreach ($wheels as $vehicle => $wheel_count) { + echo "A $vehicle has $wheel_count wheels"; +} + +echo "\n"; + +$i = 0; +while ($i < 5) { + if ($i === 3) { + break; // 退出循环 + } + echo $i++; +} // 输出 "012" + +for ($i = 0; $i < 5; $i++) { + if ($i === 3) { + continue; // 跳过此次遍历 + } + echo $i; +} // 输出 "0124" + + +/******************************** + * 函数 + */ + +// 通过"function"定义函数: +function my_function () { + return 'Hello'; +} + +echo my_function(); // => "Hello" + +// 函数名需要以字母或者下划线开头, +// 后面可以跟着任意的字幕、下划线、数字. + +function add ($x, $y = 1) { // $y 是可选参数,默认值为 1 + $result = $x + $y; + return $result; +} + +echo add(4); // => 5 +echo add(4, 2); // => 6 + +// $result 在函数外部不可访问 +// print $result; // 抛出警告 + +// 从 PHP 5.3 起我们可以定义匿名函数 +$inc = function ($x) { + return $x + 1; +}; + +echo $inc(2); // => 3 + +function foo ($x, $y, $z) { + echo "$x - $y - $z"; +} + +// 函数也可以返回一个函数 +function bar ($x, $y) { + // 用 'use' 将外部的参数引入到里面 + return function ($z) use ($x, $y) { + foo($x, $y, $z); + }; +} + +$bar = bar('A', 'B'); +$bar('C'); // 输出 "A - B - C" + +// 你也可以通过字符串调用函数 +$function_name = 'add'; +echo $function_name(1, 2); // => 3 +// 在通过程序来决定调用哪个函数时很有用 +// 或者,使用 call_user_func(callable $callback [, $parameter [, ... ]]); + +/******************************** + * 导入 + */ + +<?php +// 被导入的php文件也必须以php开标签开始 + +include 'my-file.php'; +// 现在my-file.php就在当前作用域中可见了 +// 如果这个文件无法被导入(比如文件不存在),会抛出警告 + +include_once 'my-file.php'; +// my-file.php中的代码在其他地方被导入了,那么就不会被再次导入 +// 这会避免类的多重定义错误 + +require 'my-file.php'; +require_once 'my-file.php'; +// 和include功能相同,只不过如果不能被导入时,会抛出错误 + +// my-include.php的内容: +<?php + +return 'Anything you like.'; +// 文件结束 + +// Include和Require函数也有返回值 +$value = include 'my-include.php'; + +// 被引入的文件是根据文件路径或者include_path配置来查找到的 +// 如果文件最终没有被找到,那么就会查找当前文件夹。之后才会报错 +/* */ + +/******************************** + * 类 + */ + +// 类是由class关键字定义的 + +class MyClass +{ + const MY_CONST = 'value'; // 常量 + + static $staticVar = 'static'; + + // 属性必须声明其作用域 + public $property = 'public'; + public $instanceProp; + protected $prot = 'protected'; // 当前类和子类可访问 + private $priv = 'private'; // 仅当前类可访问 + + // 通过 __construct 来定义构造函数 + public function __construct($instanceProp) { + // 通过 $this 访问当前对象 + $this->instanceProp = $instanceProp; + } + + // 方法就是类中定义的函数 + public function myMethod() + { + print 'MyClass'; + } + + final function youCannotOverrideMe() + { + } + + public static function myStaticMethod() + { + print 'I am static'; + } +} + +echo MyClass::MY_CONST; // 输出 'value'; +echo MyClass::$staticVar; // 输出 'static'; +MyClass::myStaticMethod(); // 输出 'I am static'; + +// 通过new来新建实例 +$my_class = new MyClass('An instance property'); +// 如果不传递参数,那么括号可以省略 + +// 用 -> 来访问成员 +echo $my_class->property; // => "public" +echo $my_class->instanceProp; // => "An instance property" +$my_class->myMethod(); // => "MyClass" + + +// 使用extends来生成子类 +class MyOtherClass extends MyClass +{ + function printProtectedProperty() + { + echo $this->prot; + } + + // 方法覆盖 + function myMethod() + { + parent::myMethod(); + print ' > MyOtherClass'; + } +} + +$my_other_class = new MyOtherClass('Instance prop'); +$my_other_class->printProtectedProperty(); // => 输出 "protected" +$my_other_class->myMethod(); // 输出 "MyClass > MyOtherClass" + +final class YouCannotExtendMe +{ +} + +// 你可以使用“魔法方法”来生成getter和setter方法 +class MyMapClass +{ + private $property; + + public function __get($key) + { + return $this->$key; + } + + public function __set($key, $value) + { + $this->$key = $value; + } +} + +$x = new MyMapClass(); +echo $x->property; // 会使用 __get() 方法 +$x->property = 'Something'; // 会使用 __set() 方法 + +// 类可以是被定义成抽象类 (使用 abstract 关键字) 或者 +// 去实现接口 (使用 implements 关键字). +// 接口需要通过interface关键字来定义 + +interface InterfaceOne +{ + public function doSomething(); +} + +interface InterfaceTwo +{ + public function doSomethingElse(); +} + +// 接口可以被扩展 +interface InterfaceThree extends InterfaceTwo +{ + public function doAnotherContract(); +} + +abstract class MyAbstractClass implements InterfaceOne +{ + public $x = 'doSomething'; +} + +class MyConcreteClass extends MyAbstractClass implements InterfaceTwo +{ + public function doSomething() + { + echo $x; + } + + public function doSomethingElse() + { + echo 'doSomethingElse'; + } +} + + +// 一个类可以实现多个接口 +class SomeOtherClass implements InterfaceOne, InterfaceTwo +{ + public function doSomething() + { + echo 'doSomething'; + } + + public function doSomethingElse() + { + echo 'doSomethingElse'; + } +} + + +/******************************** + * 特征 + */ + +// 特征 从 PHP 5.4.0 开始包括,需要用 "trait" 这个关键字声明 + +trait MyTrait +{ + public function myTraitMethod() + { + print 'I have MyTrait'; + } +} + +class MyTraitfulClass +{ + use MyTrait; +} + +$cls = new MyTraitfulClass(); +$cls->myTraitMethod(); // 输出 "I have MyTrait" + + +/******************************** + * 命名空间 + */ + +// 这部分是独立于这个文件的 +// 因为命名空间必须在一个文件的开始处。 + +<?php + +// 类会被默认的放在全局命名空间中,可以被一个\来显式调用 + +$cls = new \MyClass(); + + + +// 为一个文件设置一个命名空间 +namespace My\Namespace; + +class MyClass +{ +} + +// (或者从其他文件中) +$cls = new My\Namespace\MyClass; + +//或者从其他命名空间中 +namespace My\Other\Namespace; + +use My\Namespace\MyClass; + +$cls = new MyClass(); + +// 你也可以为命名空间起一个别名 + +namespace My\Other\Namespace; + +use My\Namespace as SomeOtherNamespace; + +$cls = new SomeOtherNamespace\MyClass(); + +*/ + +``` + +## 更多阅读 + +访问 [PHP 官方文档](http://www.php.net/manual/) + +如果你对最佳实践感兴趣(实时更新) [PHP The Right Way](http://www.phptherightway.com/). + +如果你很熟悉善于包管理的语言 [Composer](http://getcomposer.org/). + +如要了解通用标准,请访问PHP Framework Interoperability Group's [PSR standards](https://github.com/php-fig/fig-standards). diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown new file mode 100755 index 00000000..764eed54 --- /dev/null +++ b/zh-cn/python-cn.html.markdown @@ -0,0 +1,475 @@ +--- +language: python +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: learnpython-zh.py +lang: zh-cn +--- + +Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一 +我喜爱python是因为它有极为清晰的语法,甚至可以说,它就是可以执行的伪代码 + +很欢迎来自您的反馈,你可以在[@louiedinh](http://twitter.com/louiedinh) 和 louiedinh [at] [google's email service] 这里找到我 + +注意: 这篇文章针对的版本是Python 2.7,但大多也可使用于其他Python 2的版本 +如果是Python 3,请在网络上寻找其他教程 + +```python +# 单行注释 +""" 多行字符串可以用 + 三个引号包裹,不过这也可以被当做 + 多行注释 +""" + +#################################################### +## 1. 原始数据类型和操作符 +#################################################### + +# 数字类型 +3 #=> 3 + +# 简单的算数 +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# 整数的除法会自动取整 +5 / 2 #=> 2 + +# 要做精确的除法,我们需要引入浮点数 +2.0 # 浮点数 +11.0 / 4.0 #=> 2.75 好多了 + +# 括号具有最高优先级 +(1 + 3) * 2 #=> 8 + +# 布尔值也是原始数据类型 +True +False + +# 用not来取非 +not True #=> False +not False #=> True + +# 相等 +1 == 1 #=> True +2 == 1 #=> False + +# 不等 +1 != 1 #=> False +2 != 1 #=> True + +# 更多的比较操作符 +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# 比较运算可以连起来写! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# 字符串通过"或'括起来 +"This is a string." +'This is also a string.' + +# 字符串通过加号拼接 +"Hello " + "world!" #=> "Hello world!" + +# 字符串可以被视为字符的列表 +"This is a string"[0] #=> 'T' + +# % 可以用来格式化字符串 +"%s can be %s" % ("strings", "interpolated") + +# 也可以用format方法来格式化字符串 +# 推荐使用这个方法 +"{0} can be {1}".format("strings", "formatted") +# 也可以用变量名代替数字 +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None 是对象 +None #=> None + +# 不要用相等 `==` 符号来和None进行比较 +# 要用 `is` +"etc" is None #=> False +None is None #=> True + +# 'is' 可以用来比较对象的相等性 +# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少 + +# None, 0, 和空字符串都被算作False +# 其他的均为True +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. 变量和集合 +#################################################### + +# 很方便的输出 +print "I'm Python. Nice to meet you!" + + +# 给变量赋值前不需要事先生命 +some_var = 5 # 规范用小写字母和下划线来做为变量名 +some_var #=> 5 + +# 访问之前为赋值的变量会抛出异常 +# 查看控制流程一节来了解异常处理 +some_other_var # 抛出命名异常 + +# if语句可以作为表达式来使用 +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# 列表用来保存序列 +li = [] +# 可以直接初始化列表 +other_li = [4, 5, 6] + +# 在列表末尾添加元素 +li.append(1) #li 现在是 [1] +li.append(2) #li 现在是 [1, 2] +li.append(4) #li 现在是 [1, 2, 4] +li.append(3) #li 现在是 [1, 2, 4, 3] +# 移除列表末尾元素 +li.pop() #=> 3 and li is now [1, 2, 4] +# 放回来 +li.append(3) # li is now [1, 2, 4, 3] again. + +# 像其他语言访问数组一样访问列表 +li[0] #=> 1 +# 访问最后一个元素 +li[-1] #=> 3 + +# 越界会抛出异常 +li[4] # 抛出越界异常 + +# 切片语法需要用到列表的索引访问 +# 可以看做数学之中左闭右开区间 +li[1:3] #=> [2, 4] +# 省略开头的元素 +li[2:] #=> [4, 3] +# 省略末尾的元素 +li[:3] #=> [1, 2, 4] + +# 删除特定元素 +del li[2] # li 现在是 [1, 2, 3] + +# 合并列表 +li + other_li #=> [1, 2, 3, 4, 5, 6] - 不改变这两个列表 + +# 通过拼接合并列表 +li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] + +# 用in来返回元素是否在列表中 +1 in li #=> True + +# 返回列表长度 +len(li) #=> 6 + + +# 元组类似于列表,但是他是不可改变的 +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # 类型错误 + +# 对于大多数的列表操作,也适用于元组 +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# 你可以将元组解包赋给多个变量 +a, b, c = (1, 2, 3) # a是1,b是2,c是3 +# 如果不加括号,那么会自动视为元组 +d, e, f = 4, 5, 6 +# 现在我们可以看看交换两个数字是多么容易的事 +e, d = d, e # d是5,e是4 + + +# 字典用来储存映射关系 +empty_dict = {} +# 字典初始化 +filled_dict = {"one": 1, "two": 2, "three": 3} + +# 字典也用中括号访问元素 +filled_dict["one"] #=> 1 + +# 把所有的键保存在列表中 +filled_dict.keys() #=> ["three", "two", "one"] +# 键的顺序并不是唯一的,得到的不一定是这个顺序 + +# 把所有的值保存在列表中 +filled_dict.values() #=> [3, 2, 1] +# 和键的顺序相同 + +# 判断一个键是否存在 +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# 查询一个不存在的键会抛出键异常 +filled_dict["four"] # 键异常 + +# 用get方法来避免键异常 +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# get方法支持在不存在的时候返回一个默认值 +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# Setdefault是一个更安全的添加字典元素的方法 +filled_dict.setdefault("five", 5) #filled_dict["five"] 的值为 5 +filled_dict.setdefault("five", 6) #filled_dict["five"] 的值仍然是 5 + + +# 集合储存无顺序的元素 +empty_set = set() +# 出事话一个集合 +some_set = set([1,2,2,3,4]) # filled_set 现在是 set([1, 2, 3, 4]) + +# Python 2.7 之后,大括号可以用来表示集合 +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# 为集合添加元素 +filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} + +# 用&来实现集合的交 +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# 用|来实现集合的并 +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# 用-来实现集合的差 +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# 用in来判断元素是否存在于集合中 +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. 控制流程 +#################################################### + +# 新建一个变量 +some_var = 5 + +# 这是个if语句,在python中缩进是很重要的。 +# 会输出 "some var is smaller than 10" +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # 这个 elif 语句是不必须的 + print "some_var is smaller than 10." +else: # 也不是必须的 + print "some_var is indeed 10." + + +""" +用for循环遍历列表 +输出: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # 你可以用 % 来格式化字符串 + print "%s is a mammal" % animal + +""" +`range(number)` 返回从0到给定数字的列表 +输出: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While循环 +输出: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Shorthand for x = x + 1 + +# 用 try/except块来处理异常 + +# Python 2.6 及以上适用: +try: + # 用raise来抛出异常 + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass就是什么都不做,不过通常这里会做一些恢复工作 + + +#################################################### +## 4. 函数 +#################################################### + +# 用def来新建函数 +def add(x, y): + print "x is %s and y is %s" % (x, y) + return x + y # Return values with a return statement + +# 调用带参数的函数 +add(5, 6) #=> 输出 "x is 5 and y is 6" 返回 11 + +# 通过关键字赋值来调用函数 +add(y=6, x=5) # 顺序是无所谓的 + +# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的 +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的 +def keyword_args(**kwargs): + return kwargs + +# 实际效果: +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# 你也可以同时将一个函数定义成两种形式 +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# 当调用函数的时候,我们也可以和之前所做的相反,把元组和字典展开为参数 +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalent to foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) + +# Python 有一等函数: +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# 匿名函数 +(lambda x: x > 2)(3) #=> True + +# 内置高阶函数 +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# 可以用列表方法来对高阶函数进行更巧妙的引用 +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. 类 +#################################################### + +# 我们新建的类是从object类中继承的 +class Human(object): + + # 类属性,由所有类的对象共享 + species = "H. sapiens" + + # 基本构造函数 + def __init__(self, name): + # 将参数赋给对象成员属性 + self.name = name + + # 成员方法,参数要有self + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # 类方法由所有类的对象共享 + # 这类方法在调用时,会把类本身传给第一个参数 + @classmethod + def get_species(cls): + return cls.species + + # 静态方法是不需要类和对象的引用就可以调用的方法 + @staticmethod + def grunt(): + return "*grunt*" + + +# 实例化一个类 +i = Human(name="Ian") +print i.say("hi") # 输出 "Ian: hi" + +j = Human("Joel") +print j.say("hello") # 输出 "Joel: hello" + +# 访问类的方法 +i.get_species() #=> "H. sapiens" + +# 改变共享属性 +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# 访问静态变量 +Human.grunt() #=> "*grunt*" + + +#################################################### +## 6. 模块 +#################################################### + +# 我们可以导入其他模块 +import math +print math.sqrt(16) #=> 4 + +# 我们也可以从一个模块中特定的函数 +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# 从模块中导入所有的函数 +# 警告:不推荐使用 +from math import * + +# 简写模块名 +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Python的模块其实只是普通的python文件 +# 你也可以创建自己的模块,并且导入它们 +# 模块的名字就和文件的名字相同 + +# 以可以通过下面的信息找找要成为模块需要什么属性或方法 +import math +dir(math) + + +``` + +## 更多阅读 + +希望学到更多?试试下面的链接: + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown new file mode 100644 index 00000000..6530b520 --- /dev/null +++ b/zh-cn/ruby-cn.html.markdown @@ -0,0 +1,330 @@ +--- +language: ruby +filename: learnruby-zh.rb +lang: zh-cn +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] +translators: + - ["Lin Xiangyu", "https://github.com/oa414"] +--- + +```ruby +# 这是单行注释 + +=begin +这是多行注释 +没人用这个 +你也不该用 +=end + +# 首先,也是最重要的,所有东西都是对象 + +# 数字是对象 + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# 一些基本的算术符号 +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# 算术符号只是语法糖而已 +# 实际上是调用对象的方法 +1.+(3) #=> 4 +10.* 5 #=> 50 + +# 特殊的只也是对象 +nil # 空 +true # 真 +false # 假 + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# 相等运算符 +1 == 1 #=> true +2 == 1 #=> false + +# 不等运算符 +1 != 1 #=> false +2 != 1 #=> true +!true #=> false +!false #=> true + +# 除了false自己,nil是唯一的值为false的对象 + +!nil #=> true +!false #=> true +!0 #=> false + +# 更多比较 +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# 字符串是对象 + +'I am a string'.class #=> String +"I am a string too".class #=> String + +placeholder = "use string interpolation" +"I can #{placeholder} when using double quoted strings" +#=> "I can use string interpolation when using double quoted strings" + + +# 输出值 +puts "I'm printing!" + +# 变量 +x = 25 #=> 25 +x #=> 25 + +# 注意赋值语句返回了赋的值 +# 这意味着你可以用多重赋值语句 + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# 按照惯例,用snake_case 作为变量名 +snake_case = true + +# 使用具有描述性的运算符 +path_to_project_root = '/good/name/' +path = '/bad/name/' + +# 符号(Symbols,也是对象) +# 符号是不可变的,内部用整数类型表示的可重用的值。通常用它代替字符串来有效地表达有意义的值 + + +:pending.class #=> Symbol + +status = :pending + +status == :pending #=> true + +status == 'pending' #=> false + +status == :approved #=> false + +# 数组 + +# 这是一个数组 +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# 数组可以包含不同类型的元素 + +array = [1, "hello", false] #=> => [1, "hello", false] + +# 数组可以被索引 +# 从前面开始 +array[0] #=> 1 +array[12] #=> nil + +# 像运算符一样,[var]形式的访问 +# 也就是一个语法糖 +# 实际上是调用对象的[] 方法 +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# 从尾部开始 +array[-1] #=> 5 + +# 同时指定开始的位置和结束的位置 +array[2, 4] #=> [3, 4, 5] + +# 或者指定一个范围 +array[1..3] #=> [2, 3, 4] + +# 像这样往数组增加一个元素 +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# 哈希表是Ruby的键值对的基本数据结构 +# 哈希表由大括号定义 +hash = {'color' => 'green', 'number' => 5} + +hash.keys #=> ['color', 'number'] + +# 哈希表可以通过键快速地查询 +hash['color'] #=> 'green' +hash['number'] #=> 5 + +# 查询一个不存在地键将会返回nil +hash['nothing here'] #=> nil + +# 用 #each 方法来枚举哈希表: +hash.each do |k, v| + puts "#{k} is #{v}" +end + +# 从Ruby 1.9开始, 用符号作为键的时候有特别的记号表示: + +new_hash = { defcon: 3, action: true} + +new_hash.keys #=> [:defcon, :action] + +# 小贴士:数组和哈希表都是可枚举的 +# 它们可以共享一些有用的方法,比如each, map, count, 和more + +# 控制流 + +if true + "if statement" +elsif false + "else if, optional" +else + "else, also optional" +end + +for counter in 1..5 + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +# 然而 +# 没人用for循环 +# 用`each`来代替,就像这样 + +(1..5).each do |counter| + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +counter = 1 +while counter <= 5 do + puts "iteration #{counter}" + counter += 1 +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +grade = 'B' + +case grade +when 'A' + puts "Way to go kiddo" +when 'B' + puts "Better luck next time" +when 'C' + puts "You can do better" +when 'D' + puts "Scraping through" +when 'F' + puts "You failed!" +else + puts "Alternative grading system, eh?" +end + +# 函数 + +def double(x) + x * 2 +end + +# 函数 (以及所有的方法块) 隐式地返回了最后语句的值 +double(2) #=> 4 + +# 当不存在歧义的时候括号是可有可无的 +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x,y) + x + y +end + +# 方法的参数通过逗号分隔 +sum 3, 4 #=> 7 + +sum sum(3,4), 5 #=> 12 + +# yield +# 所有的方法都有一个隐式的块参数 +# 可以用yield参数调用 + +def surround + puts "{" + yield + puts "}" +end + +surround { puts 'hello world' } + +# { +# hello world +# } + + +# 用class关键字定义一个类 +class Human + + # 一个类变量,它被这个类地所有实例变量共享 + @@species = "H. sapiens" + + # 构造函数 + def initialize(name, age=0) + # 将参数name的值赋给实例变量@name + @name = name + # 如果没有给出age, 那么会采用参数列表中地默认地值 + @age = age + end + + # 基本的 setter 方法 + def name=(name) + @name = name + end + + # 基本地 getter 方法 + def name + @name + end + + # 一个类方法以self.开头 + # 它可以被类调用,但不能被类的实例调用 + def self.say(msg) + puts "#{msg}" + end + + def species + @@species + end + +end + + +# 类的例子 +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# 让我们来调用一些方法 +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# 调用对象的方法 +Human.say("Hi") #=> "Hi" + +``` diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown new file mode 100644 index 00000000..1ce41ac6 --- /dev/null +++ b/zh-cn/scala-cn.html.markdown @@ -0,0 +1,413 @@ +--- +language: Scala +filename: learnscala-zh.scala +contributors: + - ["George Petrov", "http://github.com/petrovg"] + - ["Dominic Bou-Samra", "http://dbousamra.github.com"] +translators: + - ["Peiyong Lin", ""] +filename: learn.scala +lang: zh-cn +--- + +Scala - 一门可拓展性的语言 + +```cpp + +/* + 自行设置: + + 1) 下载 Scala - http://www.scala-lang.org/downloads + 2) unzip/untar 到你喜欢的地方,放在路径中的 bin 目录下 + 3) 在终端输入 scala,开启 Scala 的 REPL,你会看到提示符: + + scala> + + 这就是所谓的 REPL,你现在可以在其中运行命令,让我们做到这一点: +*/ + +println(10) // 打印整数 10 + +println("Boo!") // 打印字符串 "BOO!" + + +// 一些基础 + +// 打印并强制换行 +println("Hello world!") +// 没有强制换行的打印 +print("Hello world") + +// 通过 var 或者 val 来声明变量 +// val 声明是不可变的,var 声明是可修改的。不可变性是好事。 +val x = 10 // x 现在是 10 +x = 20 // 错误: 对 val 声明的变量重新赋值 +var x = 10 +x = 20 // x 现在是 20 + +// 单行注释开始于两个斜杠 +/* +多行注释看起来像这样。 +*/ + +// 布尔值 +true +false + +// 布尔操作 +!true // false +!false // true +true == false // false +10 > 5 // true + +// 数学运算像平常一样 +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 + + +// 在 REPL 计算一个命令会返回给你结果的类型和值 + +1 + 7 + +/* 上行的结果是: + + scala> 1 + 7 + res29: Int = 8 + + 这意味着计算 1 + 7 的结果是一个 Int 类型的对象,其值为 8 + + 1+7 的结果是一样的 +*/ + + +// 包括函数在内,每一个事物都是对象。在 REPL 中输入: + +7 // 结果 res30: Int = 7 (res30 是一个生成的结果的 var 命名) + +// 下一行给你一个接收一个 Int 类型并返回该数的平方的函数 +(x:Int) => x * x + +// 你可以分配给函数一个标识符,像这样: +val sq = (x:Int) => x * x + +/* 上面的例子说明 + + sq: Int => Int = <function1> + + 意味着这次我们给予了 sq 这样一个显式的名字给一个接受一个 Int 类型值并返回 一个 Int 类型值的函数 + + sq 可以像下面那样被执行: +*/ + +sq(10) // 返回给你:res33: Int = 100. + +// Scala 允许方法和函数返回或者接受其它的函数或者方法作为参数。 + +val add10: Int => Int = _ + 10 // 一个接受一个 Int 类型参数并返回一个 Int 类型值的函数 +List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被应用到每一个元素 + +// 匿名函数可以被使用来代替有命名的函数: +List(1, 2, 3) map (x => x + 10) + +// 下划线标志,如果匿名函数只有一个参数可以被使用来表示该参数变量 +List(1, 2, 3) map (_ + 10) + +// 如果你所应用的匿名块和匿名函数都接受一个参数,那么你甚至可以省略下划线 +List("Dom", "Bob", "Natalia") foreach println + + + +// 数据结构 + +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21) // 这会抛出一个异常 + +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle") // 这会抛出一个异常 + +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") + +val s = Set(1, 3, 7) +s(0) +s(1) + +/* 查看 map 的文档 + * 点击[这里](http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map) + * 确保你可以读它 + */ + + +// 元组 + +(1, 2) + +(4, 3, 2) + +(1, 2, "three") + +(a, 2, "three") + +// 为什么有这个? + +val divideInts = (x:Int, y:Int) => (x / y, x % y) + +divideInts(10,3) // 函数 divideInts 返回你结果和余数 + +// 要读取元组的元素,使用 _._n,n是从1开始的元素索引 + +val d = divideInts(10,3) + +d._1 + +d._2 + + + +// 选择器 + +s.map(sq) + +val sSquared = s. map(sq) + +sSquared.filter(_ < 10) + +sSquared.reduce (_+_) + +// filter 函数接受一个预测(一个函数,形式为 A -> Boolean) 并选择出所有的元素满足这个预测 + +List(1, 2, 3) filter (_ > 2) // List(3) +List( + Person(name = "Dom", age = 23), + Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) + + +// Scala 的 foreach 方法定义在特定的接受一个类型的集合上 +// 返回 Unit(一个 void 方法) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println + + + + +// For 包含 + +for { n <- s } yield sq(n) + +val nSquared2 = for { n <- s } yield sq(n) + +for { n <- nSquared2 if n < 10 } yield n + +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared + +/* 注意:这些不是 for 循环. 一个 for 循环的语义是 '重复'('repeat'), + 然而,一个 for-包含 定义了一个两个数据结合间的关系 */ + + + +// 循环和迭代 + +1 to 5 +val r = 1 to 5 +r.foreach( println ) + +r foreach println +// 注意:Scala 是相当宽容的当它遇到点和括号 - 分别地学习这些规则。 +// 这帮助你编写读起来像英语的 DSLs 和 APIs + +(5 to 1 by -1) foreach ( println ) + +// while 循环 +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + +while (i < 10) { println("i " + i); i+=1 } // 发生了什么?为什么? + +i // 展示 i 的值。注意到 while 是一个传统意义上的循环 + // 它顺序地执行并且改变循环变量的值。while 非常快,比 Java // 循环快, + // 但是在其上使用选择器和包含更容易理解和并行。 + +// do while 循环 +do { + println("x is still less then 10"); + x += 1 +} while (x < 10) + +// 在 Scala中,尾递归是一种惯用的执行循环的方式。 +// 递归函数需要显示的返回类型,编译器不能推断出类型。 +// 这里它是 Unit。 +def showNumbersInRange(a:Int, b:Int):Unit = { + print(a) + if (a < b) + showNumbersInRange(a + 1, b) +} + + + +// 条件语句 + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + + + +// 面向对象特性 + +// 类名是 Dog +class Dog { + //bark 方法,返回字符串 + def bark: String = { + // the body of the method + "Woof, woof!" + } +} + +// 类可以包含几乎其它的构造,包括其它的类, +// 函数,方法,对象,case 类,特性等等。 + + + +// Case 类 + +case class Person(name:String, phoneNumber:String) + +Person("George", "1234") == Person("Kate", "1236") + + + + +// 模式匹配 + +val me = Person("George", "1234") + +me match { case Person(name, number) => { + "We matched someone : " + name + ", phone : " + number }} + +me match { case Person(name, number) => "Match : " + name; case _ => "Hm..." } + +me match { case Person("George", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + +val kate = Person("Kate", "1234") + +kate match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + + + +// 正则表达式 + +val email = "(.*)@(.*)".r // 在字符串上调用 r 会使它变成一个正则表达式 + +val email(user, domain) = "henry@zkpr.com" + +"mrbean@pyahoo.com" match { + case email(name, domain) => "I know your name, " + name +} + + + +// 字符串 + +"Scala 字符串被双引号包围" // +'a' // Scala 字符 +'单引号的字符串不存在' // 错误 +"字符串拥有通常的 Java 方法定义在其上".length +"字符串也有额外的 Scala 方法".reverse + +// 参见: scala.collection.immutable.StringOps + +println("ABCDEF".length) +println("ABCDEF".substring(2, 6)) +println("ABCDEF".replace("C", "3")) + +val n = 45 +println(s"We have $n apples") + +val a = Array(11, 9, 6) +println(s"My second daughter is ${a(2-1)} years old") + +// 一些字符需要被转义,举例来说,字符串中的双引号: +val a = "They stood outside the \"Rose and Crown\"" + +// 三个双引号使得字符串可以跨行并且可以包含引号(无需转义) + +val html = """<form id="daform"> + <p>Press belo', Joe</p> + | <input type="submit"> + </form>""" + + + +// 应用结果和组织 + +// import +import scala.collection.immutable.List + +// Import 所有的子包 +import scala.collection.immutable._ + +// 在一条语句中 Import 多个类 +import scala.collection.immutable.{List, Map} + +// 使用 '=>' 来重命名一个 import +import scala.collection.immutable{ List => ImmutableList } + +// import 除了一些类的其它所有的类。下面的例子除去了 Map 类和 Set 类: +import scala.collection.immutable.{Map => _, Set => _, _} + +// 在 scala 源文件中,你的程序入口点使用一个拥有单一方法 main 的对象来定义: + +object Application { + def main(args: Array[String]): Unit = { + // stuff goes here. + } +} + +// 文件可以包含多个类和对象。由 scalac 来编译 + + + + +// 输入和输出 + +// 一行一行读取文件 +import scala.io.Source +for(line <- Source.fromPath("myfile.txt").getLines()) + println(line) + +// 使用 Java 的 PrintWriter 来写文件 + + +``` + +## 更多的资源 + +[为没耐心的人准备的 Scala](http://horstmann.com/scala/) + +[Twitter Scala school](http://twitter.github.io/scala_school/) + +[The Scala documentation](http://www.scala-lang.org/documentation/) + +[在浏览器尝试 Scala](http://scalatutorials.com/tour/) + +加入 [Scala 用户组](https://groups.google.com/forum/#!forum/scala-user) |