diff options
-rw-r--r-- | elisp.html.markdown | 349 | ||||
-rw-r--r-- | erlang.html.markdown | 48 | ||||
-rw-r--r-- | git.html.markdown | 388 | ||||
-rw-r--r-- | java.html.markdown | 2 | ||||
-rw-r--r-- | livescript.html.markdown | 345 | ||||
-rw-r--r-- | lua.html.markdown | 2 | ||||
-rw-r--r-- | php.html.markdown | 4 | ||||
-rw-r--r-- | racket.html.markdown | 607 | ||||
-rw-r--r-- | ruby.html.markdown | 2 |
9 files changed, 1725 insertions, 22 deletions
diff --git a/elisp.html.markdown b/elisp.html.markdown new file mode 100644 index 00000000..c99466b6 --- /dev/null +++ b/elisp.html.markdown @@ -0,0 +1,349 @@ +--- +language: elisp +contributors: + - ["Bastien Guerry", "http://bzg.fr"] +filename: learn-emacs-lisp.el +--- + +```elisp +;; This gives an introduction to Emacs Lisp in 15 minutes (v0.2a) +;; +;; 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) +;; 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 +;; +;; 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 "Alice". +;; \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 +``` diff --git a/erlang.html.markdown b/erlang.html.markdown index 208f31e4..065219ba 100644 --- a/erlang.html.markdown +++ b/erlang.html.markdown @@ -1,12 +1,12 @@ --- language: erlang -contributor: +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/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/java.html.markdown b/java.html.markdown index a6026651..b4531635 100644 --- a/java.html.markdown +++ b/java.html.markdown @@ -343,7 +343,7 @@ class Bicycle { speed -= decrement; } - public void setName(int newName) { + public void setName(String newName) { name = newName; } 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 0ece399f..7325a1cf 100644 --- a/lua.html.markdown +++ b/lua.html.markdown @@ -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 9627035c..e81b88fd 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -1,8 +1,8 @@ --- language: php contributors: -- [Malcolm Fell](http://emarref.net/) -- [Trismegiste](https://github.com/Trismegiste) + - ["Malcolm Fell", "http://emarref.net/"] + - ["Trismegiste", "https://github.com/Trismegiste"] filename: learnphp.php --- 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 index af7af918..38d060a3 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -305,6 +305,8 @@ 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" |