Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Louie Dinh 2013-06-28 16:29:46 -07:00
commit a87a1ea3fd
4 changed files with 488 additions and 45 deletions

338
c.html.markdown Normal file
View File

@ -0,0 +1,338 @@
---
language: c
author: Adam Bard
author_url: http://adambard.com/
---
Ah, C. Still the language of modern high-performance computing.
C is the lowest-level language most programmers will ever use, but
it more than makes up for it with raw speed. Just be aware of its manual
memory management and C will take you as far as you need to go.
```c
// Single-line comments start with //
/*
Multi-line comments look like this.
*/
// Import headers with #include
#include <stdlib.h>
#include <stdio.h>
// Declare function signatures in advance in a .h file, or at the top of
// your .c file.
void function_1();
void function_2();
// Your program's entry point is a function called
// main with an integer return type.
int main(){
// print output using printf, for "print formatted"
// %d is an integer, \n is a newline
printf("%d\n", 0); // => Prints 0
// All statements must end with a semicolon
///////////////////////////////////////
// Types
///////////////////////////////////////
// Variables must always be declared with a type.
// 32-bit integer
int x_int = 0;
// 16-bit integer
short x_short = 0;
// 8-bit integer, aka 1 byte
char x_char = 0;
char y_char = 'y'; // Char literals are quoted with ''
long x_long = 0; // Still 32 bytes for historical reasons
long long x_long_long = 0; // Guaranteed to be at least 64 bytes
// 32-bit floating-point decimal
float x_float = 0.0;
// 64-bit floating-point decimal
double x_double = 0.0;
// Integer types may be unsigned
unsigned char ux_char;
unsigned short ux_short;
unsigned int ux_int;
unsigned long long ux_long_long;
// Arrays must be initialized with a concrete size.
char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes
int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes
// You can initialize an array to 0 thusly:
char my_array[20] = {0};
// Indexing an array is like other languages -- or,
// rather, other languages are like C
my_array[0]; // => 0
// Arrays are mutable; it's just memory!
my_array[1] = 2;
printf("%d\n", my_array[1]); // => 2
// Strings are just lists of chars terminated by a null (0x00) byte.
char a_string[20] = "This is a string";
/*
You may have noticed that a_string is only 16 chars long.
Char #17 is a null byte, 0x00 aka \0.
Chars #18, 19 and 20 have undefined values.
*/
printf("%d\n", a_string[16]);
///////////////////////////////////////
// Operators
///////////////////////////////////////
int i1 = 1, i2 = 2; // Shorthand for multiple declaration
float f1 = 1.0, f2 = 2.0;
// Arithmetic is straightforward
i1 + i2; // => 3
i2 - i1; // => 1
i2 * i1; // => 2
i1 / i2; // => 0 (0.5, but truncated towards 0)
f1 / f2; // => 0.5, plus or minus epsilon
// Modulo is there as well
11 % 3; // => 2
// Comparison operators are probably familiar, but
// there is no boolean type in c. We use ints instead.
// 0 is false, anything else is true
3 == 2; // => 0 (false)
3 != 2; // => 1 (true)
3 > 2; // => 1
3 < 2; // => 0
2 <= 2; // => 1
2 >= 2; // => 1
// Logic works on ints
!3; // => 0 (Logical not)
!0; // => 1
1 && 1; // => 1 (Logical and)
0 && 1; // => 0
0 || 1; // => 1 (Logical or)
0 || 0; // => 0
// Bitwise operators!
~0x0F; // => 0xF0 (bitwise negation)
0x0F & 0xF0; // => 0x00 (bitwise AND)
0x0F | 0xF0; // => 0xFF (bitwise OR)
0x04 ^ 0x0F; // => 0x0B (bitwise XOR)
0x01 << 1; // => 0x02 (bitwise left shift (by 1))
0x02 >> 1; // => 0x01 (bitwise right shift (by 1))
///////////////////////////////////////
// Control Structures
///////////////////////////////////////
if(0){
printf("I am never run\n");
}else if(0){
printf("I am also never run\n");
}else{
printf("I print\n");
}
// While loops exist
int ii = 0;
while(ii < 10){
printf("%d, ", ii++); // ii++ increments ii in-place, after using its value.
} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
int kk = 0;
do{
printf("%d, ", kk);
}while(++kk < 10); // ++kk increments kk in-place, before using its value
// => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
// For loops too
int jj;
for(jj=0; jj < 10; jj++){
printf("%d, ", jj);
} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
///////////////////////////////////////
// Typecasting
///////////////////////////////////////
// Everything in C is stored somewhere in memory. You can change
// the type of a variable to choose how to read its data
int x_hex = 0x01; // You can assign vars with hex literals
// Casting between types will attempt to preserve their numeric values
printf("%d\n", x_hex); // => Prints 1
printf("%d\n", (short) x_hex); // => Prints 1
printf("%d\n", (char) x_hex); // => Prints 1
// Types will overflow without warning
printf("%d\n", (char) 257); // => 1 (Max char = 255)
printf("%d\n", (short) 65537); // => 1 (Max short = 65535)
///////////////////////////////////////
// Pointers
///////////////////////////////////////
// You can retrieve the memory address of your variables,
// then mess with them.
int x = 0;
printf("%p\n", &x); // Use & to retrieve the address of a variable
// (%p formats a pointer)
// => Prints some address in memory;
int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory
int xx;
for(xx=0; xx<20; xx++){
x_array[xx] = 20 - xx;
} // Initialize x_array to 20, 19, 18,... 2, 1
// Pointer types end with *
int* x_ptr = x_array;
// This works because arrays are pointers to their first element.
// Put a * in front to de-reference a pointer and retrieve the value,
// of the same type as the pointer, that the pointer is pointing at.
printf("%d\n", *(x_ptr)); // => Prints 20
printf("%d\n", x_array[0]); // => Prints 20
// Pointers are incremented and decremented based on their type
printf("%d\n", *(x_ptr + 1)); // => Prints 19
printf("%d\n", x_array[1]); // => Prints 19
// Array indexes are such a thin wrapper around pointer
// arithmetic that the following works:
printf("%d\n", 0[x_array]); // => Prints 20;
printf("%d\n", 2[x_array]); // => Prints 18;
// The above is equivalent to:
printf("%d\n", *(0 + x_ptr));
printf("%d\n", *(2 + x_ptr));
// You can give a pointer a block of memory to use with malloc
int* my_ptr = (int*) malloc(sizeof(int) * 20);
for(xx=0; xx<20; xx++){
*(my_ptr + xx) = 20 - xx;
} // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints)
// Dereferencing memory that you haven't allocated gives
// unpredictable results
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what?
// When you're done with a malloc'd block, you need to free it
free(my_ptr);
// Strings can be char arrays, but are usually represented as char
// pointers:
char* my_str = "This is my very own string";
printf("%d\n", *my_str); // 84 (The ascii value of 'T')
function_1();
} // end main function
///////////////////////////////////////
// Functions
///////////////////////////////////////
// Function declaration syntax:
// <return type> <function name>(<args>)
int add_two_ints(int x1, int x2){
return x1 + x2; // Use return a return a value
}
/*
Pointers are passed-by-reference (duh), so functions
can mutate their values.
Example: in-place string reversal
*/
// A void function returns no value
void str_reverse(char* str_in){
char tmp;
int ii=0, len = strlen(str_in); // Strlen is part of the c standard library
for(ii=0; ii<len/2; ii++){
tmp = str_in[ii];
str_in[ii] = str_in[len - ii - 1]; // ii-th char from end
str_in[len - ii - 1] = tmp;
}
}
/*
char c[] = "This is a test.";
str_reverse(c);
printf("%s\n", c); // => ".tset a si sihT"
*/
///////////////////////////////////////
// User-defined types and structs
///////////////////////////////////////
// Typedefs can be used to create type aliases
typedef int my_type;
my_type my_type_var = 0;
// Structs are just collections of data
struct rectangle {
int width;
int height;
};
void function_1(){
struct rectangle my_rec;
// Access struct members with .
my_rec.width = 10;
my_rec.height = 20;
// You can declare pointers to structs
struct rectangle* my_rec_ptr = &my_rec;
// Use dereferencing to set struct pointer members...
(*my_rec_ptr).width = 30;
// ... or use the -> shorthand
my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10;
}
// You can apply a typedef to a struct for convenience
typedef struct rectangle rect;
int area(rect r){
return r.width * r.height;
}
```
## Further Reading
Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/)
Other than that, Google is your friend.

