diff options
-rw-r--r-- | Visual Basic | 248 | ||||
-rw-r--r-- | c.html.markdown | 36 | ||||
-rw-r--r-- | clojure.html.markdown | 4 | ||||
-rw-r--r-- | coffeescript.html.markdown | 55 | ||||
-rw-r--r-- | dart.html.markdown | 4 | ||||
-rw-r--r-- | elisp.html.markdown | 353 | ||||
-rw-r--r-- | elixir.html.markdown | 10 | ||||
-rw-r--r-- | erlang.html.markdown | 50 | ||||
-rw-r--r-- | fsharp.html.markdown | 4 | ||||
-rw-r--r-- | git.html.markdown | 388 | ||||
-rw-r--r-- | haskell.html.markdown | 114 | ||||
-rw-r--r-- | java.html.markdown | 115 | ||||
-rw-r--r-- | javascript.html.markdown | 436 | ||||
-rw-r--r-- | julia.html.markdown | 4 | ||||
-rw-r--r-- | livescript.html.markdown | 345 | ||||
-rw-r--r-- | lua.html.markdown | 6 | ||||
-rw-r--r-- | php.html.markdown | 23 | ||||
-rw-r--r-- | python.html.markdown | 6 | ||||
-rw-r--r-- | r.html.markdown | 4 | ||||
-rw-r--r-- | racket.html.markdown | 607 | ||||
-rw-r--r-- | ruby.html.markdown | 328 | ||||
-rw-r--r-- | visualbasic.html.markdown | 281 | ||||
-rw-r--r-- | whip.html.markdown | 238 | ||||
-rwxr-xr-x | zh-cn/c-cn.html.markdown | 395 | ||||
-rwxr-xr-x | zh-cn/elisp-cn.html.markdown | 344 | ||||
-rwxr-xr-x | zh-cn/java-cn.html.markdown | 405 | ||||
-rwxr-xr-x | zh-cn/javascript.html.markdown | 418 | ||||
-rwxr-xr-x | zh-cn/php-cn.html.markdown | 636 |
28 files changed, 5736 insertions, 121 deletions
diff --git a/Visual Basic b/Visual Basic new file mode 100644 index 00000000..73430633 --- /dev/null +++ b/Visual Basic @@ -0,0 +1,248 @@ +--- +language: Visual Basic Console Application +contributors: + - ["Brian Martin", "http://brianmartin.biz"] +filename: learnvisualbasic.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("Learn X in Y Minutes is a creation of Adam Bard (@adambard) This particular program 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. + Private Sub HelloWorldOutput() 'We use private subs to seperate different sections of the program. + Console.Title = "Hello World Ouput | Learn X in Y Minutes" 'Title of Console Application + '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() 'We use private subs to seperate different sections of the program. + Console.Title = "Hello World YourName | Learn X in Y Minutes" 'Title of Console Application + 'Variables + 'Data entered by a user needs to be stored. + 'Variables also start with a Dim and end with an As VariableType. + Dim username As String 'In this tutorial, we want to know what your name, and make the program respond to what is said. + '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() 'We use private subs to seperate different sections of the program. + Console.Title = "Calculating Whole Numbers | Learn X in Y Minutes" 'Title of Console Application + 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" 'Title of Console Application + 'Of course we would like to be able to add up decimals. + 'Therefore we could change the above from Integer to Double. + Console.Write("First number: ") 'Enter a whole number, 1.2, 2.4, 50.1, 104.9 ect + 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" 'Title of Console Application + 'However if you'd like the calculator to subtract, divide, multiple and add up. + 'Copy and paste the above again. + Console.Write("First number: ") 'Enter a whole number, 1.2, 2.4, 50.1, 104.9 ect + 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()) + Console.WriteLine(" = " + c.ToString.PadLeft(3)) 'We want to pad the answers to the left by 3 spaces. + Console.Write(a.ToString() + " * " + b.ToString()) + Console.WriteLine(" = " + d.ToString.PadLeft(3)) 'We want to pad the answers to the left by 3 spaces. + Console.Write(a.ToString() + " - " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) 'We want to pad the answers to the left by 3 spaces. + Console.Write(a.ToString() + " / " + b.ToString()) + Console.WriteLine(" = " + e.ToString.PadLeft(3)) 'We want to pad the answers to the left by 3 spaces. + 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)") + answer = Console.ReadLine 'The program grabs the variable and prints and starts again. + Loop While answer = "yes" 'The command for the variable to work would be in this case "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" + For i As Integer = 10 To 0 Step -1 'Declare Vairable and what number it should count down in Step -1, Step -2, Step -3 ect. + Console.WriteLine(i.ToString) 'Print the value of the counter variable + 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 'Hey, if Adam uses this program, kudos where kudos is due, right? + Console.WriteLine("Hello Adam") + Console.WriteLine("Thanks for creating the useful tutorial site www.learnxinyminutes.com!") + Console.ReadLine() + Else + Console.WriteLine("Hello " + userName) 'prints the username of the user + Console.WriteLine("Hope all is well have you checked out www.learnxinyminutes.com") 'Prints a message to the user + 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 complier and run (F5) the program. diff --git a/c.html.markdown b/c.html.markdown index 69bf099e..b5286f70 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. @@ -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/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..00f38d60 --- /dev/null +++ b/git.html.markdown @@ -0,0 +1,388 @@ +--- +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 origin master +``` + +### 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..be7d8669 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. -} ---------------------------------------------------- @@ -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..9cc7617d --- /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 73445839..5f5a4b54 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -1,7 +1,8 @@ --- language: php -author: Malcolm Fell -author_url: http://emarref.net/ +contributors: + - ["Malcolm Fell", "http://emarref.net/"] + - ["Trismegiste", "https://github.com/Trismegiste"] filename: learnphp.php --- @@ -47,9 +48,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) @@ -395,9 +396,6 @@ echo $function_name(1, 2); // => 3 * Includes */ -/* -``` -```php <?php // PHP within included files must also begin with a PHP open tag. @@ -541,6 +539,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'; @@ -605,9 +609,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/python.html.markdown b/python.html.markdown index e0851950..e7ee6fbd 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. Its 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] diff --git a/r.html.markdown b/r.html.markdown index 535b9065..0240e8fb 100644 --- a/r.html.markdown +++ b/r.html.markdown @@ -1,7 +1,7 @@ --- language: R -author: e99n09 -author_url: http://github.com/e99n09 +contributors: + - ["e99n09", "http://github.com/e99n09"] filename: learnr.r --- 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.html.markdown b/ruby.html.markdown new file mode 100644 index 00000000..a3bcbbd5 --- /dev/null +++ b/ruby.html.markdown @@ -0,0 +1,328 @@ +--- +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" + +``` 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..f8a8e0bd --- /dev/null +++ b/zh-cn/c-cn.html.markdown @@ -0,0 +1,395 @@ +--- +language: c +filename: learnc.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/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown new file mode 100755 index 00000000..c3a2f927 --- /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.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/java-cn.html.markdown b/zh-cn/java-cn.html.markdown new file mode 100755 index 00000000..b9ccf61a --- /dev/null +++ b/zh-cn/java-cn.html.markdown @@ -0,0 +1,405 @@ +--- +name: java +category: language +language: java +lang: zh-cn +filename: LearnJava.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.html.markdown b/zh-cn/javascript.html.markdown new file mode 100755 index 00000000..3b5cfa94 --- /dev/null +++ b/zh-cn/javascript.html.markdown @@ -0,0 +1,418 @@ +--- +language: javascript +category: language +name: javascript +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..3b242ce1 --- /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.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). |