View File

@ -12,6 +12,9 @@ state as it comes up.
This combination allows it to handle concurrent processing very simply, This combination allows it to handle concurrent processing very simply,
and often automatically. and often automatically.
(You need a version of Clojure 1.2 or newer)
```clojure ```clojure
; Comments start with semicolons. ; Comments start with semicolons.

View File

@ -47,8 +47,8 @@ $integer = 0123; // octal number (equivalent to 83 decimal)
$integer = 0x1A; // hexadecimal number (equivalent to 26 decimal) $integer = 0x1A; // hexadecimal number (equivalent to 26 decimal)
// Floats (aka doubles) // Floats (aka doubles)
$float = 1.234; $float = 1.234;
$float = 1.2e3; $float = 1.2e3;
$float = 7E-10; $float = 7E-10;
// Arithmetic // Arithmetic
@ -87,7 +87,7 @@ $sgl_quotes
END; // Nowdoc syntax is available in PHP 5.3.0 END; // Nowdoc syntax is available in PHP 5.3.0
// Manipulation // Manipulation
$concatenated = $sgl_quotes + $dbl_quotes; $concatenated = $sgl_quotes . $dbl_quotes;
``` ```
### Compound ### Compound
@ -119,6 +119,8 @@ print('Hello World!'); // The same as echo
// echo is actually a language construct, so you can drop the parentheses. // echo is actually a language construct, so you can drop the parentheses.
echo 'Hello World!'; echo 'Hello World!';
print 'Hello World!'; // So is print
echo 100; echo 100;
echo $variable; echo $variable;
echo function_result(); echo function_result();
@ -135,12 +137,12 @@ echo function_result();
```php ```php
<?php <?php
$a = 1; $x = 1;
$b = 2; $y = 2;
$a = $b; // A now contains the same value sa $b $x = $y; // A now contains the same value sa $y
$a =& $b; $x = &$y;
// A now contains a reference to $b. Changing the value of // $x now contains a reference to $y. Changing the value of
// $a will change the value of $b also, and vice-versa. // $x will change the value of $y also, and vice-versa.
``` ```
### Comparison ### Comparison
@ -148,15 +150,20 @@ $a =& $b;
```php ```php
<?php <?php
// These comparisons will always be true, even if the types aren't the same.
$a == $b // TRUE if $a is equal to $b after type juggling. $a == $b // TRUE if $a is equal to $b after type juggling.
$a === $b // TRUE if $a is equal to $b, and they are of the same type.
$a != $b // TRUE if $a is not equal to $b after type juggling. $a != $b // TRUE if $a is not equal to $b after type juggling.
$a <> $b // TRUE if $a is not equal to $b after type juggling. $a <> $b // TRUE if $a is not equal to $b after type juggling.
$a !== $b // TRUE if $a is not equal to $b, or they are not of the same type.
$a < $b // TRUE if $a is strictly less than $b. $a < $b // TRUE if $a is strictly less than $b.
$a > $b // TRUE if $a is strictly greater than $b. $a > $b // TRUE if $a is strictly greater than $b.
$a <= $b // TRUE if $a is less than or equal to $b. $a <= $b // TRUE if $a is less than or equal to $b.
$a >= $b // TRUE if $a is greater than or equal to $b. $a >= $b // TRUE if $a is greater than or equal to $b.
// The following will only be true if the values match and are the same type.
$a === $b // TRUE if $a is equal to $b, and they are of the same type.
$a !== $b // TRUE if $a is not equal to $b, or they are not of the same type.
1 == '1' // TRUE
1 === '1' // FALSE
``` ```
## [Type Juggling](http://www.php.net/manual/en/language.types.type-juggling.php) ## [Type Juggling](http://www.php.net/manual/en/language.types.type-juggling.php)
@ -176,7 +183,11 @@ echo $string + $string;
$string = 'one'; $string = 'one';
echo $string + $string; echo $string + $string;
// Outputs 0 because the + operator cannot cast the string 'one' to a number // Outputs 0 because the + operator cannot cast the string 'one' to a number
```
Type casting can be used to treat a variable as another type temporarily by using cast operators in parentheses.
```php
$boolean = (boolean) $integer; // $boolean is true $boolean = (boolean) $integer; // $boolean is true
$zero = 0; $zero = 0;
@ -222,9 +233,9 @@ if (/* test */) {
?> ?>
<?php if (/* test */): ?> <?php if (/* test */): ?>
<!-- Do something that isn't PHP --> This is displayed if the test is truthy.
<?php else: ?> <?php else: ?>
<!-- Do something default --> This is displayed otherwise.
<?php endif; ?> <?php endif; ?>
``` ```
@ -278,7 +289,6 @@ while ($i < 5) {
if ($i == 3) { if ($i == 3) {
break; // Exit out of the while loop and continue. break; // Exit out of the while loop and continue.
} }
echo $i++; echo $i++;
} }
@ -288,7 +298,6 @@ while ($i < 5) {
if ($i == 3) { if ($i == 3) {
continue; // Skip this iteration of the loop continue; // Skip this iteration of the loop
} }
echo $i++; echo $i++;
} }
``` ```
@ -325,8 +334,8 @@ number of letters, numbers, or underscores. There are three ways to declare func
```php ```php
<?php <?php
function my_function_name ($arg_1, $arg_2) { // $arg_1 and $arg_2 are required function my_function_name ($arg_1, $arg_2) {
// Do something with $arg_1 and $arg_2; // $arg_1 and $arg_2 are required
} }
// Functions may be nested to limit scope // Functions may be nested to limit scope
@ -335,7 +344,25 @@ function outer_function ($arg_1 = null) { // $arg_1 is optional
} }
} }
// inner_function() does not exist and cannot be called until outer_function() is called // inner_function() does not exist and cannot be called until
// outer_function() is called
```
This enables [currying](http://en.wikipedia.org/wiki/Currying) in PHP.
```php
function foo ($x, $y, $z) {
echo "$x - $y - $z";
}
function bar ($x, $y) {
return function ($z) use ($x, $y) {
foo($x, $y, $z);
};
}
$bar = bar('A', 'B');
$bar('C');
``` ```
### [Variable](http://www.php.net/manual/en/functions.variable-functions.php) ### [Variable](http://www.php.net/manual/en/functions.variable-functions.php)
@ -355,7 +382,11 @@ Similar to variable functions, functions may be anonymous.
```php ```php
<?php <?php
my_function(function () { function my_function($callback) {
$callback('My argument');
}
my_function(function ($my_argument) {
// do something // do something
}); });
@ -395,13 +426,11 @@ methods if they belong to a class.
class MyClass { class MyClass {
function myFunction() { function myFunction() {
} }
function function youCannotOverrideMe() final function youCannotOverrideMe() {
{
} }
public static function myStaticMethod() public static function myStaticMethod() {
{
} }
} }
@ -421,12 +450,12 @@ PHP offers some [magic methods](http://www.php.net/manual/en/language.oop5.magic
class MyClass { class MyClass {
private $property; private $property;
public function __get($key) public function __get($key)
{ {
return $this->$key; return $this->$key;
} }
public function __set($key, $value) public function __set($key, $value)
{ {
$this->$key = $value; $this->$key = $value;
@ -438,7 +467,8 @@ echo $x->property; // Will use the __get() method
$x->property = 'Something'; // Will use the __set() method $x->property = 'Something'; // Will use the __set() method
``` ```
Classes can be abstract (using the ```abstract``` keyword), extend other classes (using the ```extends``` keyword) and implement interfaces (using the ```implements``` keyword). An interface is declared with the ```interface``` keyword. Classes can be abstract (using the ```abstract``` keyword), extend other classes (using the ```extends``` keyword) and
implement interfaces (using the ```implements``` keyword). An interface is declared with the ```interface``` keyword.
```php ```php
<?php <?php

View File

@ -26,7 +26,7 @@ to Python 2.x. Look for another tour of Python 3 soon!
# Math is what you would expect # Math is what you would expect
1 + 1 #=> 2 1 + 1 #=> 2
8 - 1 #=> 9 8 - 1 #=> 7
10 * 2 #=> 20 10 * 2 #=> 20
35 / 5 #=> 7 35 / 5 #=> 7
@ -49,11 +49,24 @@ False
not True #=> False not True #=> False
not False #=> True not False #=> True
# Equality is == # Equality is ==
1 == 1 #=> True 1 == 1 #=> True
2 == 1 #=> False 2 == 1 #=> False
# Inequality is !=
1 != 1 #=> False
2 != 1 #=> True
# More comparisons
1 < 10 #=> True
1 > 10 #=> False
2 <= 2 #=> True
2 >= 2 #=> True
# Comparisons can be chained !
1 < 2 < 3 #=> True
2 < 3 < 2 #=> False
# Strings are created with " or ' # Strings are created with " or '
"This is a string." "This is a string."
'This is also a string.' 'This is also a string.'
@ -81,8 +94,15 @@ some_var = 5 # Convention is to use lower_case_with_underscores
some_var #=> 5 some_var #=> 5
# Accessing a previously unassigned variable is an exception # Accessing a previously unassigned variable is an exception
some_other_var # Will raise a NameError try:
some_other_var
except NameError:
print "Raises a name error"
# Conditional Expressions can be used when assigning
some_var = a if a > b else b
# If a is greater than b, then a is assigned to some_var.
# Otherwise b is assigned to some_var.
# Lists store sequences # Lists store sequences
li = [] li = []
@ -102,11 +122,16 @@ li.append(3) # li is now [1, 2, 4, 3] again.
# Access a list like you would any array # Access a list like you would any array
li[0] #=> 1 li[0] #=> 1
# Look at the last element # Look at the last element
li[-1] #=> 4 li[-1] #=> 3
# Looking out of bounds is an IndexError
li[4] # Raises an IndexError
# You can look at ranges with slice syntax. It's an closed/open range for you mathy types. # Looking out of bounds is an IndexError
try:
li[4] # Raises an IndexError
except IndexError:
print "Raises an IndexError"
# You can look at ranges with slice syntax.
# (It's a closed/open range for you mathy types.)
li[1:3] #=> [2, 4] li[1:3] #=> [2, 4]
# Omit the beginning # Omit the beginning
li[:3] #=> [1, 2, 4] li[:3] #=> [1, 2, 4]
@ -120,7 +145,7 @@ del li[2] # li is now [1, 2, 3]
li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li and other_li is left alone li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li and other_li is left alone
# Concatenate lists with extend # Concatenate lists with extend
li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6]
# Check for existence in a list with in # Check for existence in a list with in
1 in li #=> True 1 in li #=> True
@ -131,7 +156,10 @@ len(li) #=> 6
# Tuples are like lists but are immutable. # Tuples are like lists but are immutable.
tup = (1, 2, 3) tup = (1, 2, 3)
tup[0] #=> 1 tup[0] #=> 1
tup[0] = 3 # Raises a TypeError try:
tup[0] = 3 # Raises a TypeError
except TypeError:
print "Tuples cannot be mutated."
# You can do all those list thingies on tuples too # You can do all those list thingies on tuples too
len(tup) #=> 3 len(tup) #=> 3
@ -143,7 +171,7 @@ tup[:2] #=> (1, 2)
a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3
# Tuples are created by default if you leave out the parentheses # Tuples are created by default if you leave out the parentheses
d, e, f = 4, 5, 6 d, e, f = 4, 5, 6
# Now look how easy it is to swap to values # Now look how easy it is to swap two values
e, d = d, e # d is now 5 and e is now 4 e, d = d, e # d is now 5 and e is now 4
@ -168,6 +196,21 @@ filled_dict.values() #=> [3, 2, 1]
"one" in filled_dict #=> True "one" in filled_dict #=> True
1 in filled_dict #=> False 1 in filled_dict #=> False
# Trying to look up a non-existing key will raise a KeyError
filled_dict["four"] #=> KeyError
# Use get method to avoid the KeyError
filled_dict.get("one") #=> 1
filled_dict.get("four") #=> None
# The get method supports a default argument when the value is missing
filled_dict.get("one", 4) #=> 1
filled_dict.get("four", 4) #=> 4
# Setdefault method is a safe way to add new key-value pair into dictionary
filled_dict.setdefault("five", 5) #filled_dict["five"] is set to 5
filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5
# Sets store ... well sets # Sets store ... well sets
empty_set = set() empty_set = set()
@ -216,14 +259,14 @@ prints:
""" """
for animal in ["dog", "cat", "mouse"]: for animal in ["dog", "cat", "mouse"]:
# You can use % to interpolate formatted strings # You can use % to interpolate formatted strings
print "%s is a mammal" % animal print "%s is a mammal" % animal
""" """
While loops go until a condition is no longer met. While loops go until a condition is no longer met.
prints: prints:
0 0
1 1
2 2
3 3
""" """
x = 0 x = 0
@ -232,11 +275,20 @@ while x < 4:
x += 1 # Shorthand for x = x + 1 x += 1 # Shorthand for x = x + 1
# Handle exceptions with a try/except block # Handle exceptions with a try/except block
# Works on Python 2.6 and up:
try: try:
raise IndexError("This is an index error") # Use raise to raise an error # Use raise to raise an error
raise IndexError("This is an index error")
except IndexError as e: except IndexError as e:
pass # Pass is just a no-op. Usually you would do recovery here. pass # Pass is just a no-op. Usually you would do recovery here.
# Works for Python 2.7 and down:
try:
raise IndexError("This is an index error")
except IndexError, e: # No "as", comma instead
pass
#################################################### ####################################################
## 4. Functions ## 4. Functions
@ -252,20 +304,38 @@ add(5, 6) #=> 11 and prints out "x is 5 and y is 6"
# Another way to call functions is with keyword arguments # Another way to call functions is with keyword arguments
add(y=6, x=5) # Keyword arguments can arrive in any order. add(y=6, x=5) # Keyword arguments can arrive in any order.
# You can define functions that take a variable number of positional arguments # You can define functions that take a variable number of
# positional arguments
def varargs(*args): def varargs(*args):
return args return args
varargs(1, 2, 3) #=> (1,2,3) varargs(1, 2, 3) #=> (1,2,3)
# You can define functions that take a variable number of keyword arguments # You can define functions that take a variable number of
# keyword arguments, as well
def keyword_args(**kwargs): def keyword_args(**kwargs):
return kwargs return kwargs
# Let's call it to see what happens # Let's call it to see what happens
keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
# You can do both at once, if you like
def all_the_args(*args, **kwargs):
print args
print kwargs
"""
all_the_args(1, 2, a=3, b=4) prints:
[1, 2]
{"a": 3, "b": 4}
"""
# You can also use * and ** when calling a function
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
foo(*args) # equivalent to foo(1, 2, 3, 4)
foo(**kwargs) # equivalent to foo(a=3, b=4)
foo(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4)
# Python has first class functions # Python has first class functions
def create_adder(x): def create_adder(x):
@ -273,7 +343,7 @@ def create_adder(x):
return x + y return x + y
return adder return adder
add_10 = create_adder(10): add_10 = create_adder(10)
add_10(3) #=> 13 add_10(3) #=> 13
# There are also anonymous functions # There are also anonymous functions
@ -329,9 +399,11 @@ print j.say("hello") #prints out "Joel: hello"
i.get_species() #=> "H. sapiens" i.get_species() #=> "H. sapiens"
# Change the shared attribute # Change the shared attribute
i.species = "H. neanderthalensis" Human.species = "H. neanderthalensis"
i.get_species() #=> "H. neanderthalensis" i.get_species() #=> "H. neanderthalensis"
j.get_species() #=> "H. neanderthalensis" j.get_species() #=> "H. neanderthalensis"
# Call the static method # Call the static method
Human.grunt() #=> "*grunt*" Human.grunt() #=> "*grunt*"
```