diff --git a/tests/results/1 b/tests/results/1 index b83ed07..8b7a51e 100644 --- a/tests/results/1 +++ b/tests/results/1 @@ -1,10 +1,12 @@ +1_Inheritance 1line +2_Multiple_Inheritance :learn :list Advanced Classes Comments -Control_Flow +Control_Flow_and_Iterables Functions Modules Primitive_Datatypes_and_Operators @@ -13,6 +15,7 @@ doc func hello lambda +list_comprehension loops recursion rosetta/ diff --git a/tests/results/15 b/tests/results/15 index bc1df86..237ec80 100644 --- a/tests/results/15 +++ b/tests/results/15 @@ -1,361 +1,384 @@ -# Single line comments start with a number symbol. +# Single line comments start with a number symbol. """ Multiline strings can be written  using three "s, and are often used - as comments + as documentation. """ -#################################################### -# 1. Primitive Datatypes and Operators -#################################################### +#################################################### +## 1. Primitive Datatypes and Operators +#################################################### -# You have numbers -3 # => 3 +# You have numbers +3 # => 3 -# Math is what you would expect -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 -35 / 5 # => 7 +# Math is what you would expect +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 -# Division is a bit tricky. It is integer division and floors the results -# automatically. -5 / 2 # => 2 +# Integer division rounds down for both positive and negative numbers. +5 // 3 # => 1 +-5 // 3 # => -2 +5.0 // 3.0 # => 1.0 # works on floats too +-5.0 // 3.0 # => -2.0 -# To fix division we need to learn about floats. -2.0 # This is a float -11.0 / 4.0 # => 2.75 ahhh...much better +# The result of division is always a float +10.0 / 3 # => 3.3333333333333335 -# Result of integer division truncated down both for positive and negative. -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 +# Modulo operation +7 % 3 # => 1 -# Note that we can also import division module(Section 6 Modules) -# to carry out normal division with just one '/'. -from __future__ import division +# Exponentiation (x**y, x to the yth power) +2**3 # => 8 -11 / 4 # => 2.75 ...normal division -11 // 4 # => 2 ...floored division +# Enforce precedence with parentheses +1 + 3 * 2 # => 7 +(1 + 3) * 2 # => 8 -# Modulo operation -7 % 3 # => 1 +# Boolean values are primitives (Note: the capitalization) +True # => True +False # => False -# Exponentiation (x to the yth power) -2 ** 4 # => 16 +# negate with not +not True # => False +not False # => True -# Enforce precedence with parentheses -(1 + 3) * 2 # => 8 +# Boolean Operators +# Note "and" and "or" are case-sensitive +True and False # => False +False or True # => True -# Boolean Operators -# Note "and" and "or" are case-sensitive -True and False # => False -False or True # => True +# True and False are actually 1 and 0 but with different keywords +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 -# Note using Bool operators with ints -0 and 2 # => 0 --5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True +# Comparison operators look at the numerical value of True and False +0 == False # => True +1 == True # => True +2 == True # => False +-5 != False # => True -# negate with not -not True # => False -not False # => True +# Using boolean logical operators on ints casts them to booleans for evaluation, but their non-cast value is returned +# Don't mix up with bool(ints) and bitwise and/or (&,|) +bool(0) # => False +bool(4) # => True +bool(-6) # => True +0 and 2 # => 0 +-5 or 0 # => -5 -# Equality is == -1 == 1 # => True -2 == 1 # => False +# Equality is == +1 == 1 # => True +2 == 1 # => False -# Inequality is != -1 != 1 # => False -2 != 1 # => True +# Inequality is != +1 != 1 # => False +2 != 1 # => True -# More comparisons -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => 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 +# Seeing whether a value is in a range +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# Chaining makes this look nicer +1 < 2 < 3 # => True +2 < 3 < 2 # => False -# Strings are created with " or ' +# (is vs. ==) is checks if two variables refer to the same object, but == checks +# if the objects pointed to have the same values. +a = [1, 2, 3, 4] # Point a at a new list, [1, 2, 3, 4] +b = a # Point b at what a is pointing to +b is a # => True, a and b refer to the same object +b == a # => True, a's and b's objects are equal +b = [1, 2, 3, 4] # Point b at a new list, [1, 2, 3, 4] +b is a # => False, a and b do not refer to the same object +b == a # => True, a's and b's objects are equal + +# Strings are created with " or ' "This is a string." 'This is also a string.' -# Strings can be added too! -"Hello " + "world!" # => "Hello world!" -# Strings can be added without using '+' -"Hello " "world!" # => "Hello world!" +# Strings can be added too! But try not to do this. +"Hello " + "world!" # => "Hello world!" +# String literals (but not variables) can be concatenated without using '+' +"Hello " "world!" # => "Hello world!" -# ... or multiplied -"Hello" * 3 # => "HelloHelloHello" +# A string can be treated like a list of characters +"Hello world!"[0] # => 'H' -# A string can be treated like a list of characters -"This is a string"[0] # => 'T' +# You can find the length of a string +len("This is a string") # => 16 -# You can find the length of a string -len("This is a string") # => 16 - -# String formatting with % -# Even though the % string operator will be deprecated on Python 3.1 and removed -# later at some time, it may still be good to know how it works. -x = 'apple' -y = 'lemon' -z = "The items in the basket are %s and %s" % (x, y) - -# A newer way to format strings is the format method. -# This method is the preferred way -"{} is a {}".format("This", "placeholder") -"{0} can be {1}".format("strings", "formatted") -# You can use keywords if you don't want to count. -"{name} wants to eat {food}".format(name="Bob", food="lasagna") - -# None is an object -None # => None - -# Don't use the equality "==" symbol to compare objects to None -# Use "is" instead -"etc" is None # => False -None is None # => True - -# The 'is' operator tests for object identity. This isn't -# very useful when dealing with primitive values, but is -# very useful when dealing with objects. - -# Any object can be used in a Boolean context. -# The following values are considered falsey: -# - None -# - zero of any numeric type (e.g., 0, 0L, 0.0, 0j) -# - empty sequences (e.g., '', (), []) -# - empty containers (e.g., {}, set()) -# - instances of user-defined classes meeting certain conditions -# see: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ -# -# All other values are truthy (using the bool() function on them returns True). -bool(0) # => False -bool("") # => False +# You can also format using f-strings or formatted string literals (in Python 3.6+) +name = "Reiko" +f"She said her name is {name}." # => "She said her name is Reiko" +# You can basically put any Python statement inside the braces and it will be output in the string. +f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." -#################################################### -# 2. Variables and Collections -#################################################### +# None is an object +None # => None -# Python has a print statement -print "I'm Python. Nice to meet you!" # => I'm Python. Nice to meet you! +# Don't use the equality "==" symbol to compare objects to None +# Use "is" instead. This checks for equality of object identity. +"etc" is None # => False +None is None # => True -# Simple way to get input data from console -input_string_var = raw_input( - "Enter some data: ") # Returns the data as a string -input_var = input("Enter some data: ") # Evaluates the data as python code -# Warning: Caution is recommended for input() method usage -# Note: In python 3, input() is deprecated and raw_input() is renamed to input() +# None, 0, and empty strings/lists/dicts/tuples all evaluate to False. +# All other values are True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False -# No need to declare variables before assigning to them. -some_var = 5 # Convention is to use lower_case_with_underscores -some_var # => 5 +#################################################### +## 2. Variables and Collections +#################################################### -# Accessing a previously unassigned variable is an exception. -# See Control Flow to learn more about exception handling. -some_other_var # Raises a name error +# Python has a print function +print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! -# if can be used as an expression -# Equivalent of C's '?:' ternary operator -"yahoo!" if 3 > 2 else 2 # => "yahoo!" +# By default the print function also prints out a newline at the end. +# Use the optional argument end to change the end string. +print("Hello, World", end="!") # => Hello, World! -# Lists store sequences +# Simple way to get input data from console +input_string_var = input("Enter some data: ") # Returns the data as a string +# Note: In earlier versions of Python, input() method was named as raw_input() + +# There are no declarations, only assignments. +# Convention is to use lower_case_with_underscores +some_var = 5 +some_var # => 5 + +# Accessing a previously unassigned variable is an exception. +# See Control Flow to learn more about exception handling. +some_unknown_var # Raises a NameError + +# if can be used as an expression +# Equivalent of C's '?:' ternary operator +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# Lists store sequences li = [] -# You can start with a prefilled list +# You can start with a prefilled list other_li = [4, 5, 6] -# Add stuff to the end of a list with append -li.append(1) # li is now [1] -li.append(2) # li is now [1, 2] -li.append(4) # li is now [1, 2, 4] -li.append(3) # li is now [1, 2, 4, 3] -# Remove from the end with pop -li.pop() # => 3 and li is now [1, 2, 4] -# Let's put it back -li.append(3) # li is now [1, 2, 4, 3] again. +# Add stuff to the end of a list with append +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] +# Remove from the end with pop +li.pop() # => 3 and li is now [1, 2, 4] +# Let's put it back +li.append(3) # li is now [1, 2, 4, 3] again. -# Access a list like you would any array -li[0] # => 1 -# Assign new values to indexes that have already been initialized with = -li[0] = 42 -li[0] # => 42 -li[0] = 1 # Note: setting it back to the original value -# Look at the last element -li[-1] # => 3 +# Access a list like you would any array +li[0] # => 1 +# Look at the last element +li[-1] # => 3 -# Looking out of bounds is an IndexError -li[4] # Raises an IndexError +# Looking out of bounds is an IndexError +li[4] # 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] -# Omit the beginning -li[2:] # => [4, 3] -# Omit the end -li[:3] # => [1, 2, 4] -# Select every second entry -li[::2] # =>[1, 4] -# Reverse a copy of the list -li[::-1] # => [3, 4, 2, 1] -# Use any combination of these to make advanced slices -# li[start:end:step] +# You can look at ranges with slice syntax. +# The start index is included, the end index is not +# (It's a closed/open range for you mathy types.) +li[1:3] # Return list from index 1 to 3 => [2, 4] +li[2:] # Return list starting from index 2 => [4, 3] +li[:3] # Return list from beginning until index 3 => [1, 2, 4] +li[::2] # Return list selecting every second entry => [1, 4] +li[::-1] # Return list in reverse order => [3, 4, 2, 1] +# Use any combination of these to make advanced slices +# li[start:end:step] -# Remove arbitrary elements from a list with "del" -del li[2] # li is now [1, 2, 3] +# Make a one layer deep copy using slices +li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false. -# You can add lists -li + other_li # => [1, 2, 3, 4, 5, 6] -# Note: values for li and for other_li are not modified. +# Remove arbitrary elements from a list with "del" +del li[2] # li is now [1, 2, 3] -# Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] +# Remove first occurrence of a value +li.remove(2) # li is now [1, 3] +li.remove(2) # Raises a ValueError as 2 is not in the list -# Remove first occurrence of a value -li.remove(2) # li is now [1, 3, 4, 5, 6] -li.remove(2) # Raises a ValueError as 2 is not in the list +# Insert an element at a specific index +li.insert(1, 2) # li is now [1, 2, 3] again -# Insert an element at a specific index -li.insert(1, 2) # li is now [1, 2, 3, 4, 5, 6] again +# Get the index of the first item found matching the argument +li.index(2) # => 1 +li.index(4) # Raises a ValueError as 4 is not in the list -# Get the index of the first item found -li.index(2) # => 1 -li.index(7) # Raises a ValueError as 7 is not in the list +# You can add lists +# Note: values for li and for other_li are not modified. +li + other_li # => [1, 2, 3, 4, 5, 6] -# Check for existence in a list with "in" -1 in li # => True +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] -# Examine the length with "len()" -len(li) # => 6 +# Check for existence in a list with "in" +1 in li # => True -# Tuples are like lists but are immutable. +# Examine the length with "len()" +len(li) # => 6 + + +# Tuples are like lists but are immutable. tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # Raises a TypeError +tup[0] # => 1 +tup[0] = 3 # Raises a TypeError -# You can do all those list thingies on tuples too -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True +# Note that a tuple of length one has to have a comma after the last element but +# tuples of other lengths, even zero, do not. +type((1)) # =>  +type((1,)) # =>  +type(()) # =>  -# You can unpack tuples (or lists) into variables -a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 -d, e, f = 4, 5, 6 # you can leave out the parentheses -# Tuples are created by default if you leave out the parentheses -g = 4, 5, 6 # => (4, 5, 6) -# Now look how easy it is to swap two values -e, d = d, e # d is now 5 and e is now 4 +# You can do most of the list operations on tuples too +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True -# Dictionaries store mappings +# You can unpack tuples (or lists) into variables +a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 +# You can also do extended unpacking +a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4 +# Tuples are created by default if you leave out the parentheses +d, e, f = 4, 5, 6 # tuple 4, 5, 6 is unpacked into variables d, e and f +# respectively such that d = 4, e = 5 and f = 6 +# Now look how easy it is to swap two values +e, d = d, e # d is now 5 and e is now 4 + + +# Dictionaries store mappings from keys to values empty_dict = {} -# Here is a prefilled dictionary +# Here is a prefilled dictionary filled_dict = {"one": 1, "two": 2, "three": 3} -# Look up values with [] -filled_dict["one"] # => 1 +# Note keys for dictionaries have to be immutable types. This is to ensure that +# the key can be converted to a constant hash value for quick look-ups. +# Immutable types include ints, floats, strings, tuples. +invalid_dict = {[1,2,3]: "123"} # => Raises a TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Values can be of any type, however. -# Get all keys as a list with "keys()" -filled_dict.keys() # => ["three", "two", "one"] -# Note - Dictionary key ordering is not guaranteed. -# Your results might not match this exactly. +# Look up values with [] +filled_dict["one"] # => 1 -# Get all values as a list with "values()" -filled_dict.values() # => [3, 2, 1] -# Note - Same as above regarding key ordering. +# Get all keys as an iterable with "keys()". We need to wrap the call in list() +# to turn it into a list. We'll talk about those later. Note - for Python +# versions <3.7, dictionary key ordering is not guaranteed. Your results might +# not match the example below exactly. However, as of Python 3.7, dictionary +# items maintain the order at which they are inserted into the dictionary. +list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+ -# Get all key-value pairs as a list of tuples with "items()" -filled_dict.items() # => [("one", 1), ("two", 2), ("three", 3)] -# Check for existence of keys in a dictionary with "in" -"one" in filled_dict # => True -1 in filled_dict # => False +# Get all values as an iterable with "values()". Once again we need to wrap it +# in list() to get it out of the iterable. Note - Same as above regarding key +# ordering. +list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ -# Looking up a non-existing key is a KeyError -filled_dict["four"] # KeyError +# Check for existence of keys in a dictionary with "in" +"one" in filled_dict # => True +1 in filled_dict # => False -# 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 -# note that filled_dict.get("four") is still => None -# (get doesn't set the value in the dictionary) +# Looking up a non-existing key is a KeyError +filled_dict["four"] # KeyError -# set the value of a key with a syntax similar to lists -filled_dict["four"] = 4 # now, filled_dict["four"] => 4 +# 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()" inserts into a dictionary only if the given key isn't present -filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 +# "setdefault()" inserts into a dictionary only if the given key isn't present +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 -# You can declare sets (which are like unordered lists that cannot contain -# duplicate values) using the set object. +# Adding to a dictionary +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # another way to add to dict + +# Remove keys from a dictionary with del +del filled_dict["one"] # Removes the key "one" from filled dict + +# From Python 3.5 you can also use the additional unpacking options +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + + + +# Sets store ... well sets empty_set = set() -# Initialize a "set()" with a bunch of values -some_set = set([1, 2, 2, 3, 4]) # some_set is now set([1, 2, 3, 4]) +# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry. +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} -# order is not guaranteed, even though it may sometimes look sorted -another_set = set([4, 3, 2, 2, 1]) # another_set is now set([1, 2, 3, 4]) +# Similar to keys of a dictionary, elements of a set have to be immutable. +invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Since Python 2.7, {} can be used to declare a set -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Add one more item to the set +filled_set = some_set +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +# Sets do not have duplicate elements +filled_set.add(5) # it remains as before {1, 2, 3, 4, 5} -# Add more items to a set -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} - -# Do set intersection with & +# Do set intersection with & other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} +filled_set & other_set # => {3, 4, 5} -# Do set union with | -filled_set | other_set # => {1, 2, 3, 4, 5, 6} +# Do set union with | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# Do set difference with - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} +# Do set difference with - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# Do set symmetric difference with ^ -{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} +# Do set symmetric difference with ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} -# Check if set on the left is a superset of set on the right -{1, 2} >= {1, 2, 3} # => False +# Check if set on the left is a superset of set on the right +{1, 2} >= {1, 2, 3} # => False -# Check if set on the left is a subset of set on the right -{1, 2} <= {1, 2, 3} # => True +# Check if set on the left is a subset of set on the right +{1, 2} <= {1, 2, 3} # => True -# Check for existence in a set with in -2 in filled_set # => True -10 in filled_set # => False -10 not in filled_set # => True +# Check for existence in a set with in +2 in filled_set # => True +10 in filled_set # => False -# Check data type of variable -type(li) # => list -type(filled_dict) # => dict -type(5) # => int +# Make a one layer deep copy +filled_set = some_set.copy() # filled_set is {1, 2, 3, 4, 5} +filled_set is some_set # => False -#################################################### -# 3. Control Flow -#################################################### +#################################################### +## 3. Control Flow and Iterables +#################################################### -# Let's just make a variable +# Let's just make a variable some_var = 5 -# Here is an if statement. Indentation is significant in python! -# prints "some_var is smaller than 10" +# Here is an if statement. Indentation is significant in Python! +# Convention is to use four spaces, not tabs. +# This prints "some_var is smaller than 10" if some_var > 10: - print "some_var is totally bigger than 10." -elif some_var < 10: # This elif clause is optional. - print "some_var is smaller than 10." -else: # This is optional too. - print "some_var is indeed 10." + print("some_var is totally bigger than 10.") +elif some_var < 10: # This elif clause is optional. + print("some_var is smaller than 10.") +else: # This is optional too. + print("some_var is indeed 10.") + """ For loops iterate over lists @@ -365,11 +388,11 @@  mouse is a mammal """ for animal in ["dog", "cat", "mouse"]: - # You can use {0} to interpolate formatted strings. (See above.) - print "{0} is a mammal".format(animal) + # You can use format() to interpolate formatted strings + print("{} is a mammal".format(animal)) """ -"range(number)" returns a list of numbers +"range(number)" returns an iterable of numbers from zero to the given number prints:  0 @@ -378,10 +401,10 @@  3 """ for i in range(4): - print i + print(i) """ -"range(lower, upper)" returns a list of numbers +"range(lower, upper)" returns an iterable of numbers from the lower number to the upper number prints:  4 @@ -390,7 +413,29 @@  7 """ for i in range(4, 8): - print i + print(i) + +""" +"range(lower, upper, step)" returns an iterable of numbers +from the lower number to the upper number, while incrementing +by step. If step is not indicated, the default value is 1. +prints: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +To loop over a list, and retrieve both the index and the value of each item in the list +prints: + 0 dog + 1 cat + 2 mouse +""" +animals = ["dog", "cat", "mouse"] +for i, value in enumerate(animals): + print(i, value) """ While loops go until a condition is no longer met. @@ -402,353 +447,537 @@ """ x = 0 while x < 4: - print x - x += 1 # Shorthand for x = x + 1 + print(x) + x += 1 # Shorthand for x = x + 1 -# Handle exceptions with a try/except block - -# Works on Python 2.6 and up: +# Handle exceptions with a try/except block try: - # Use "raise" to raise an error + # Use "raise" to raise an error  raise IndexError("This is an index error") 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. except (TypeError, NameError): - pass # Multiple exceptions can be handled together, if required. -else: # Optional clause to the try/except block. Must follow all except blocks - print "All good!" # Runs only if the code in try raises no exceptions -finally: # Execute under all circumstances - print "We can clean up resources here" + pass # Multiple exceptions can be handled together, if required. +else: # Optional clause to the try/except block. Must follow all except blocks + print("All good!") # Runs only if the code in try raises no exceptions +finally: # Execute under all circumstances + print("We can clean up resources here") -# Instead of try/finally to cleanup resources you can use a with statement +# Instead of try/finally to cleanup resources you can use a with statement with open("myfile.txt") as f:  for line in f: - print line + print(line) + +# Writing to a file +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w+") as file: + file.write(str(contents)) # writes a string to a file + +with open("myfile2.txt", "w+") as file: + file.write(json.dumps(contents)) # writes an object to a file + +# Reading from a file +with open('myfile1.txt', "r+") as file: + contents = file.read() # reads a string from a file +print(contents) +# print: {"aa": 12, "bb": 21} + +with open('myfile2.txt', "r+") as file: + contents = json.load(file) # reads a json object from a file +print(contents)  +# print: {"aa": 12, "bb": 21} -#################################################### -# 4. Functions -#################################################### +# Python offers a fundamental abstraction called the Iterable. +# An iterable is an object that can be treated as a sequence. +# The object returned by the range function, is an iterable. -# Use "def" to create new functions +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']). This is an object that implements our Iterable interface. + +# We can loop over it. +for i in our_iterable: + print(i) # Prints one, two, three + +# However we cannot address elements by index. +our_iterable[1] # Raises a TypeError + +# An iterable is an object that knows how to create an iterator. +our_iterator = iter(our_iterable) + +# Our iterator is an object that can remember the state as we traverse through it. +# We get the next object with "next()". +next(our_iterator) # => "one" + +# It maintains state as we iterate. +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# After the iterator has returned all of its data, it raises a StopIteration exception +next(our_iterator) # Raises StopIteration + +# We can also loop over it, in fact, "for" does this implicitly! +our_iterator = iter(our_iterable) +for i in our_iterator: + print(i) # Prints one, two, three + +# You can grab all the elements of an iterable or iterator by calling list() on it. +list(our_iterable) # => Returns ["one", "two", "three"] +list(our_iterator) # => Returns [] because state is saved + + +#################################################### +## 4. Functions +#################################################### + +# Use "def" to create new functions def add(x, y): - print "x is {0} and y is {1}".format(x, y) - return x + y # Return values with a return statement + print("x is {} and y is {}".format(x, y)) + return x + y # Return values with a return statement +# Calling functions with parameters +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 -# Calling functions with parameters -add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 +# Another way to call functions is with keyword arguments +add(y=6, x=5) # Keyword arguments can arrive in any order. -# Another way to call functions is with keyword arguments -add(y=6, x=5) # Keyword arguments can arrive in any order. - - -# You can define functions that take a variable number of -# positional args, which will be interpreted as a tuple by using * +# You can define functions that take a variable number of +# positional arguments def varargs(*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 args, as well, which will be interpreted as a dict by using ** +# You can define functions that take a variable number of +# keyword arguments, as well def keyword_args(**kwargs):  return kwargs - -# Let's call it to see what happens -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} +# Let's call it to see what happens +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} -# You can do both at once, if you like +# You can do both at once, if you like def all_the_args(*args, **kwargs): - print args - print kwargs - - + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) prints:  (1, 2)  {"a": 3, "b": 4} """ -# When calling functions, you can do the opposite of args/kwargs! -# Use * to expand positional args and use ** to expand keyword args. +# When calling functions, you can do the opposite of args/kwargs! +# Use * to expand tuples and use ** to expand kwargs. args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to all_the_args(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to all_the_args(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4) +all_the_args(*args) # equivalent to all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4) +# Returning multiple values (with tuple assignments) +def swap(x, y): + return y, x # Return multiple values as a tuple without the parenthesis. + # (Note: parenthesis have been excluded but can be included) -# you can pass args and kwargs along to other functions that take args/kwargs -# by expanding them with * and ** respectively -def pass_all_the_args(*args, **kwargs): - all_the_args(*args, **kwargs) - print varargs(*args) - print keyword_args(**kwargs) +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Again parenthesis have been excluded but can be included. - -# Function Scope +# Function Scope x = 5 - def set_x(num): - # Local var x not the same as global variable x - x = num # => 43 - print x # => 43 - + # Local var x not the same as global variable x + x = num # => 43 + print(x) # => 43 def set_global_x(num):  global x - print x # => 5 - x = num # global var x is now set to 6 - print x # => 6 - + print(x) # => 5 + x = num # global var x is now set to 6 + print(x) # => 6 set_x(43) set_global_x(6) -# Python has first class functions +# Python has first class functions def create_adder(x):  def adder(y):  return x + y -  return adder - add_10 = create_adder(10) -add_10(3) # => 13 +add_10(3) # => 13 -# There are also anonymous functions -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 +# There are also anonymous functions +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 -# There are built-in higher order functions -map(add_10, [1, 2, 3]) # => [11, 12, 13] -map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] +# There are built-in higher order functions +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] -# We can use list comprehensions for nice maps and filters -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] +# We can use list comprehensions for nice maps and filters +# List comprehension stores the output as a list which can itself be a nested list +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] -# You can construct set and dict comprehensions as well. -{x for x in 'abcddeef' if x in 'abc'} # => {'a', 'b', 'c'} -{x: x ** 2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} +# You can construct set and dict comprehensions as well. +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} -#################################################### -# 5. Classes -#################################################### +#################################################### +## 5. Modules +#################################################### -# We subclass from object to get a class. -class Human(object): - # A class attribute. It is shared by all instances of this class +# You can import modules +import math +print(math.sqrt(16)) # => 4.0 + +# You can get specific functions from a module +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# You can import all functions from a module. +# Warning: this is not recommended +from math import * + +# You can shorten module names +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Python modules are just ordinary Python files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# are defined in a module. +import math +dir(math) + +# If you have a Python script named math.py in the same +# folder as your current script, the file math.py will +# be loaded instead of the built-in Python module. +# This happens because the local folder has priority +# over Python's built-in libraries. + + +#################################################### +## 6. Classes +#################################################### + +# We use the "class" statement to create a class +class Human: + + # A class attribute. It is shared by all instances of this class  species = "H. sapiens" - # Basic initializer, this is called when this class is instantiated. - # Note that the double leading and trailing underscores denote objects - # or attributes that are used by python but that live in user-controlled - # namespaces. You should not invent such names on your own. + # Basic initializer, this is called when this class is instantiated. + # Note that the double leading and trailing underscores denote objects + # or attributes that are used by Python but that live in user-controlled + # namespaces. Methods(or objects or attributes) like: __init__, __str__, + # __repr__ etc. are called special methods (or sometimes called dunder methods) + # You should not invent such names on your own.  def __init__(self, name): - # Assign the argument to the instance's name attribute + # Assign the argument to the instance's name attribute  self.name = name - # Initialize property - self.age = 0 + # Initialize property + self._age = 0 - # An instance method. All methods take "self" as the first argument + # An instance method. All methods take "self" as the first argument  def say(self, msg): - return "{0}: {1}".format(self.name, msg) + print("{name}: {message}".format(name=self.name, message=msg)) - # A class method is shared among all instances - # They are called with the calling class as the first argument + # Another instance method + def sing(self): + return 'yo... yo... microphone check... one two... one two...' + + # A class method is shared among all instances + # They are called with the calling class as the first argument  @classmethod  def get_species(cls):  return cls.species - # A static method is called without a class or instance reference + # A static method is called without a class or instance reference  @staticmethod  def grunt():  return "*grunt*" - # A property is just like a getter. - # It turns the method age() into an read-only attribute - # of the same name. + # A property is just like a getter. + # It turns the method age() into an read-only attribute of the same name. + # There's no need to write trivial getters and setters in Python, though.  @property  def age(self):  return self._age - # This allows the property to be set - @age.setter + # This allows the property to be set + @age.setter  def age(self, age):  self._age = age - # This allows the property to be deleted - @age.deleter + # This allows the property to be deleted + @age.deleter  def age(self):  del self._age -# Instantiate a class -i = Human(name="Ian") -print i.say("hi") # prints out "Ian: hi" +# When a Python interpreter reads a source file it executes all its code. +# This __name__ check makes sure this code block is only executed when this +# module is the main program. +if __name__ == '__main__': + # Instantiate a class + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i and j are instances of type Human, or in other words: they are Human objects -j = Human("Joel") -print j.say("hello") # prints out "Joel: hello" + # Call our class method + i.say(i.get_species()) # "Ian: H. sapiens" + # Change the shared attribute + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" -# Call our class method -i.get_species() # => "H. sapiens" + # Call the static method + print(Human.grunt()) # => "*grunt*" -# Change the shared attribute -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" + # Cannot call static method with instance of object + # because i.grunt() will automatically put "self" (the object i) as an argument + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given -# Call the static method -Human.grunt() # => "*grunt*" - -# Update the property -i.age = 42 - -# Get the property -i.age # => 42 - -# Delete the property -del i.age -i.age # => raises an AttributeError - -#################################################### -# 6. Modules -#################################################### - -# You can import modules -import math - -print math.sqrt(16) # => 4.0 - -# You can get specific functions from a module -from math import ceil, floor - -print ceil(3.7) # => 4.0 -print floor(3.7) # => 3.0 - -# You can import all functions from a module. -# Warning: this is not recommended -from math import * - -# You can shorten module names -import math as m - -math.sqrt(16) == m.sqrt(16) # => True -# you can also test that the functions are equivalent -from math import sqrt - -math.sqrt == m.sqrt == sqrt # => True - -# Python modules are just ordinary python files. You -# can write your own, and import them. The name of the -# module is the same as the name of the file. - -# You can find out which functions and attributes -# defines a module. -import math - -dir(math) + # Update the property for this instance + i.age = 42 + # Get the property + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # Delete the property + del i.age + # i.age # => this would raise an AttributeError -# If you have a Python script named math.py in the same -# folder as your current script, the file math.py will -# be loaded instead of the built-in Python module. -# This happens because the local folder has priority -# over Python's built-in libraries. +#################################################### +## 6.1 Inheritance +#################################################### + +# Inheritance allows new child classes to be defined that inherit methods and +# variables from their parent class. + +# Using the Human class defined above as the base or parent class, we can +# define a child class, Superhero, which inherits the class variables like +# "species", "name", and "age", as well as methods, like "sing" and "grunt" +# from the Human class, but can also have its own unique properties. + +# To take advantage of modularization by file you could place the classes above in their own files, +# say, human.py + +# To import functions from other files use the following format +# from "filename-without-extension" import "function-or-class" + +from human import Human -#################################################### -# 7. Advanced -#################################################### +# Specify the parent class(es) as parameters to the class definition +class Superhero(Human): -# Generators -# A generator "generates" values as they are requested instead of storing -# everything up front + # If the child class should inherit all of the parent's definitions without + # any modifications, you can just use the "pass" keyword (and nothing else) + # but in this case it is commented out to allow for a unique child class: + # pass -# The following method (*NOT* a generator) will double all values and store it -# in `double_arr`. For large size of iterables, that might get huge! + # Child classes can override their parents' attributes + species = 'Superhuman' + + # Children automatically inherit their parent class's constructor including + # its arguments, but can also define additional arguments or definitions + # and override its methods such as the class constructor. + # This constructor inherits the "name" argument from the "Human" class and + # adds the "superpower" and "movie" arguments: + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # add additional class attributes: + self.fictional = True + self.movie = movie + # be aware of mutable default values, since defaults are shared + self.superpowers = superpowers + + # The "super" function lets you access the parent class's methods + # that are overridden by the child, in this case, the __init__ method. + # This calls the parent class constructor: + super().__init__(name) + + # override the sing method + def sing(self): + return 'Dun, dun, DUN!' + + # add an additional instance method + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # Instance type checks + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # Get the Method Resolution search Order used by both getattr() and super() + # This attribute is dynamic and can be updated + print(Superhero.__mro__) # => (, + # => , ) + + # Calls parent method but uses its own class attribute + print(sup.get_species()) # => Superhuman + + # Calls overridden method + print(sup.sing()) # => Dun, dun, DUN! + + # Calls method from Human + sup.say('Spoon') # => Tick: Spoon + + # Call method that exists only in Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Inherited class attribute + sup.age = 31 + print(sup.age) # => 31 + + # Attribute that only exists within Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) + +#################################################### +## 6.2 Multiple Inheritance +#################################################### + +# Another class definition +# bat.py +class Bat: + + species = 'Baty' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # This class also has a say method + def say(self, msg): + msg = '... ... ...' + return msg + + # And its own method as well + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + + +# And yet another class definition that inherits from Superhero and Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Define Batman as a child that inherits from both Superhero and Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # Typically to inherit attributes you have to call super: + # super(Batman, self).__init__(*args, **kwargs)  + # However we are dealing with multiple inheritance here, and super() + # only works with the next base class in the MRO list. + # So instead we explicitly call __init__ for all ancestors. + # The use of *args and **kwargs allows for a clean way to pass arguments, + # with each parent "peeling a layer of the onion". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # override the value for the name attribute + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # Get the Method Resolution search Order used by both getattr() and super(). + # This attribute is dynamic and can be updated + print(Batman.__mro__) # => (, + # => , + # => , + # => , ) + + # Calls parent method but uses its own class attribute + print(sup.get_species()) # => Superhuman + + # Calls overridden method + print(sup.sing()) # => nan nan nan nan nan batman! + + # Calls method from Human, because inheritance order matters + sup.say('I agree') # => Sad Affleck: I agree + + # Call method that exists only in 2nd ancestor + print(sup.sonar()) # => ))) ... ((( + + # Inherited class attribute + sup.age = 100 + print(sup.age) # => 100 + + # Inherited attribute from 2nd ancestor whose default value was overridden. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + + +#################################################### +## 7. Advanced +#################################################### + +# Generators help you make lazy code. def double_numbers(iterable): - double_arr = [] - for i in iterable: - double_arr.append(i + i) - return double_arr - - -# Running the following would mean we'll double all values first and return all -# of them back to be checked by our condition -for value in double_numbers(range(1000000)): # `test_non_generator` - print value - if value > 5: - break - - -# We could instead use a generator to "generate" the doubled value as the item -# is being requested -def double_numbers_generator(iterable):  for i in iterable:  yield i + i - -# Running the same code as before, but with a generator, now allows us to iterate -# over the values and doubling them one by one as they are being consumed by -# our logic. Hence as soon as we see a value > 5, we break out of the -# loop and don't need to double most of the values sent in (MUCH FASTER!) -for value in double_numbers_generator(xrange(1000000)): # `test_generator` - print value - if value > 5: +# Generators are memory-efficient because they only load the data needed to +# process the next value in the iterable. This allows them to perform +# operations on otherwise prohibitively large value ranges. +# NOTE: `range` replaces `xrange` in Python 3. +for i in double_numbers(range(1, 900000000)): # `range` is a generator. + print(i) + if i >= 30:  break -# BTW: did you notice the use of `range` in `test_non_generator` and `xrange` in `test_generator`? -# Just as `double_numbers_generator` is the generator version of `double_numbers` -# We have `xrange` as the generator version of `range` -# `range` would return back and array with 1000000 values for us to use -# `xrange` would generate 1000000 values for us as we request / iterate over those items - -# Just as you can create a list comprehension, you can create generator -# comprehensions as well. -values = (-x for x in [1, 2, 3, 4, 5]) +# Just as you can create a list comprehension, you can create generator +# comprehensions as well. +values = (-x for x in [1,2,3,4,5]) for x in values: - print(x) # prints -1 -2 -3 -4 -5 to console/terminal + print(x) # prints -1 -2 -3 -4 -5 to console/terminal -# You can also cast a generator comprehension directly to a list. -values = (-x for x in [1, 2, 3, 4, 5]) +# You can also cast a generator comprehension directly to a list. +values = (-x for x in [1,2,3,4,5]) gen_to_list = list(values) -print(gen_to_list) # => [-1, -2, -3, -4, -5] +print(gen_to_list) # => [-1, -2, -3, -4, -5] -# Decorators -# A decorator is a higher order function, which accepts and returns a function. -# Simple usage example – add_apples decorator will add 'Apple' element into -# fruits list returned by get_fruits target function. -def add_apples(func): - def get_fruits(): - fruits = func() - fruits.append('Apple') - return fruits - return get_fruits -@add_apples -def get_fruits(): - return ['Banana', 'Mango', 'Orange'] - -# Prints out the list of fruits with 'Apple' element in it: -# Banana, Mango, Orange, Apple -print ', '.join(get_fruits()) - -# in this example beg wraps say -# Beg will call say. If say_please is True then it will change the returned -# message +# Decorators +# In this example `beg` wraps `say`. If say_please is True then it +# will change the returned message. from functools import wraps @@ -757,17 +986,17 @@  def wrapper(*args, **kwargs):  msg, say_please = target_function(*args, **kwargs)  if say_please: - return "{} {}".format(msg, "Please! I am poor :(") + return "{} {}".format(msg, "Please! I am poor :(")  return msg  return wrapper @beg -def say(say_please=False): +def say(say_please=False):  msg = "Can you buy me a beer?"  return msg, say_please -print say() # Can you buy me a beer? -print say(say_please=True) # Can you buy me a beer? Please! I am poor :( +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( diff --git a/tests/results/16 b/tests/results/16 index ea42750..e33fd7f 100644 --- a/tests/results/16 +++ b/tests/results/16 @@ -2,15 +2,15 @@ 1ns Main memory reference: Send 2,000 bytes Read 1,000,000 bytes ▗▖ 100ns over commodity network: sequentially from SSD: - ▗▖ 62ns 61.712us + ▗▖ 44ns 48.981us L1 cache reference: 1ns ▗ ▗  ▗▖ 1.0us - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ SSD random read: 16.0us Disk seek: 2.679433ms -Branch mispredict: 3ns  ▗▖▗ ▗▖▗▖▗  + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ SSD random read: 16.0us Disk seek: 2.499999ms +Branch mispredict: 3ns  ▗▖▗ ▗▖▗▖  ▗▖▗▖▗▖  - Compress 1KB with Snappy: Read 1,000,000 bytes Read 1,000,000 bytes + Compress 1KB wth Snappy: Read 1,000,000 bytes Read 1,000,000 bytes L2 cache reference: 4ns 2.0us sequentially from memory: sequentially from disk: -▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 3.738us 947.322us +▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 2.967us 824.692us ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗ ▗  Mutex lock/unlock: 16ns   ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  Round trip Packet roundtrip diff --git a/tests/results/17 b/tests/results/17 index ba45f23..a1cc24f 100644 --- a/tests/results/17 +++ b/tests/results/17 @@ -1,33 +1,33 @@ -# Microsoft Azure CLI 2.0 -# Command-line tools for Azure +# Microsoft Azure CLI 2.0 +# Command-line tools for Azure -# Install Azure CLI 2.0 with one curl command. +# Install Azure CLI 2.0 with one curl command. curl -L https://aka.ms/InstallAzureCli | bash -# create a resource group named "MyResourceGroup" in the westus2 region of Azure -az group create -n MyResourceGroup -l westus2  +# create a resource group named "MyResourceGroup" in the westus2 region of Azure +az group create -n MyResourceGroup -l westus2 -# create a Linux VM using the UbuntuTLS image, with two attached storage disks of 10 GB and 20 GB +# create a Linux VM using the UbuntuTLS image, with two attached storage disks of 10 GB and 20 GB az vm create -n MyLinuxVM -g MyResourceGroup --ssh-key-value $HOME/.ssh/id_rsa.pub --image UbuntuLTS --data-disk-sizes-gb 10 20 -# list VMs +# list VMs az vm list --output table -# list only VMs having distinct state +# list only VMs having distinct state az vm list -d --query "[?powerState=='VM running']" --output table -# delete VM (with the name MyLinuxVM in the group MyResourceGroup) +# delete VM (with the name MyLinuxVM in the group MyResourceGroup) az vm delete -g MyResourceGroup -n MyLinuxVM --yes -# Delete all VMs in a resource group +# Delete all VMs in a resource group az vm delete --ids $(az vm list -g MyResourceGroup --query "[].id" -o tsv) -# Create an Image based on a running VM +# Create an Image based on a running VM az vm deallocate -g MyResourceGroup -n MyLinuxVM az vm generalize -g MyResourceGroup -n MyLinuxVM az image create --resource-group MyResourceGroup --name MyTestImage --source MyLinuxVM -# Running VM based on a VHD +# Running VM based on a VHD az storage blob upload --account-name "${account_name}" \  --account-key "${account_key}" --container-name "${container_name}" --type page \  --file "${file}" --name "${vhd_name}" @@ -36,55 +36,55 @@  --name myManagedDisk \  --source https://${account_name}.blob.core.windows.net/${container_name}/${vhd_name} -# open port +# open port az vm open-port --resource-group MyResourceGroup --name MyLinuxVM --port 443 --priority 899 -# Show storage accounts +# Show storage accounts az storage account list --output table -# Show contaniers for an account +# Show contaniers for an account az storage container list --account-name mystorageaccount --output table -# Show blobs in a container +# Show blobs in a container az storage blob list --account-name mystorageaccount --container-name mycontainer --output table -# list account keys +# list account keys az storage account keys list --account-name STORAGE_NAME --resource-group RESOURCE_GROUP -# Show own images +# Show own images az image list --output table -# Configure default storage location +# Configure default storage location az configure --defaults location=eastus2 -# Show disks +# Show disks az disk list --output table -# Copy blob +# Copy blob az storage blob copy start \ - --source-uri 'https://md-ldh5nknx2rkz.blob.core.windows.net/jzwuuuzzapn0/abcd?sv=2017-04-17&sr=b&si=68041718-6828-4f5e-9e6e-a1b719975062&sig=XXX' \ - --account-key XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX== \ - --account-name destaccount \ - --destination-container vms \ - --destination-blob DESTINATION-blob.vhd + --source-uri 'https://md-ldh5nknx2rkz.blob.core.windows.net/jzwuuuzzapn0/abcd?sv=2017-04-17&sr=b&si=68041718-6828-4f5e-9e6e-a1b719975062&sig=XXX' \ + --account-key XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX== \ + --account-name destaccount \ + --destination-container vms \ + --destination-blob DESTINATION-blob.vhd -# List virtual networks +# List virtual networks az network vnet list --output table -# List virtual networks adapters +# List virtual networks adapters az network nic list --output table -# List public IP addresses used by the VMs +# List public IP addresses used by the VMs az vm list-ip-addresses --output table -# create snapshot +# create snapshot az snapshot create --resource-group IC-EXASOL-001 --source vm1-disk1 -n vm1-snap1 -# create SAS url for a snapshot +# create SAS url for a snapshot az snapshot grant-access --resource-group IC-EXASOL-001 --name vm1-snap1 --duration-in-seconds 36000 --query '[accessSas]' -o tsv -# attach disk +# attach disk az vm disk attach --vm-name vm1 -g RESOURCE_GROUP --disk DISK1_ID -# detach disk +# detach disk az vm disk detach --vm-name vm1 -g RESOURCE_GROUP --name DISK1_ID diff --git a/tests/results/18 b/tests/results/18 index 2822759..651c8c0 100644 --- a/tests/results/18 +++ b/tests/results/18 @@ -1,19 +1,19 @@ >>> s = 'abcdefgh' >>> n, m, char, chars = 2, 3, 'd', 'cd' ->>> # starting from n=2 characters in and m=3 in length; +>>> # starting from n=2 characters in and m=3 in length; >>> s[n-1:n+m-1] 'bcd' ->>> # starting from n characters in, up to the end of the string; +>>> # starting from n characters in, up to the end of the string; >>> s[n-1:] 'bcdefgh' ->>> # whole string minus last character; +>>> # whole string minus last character; >>> s[:-1] 'abcdefg' ->>> # starting from a known character char="d" within the string and of m length; +>>> # starting from a known character char="d" within the string and of m length; >>> indx = s.index(char) >>> s[indx:indx+m] 'def' ->>> # starting from a known substring chars="cd" within the string and of m length. +>>> # starting from a known substring chars="cd" within the string and of m length. >>> indx = s.index(chars) >>> s[indx:indx+m] 'cde' diff --git a/tests/results/2 b/tests/results/2 index 7b1f52f..3e3ad19 100644 --- a/tests/results/2 +++ b/tests/results/2 @@ -1,17 +1,17 @@ -# Displays everything in the target directory -ls path/to/the/target/directory +# To display everything in , excluding hidden files: +ls <dir> -# Displays everything including hidden files -ls -a +# To display everything in , including hidden files: +ls -a <dir> -# Displays all files, along with the size (with unit suffixes) and timestamp -ls -lh  +# To display all files, along with the size (with unit suffixes) and timestamp +ls -lh <dir> -# Display files, sorted by size -ls -S +# To display files, sorted by size: +ls -S <dir> -# Display directories only -ls -d */ +# To display directories only: +ls -d */ <dir> -# Display directories only, include hidden -ls -d .*/ */ +# To display directories only, include hidden: +ls -d .*/ */ <dir> diff --git a/tests/results/20 b/tests/results/20 index c48b471..e4a147d 100644 --- a/tests/results/20 +++ b/tests/results/20 @@ -65,7 +65,9 @@ Bitmap-Bresenhams-line-algorithm Bitmap-Flood-fill Bitmap-Histogram Bitmap-Midpoint-circle-algorithm +Bitmap-PPM-conversion-through-a-pipe Bitmap-Read-a-PPM-file +Bitmap-Read-an-image-through-a-pipe Bitmap-Write-a-PPM-file Bitwise-IO Bitwise-operations @@ -92,10 +94,12 @@ Casting-out-nines Catalan-numbers Catalan-numbers-Pascals-triangle Catamorphism +Catmull-Clark-subdivision-surface Character-codes Chat-server Check-Machin-like-formulas Check-that-file-exists +Checkpoint-synchronization Chinese-remainder-theorem Cholesky-decomposition Circles-of-given-radius-through-two-points @@ -107,6 +111,7 @@ Color-of-a-screen-pixel Color-quantization Colour-bars-Display Colour-pinstripe-Display +Colour-pinstripe-Printer Combinations Combinations-and-permutations Combinations-with-repetitions @@ -141,6 +146,7 @@ Day-of-the-week Deal-cards-for-FreeCell Death-Star Deconvolution-1D +Deconvolution-2D+ Deepcopy Define-a-primitive-data-type Delegates @@ -689,6 +695,7 @@ Variadic-function Vector-products Verify-distribution-uniformity-Chi-squared-test Verify-distribution-uniformity-Naive +Video-display-modes Vigen-re-cipher Vigen-re-cipher-Cryptanalysis Visualize-a-tree @@ -715,6 +722,7 @@ Y-combinator Yahoo--search-interface Yin-and-yang Zebra-puzzle +Zeckendorf-arithmetic Zeckendorf-number-representation Zero-to-the-zero-power Zhang-Suen-thinning-algorithm diff --git a/tests/results/21 b/tests/results/21 index 47840a1..bfd13d3 100644 --- a/tests/results/21 +++ b/tests/results/21 @@ -1,270 +1,270 @@ -// Single-line comments start with two slashes. -/* Multiline comments start with slash-star, - and end with star-slash */ +// Single-line comments start with two slashes. +/* Multiline comments start with slash-star, + and end with star-slash */ -// Statements can be terminated by ; +// 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. +// ... but they don't have to be, as semicolons are automatically inserted +// wherever there's a newline, except in certain cases. doStuff() -// Because those cases can cause unexpected results, we'll keep on using -// semicolons in this guide. +// Because those cases can cause unexpected results, we'll keep on using +// semicolons in this guide. -/////////////////////////////////// -// 1. Numbers, Strings and Operators +/////////////////////////////////// +// 1. Numbers, Strings and Operators -// JavaScript has one number type (which is a 64-bit IEEE 754 double). -// Doubles have a 52-bit mantissa, which is enough to store integers -// up to about 9✕10¹⁵ precisely. -3; // = 3 -1.5; // = 1.5 +// JavaScript has one number type (which is a 64-bit IEEE 754 double). +// Doubles have a 52-bit mantissa, which is enough to store integers +// up to about 9✕10¹⁵ precisely. +3; // = 3 +1.5; // = 1.5 -// Some basic arithmetic works as you'd expect. -1 + 1; // = 2 -0.1 + 0.2; // = 0.30000000000000004 -8 - 1; // = 7 -10 * 2; // = 20 -35 / 5; // = 7 +// Some basic arithmetic works as you'd expect. +1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7 -// Including uneven division. -5 / 2; // = 2.5 +// Including uneven division. +5 / 2; // = 2.5 -// And modulo division. -10 % 2; // = 0 -30 % 4; // = 2 -18.5 % 7; // = 4.5 +// And modulo division. +10 % 2; // = 0 +30 % 4; // = 2 +18.5 % 7; // = 4.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 +// 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 +// 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, stands for 'Not a Number' +// 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, stands for 'Not a Number' -// There's also a boolean type. +// There's also a boolean type. true; false; -// Strings are created with ' or ". +// Strings are created with ' or ". 'abc'; "Hello, world"; -// Negation uses the ! symbol -!true; // = false -!false; // = true +// Negation uses the ! symbol +!true; // = false +!false; // = true -// Equality is === -1 === 1; // = true -2 === 1; // = false +// Equality is === +1 === 1; // = true +2 === 1; // = false -// Inequality is !== -1 !== 1; // = false -2 !== 1; // = true +// Inequality is !== +1 !== 1; // = false +2 !== 1; // = true -// More comparisons -1 < 10; // = true -1 > 10; // = false -2 <= 2; // = true -2 >= 2; // = true +// More comparisons +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true -// Strings are concatenated with + -"Hello " + "world!"; // = "Hello world!" +// Strings are concatenated with + +"Hello " + "world!"; // = "Hello world!" -// ... which works with more than just strings -"1, 2, " + 3; // = "1, 2, 3" -"Hello " + ["world", "!"]; // = "Hello world,!" +// ... which works with more than just strings +"1, 2, " + 3; // = "1, 2, 3" +"Hello " + ["world", "!"]; // = "Hello world,!" -// and are compared with < and > -"a" < "b"; // = true +// and are compared with < and > +"a" < "b"; // = true -// Type coercion is performed for comparisons with double equals... -"5" == 5; // = true -null == undefined; // = true +// Type coercion is performed for comparisons with double equals... +"5" == 5; // = true +null == undefined; // = true -// ...unless you use === -"5" === 5; // = false -null === undefined; // = false +// ...unless you use === +"5" === 5; // = false +null === undefined; // = false -// ...which can result in some weird behaviour... -13 + !0; // 14 -"13" + !0; // '13true' +// ...which can result in some weird behaviour... +13 + !0; // 14 +"13" + !0; // '13true' -// You can access characters in a string with `charAt` -"This is a string".charAt(0); // = 'T' +// You can access characters in a string with `charAt` +"This is a string".charAt(0); // = 'T' -// ...or use `substring` to get larger pieces. -"Hello world".substring(0, 5); // = "Hello" +// ...or use `substring` to get larger pieces. +"Hello world".substring(0, 5); // = "Hello" -// `length` is a property, so don't use (). -"Hello".length; // = 5 +// `length` is a property, so don't use (). +"Hello".length; // = 5 -// There's also `null` and `undefined`. -null; // used to indicate a deliberate non-value -undefined; // used to indicate a value is not currently present (although - // `undefined` is actually a value itself) +// There's also `null` and `undefined`. +null; // used to indicate a deliberate non-value +undefined; // used to indicate a value is not currently present (although + // `undefined` is actually a value itself) -// false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. -// Note that 0 is falsy and "0" is truthy, even though 0 == "0". +// false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. +// Note that 0 is falsy and "0" is truthy, even though 0 == "0". -/////////////////////////////////// -// 2. Variables, Arrays and Objects +/////////////////////////////////// +// 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. +// 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... +// 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. +// ...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 +// Variables declared without being assigned to are set to undefined. +var someThirdVar; // = undefined -// If you want to declare a couple of variables, then you could use a comma -// separator +// If you want to declare a couple of variables, then you could use a comma +// separator var someFourthVar = 2, someFifthVar = 4; -// 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 +// 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 +// 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. +// 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 +// Their members can be accessed using the square-brackets subscript syntax. +// Array indices start at zero. +myArray[1]; // = 45 -// Arrays are mutable and of variable length. +// Arrays are mutable and of variable length. myArray.push("World"); -myArray.length; // = 4 +myArray.length; // = 4 -// Add/Modify at specific index +// Add/Modify at specific index myArray[3] = "Hello"; -// Add and remove element from front or back end of an array -myArray.unshift(3); // Add as the first element -someVar = myArray.shift(); // Remove first element and return it -myArray.push(3); // Add as the last element -someVar = myArray.pop(); // Remove last element and return it +// Add and remove element from front or back end of an array +myArray.unshift(3); // Add as the first element +someVar = myArray.shift(); // Remove first element and return it +myArray.push(3); // Add as the last element +someVar = myArray.pop(); // Remove last element and return it -// Join all elements of an array with semicolon +// Join all elements of an array with semicolon var myArray0 = [32,false,"js",12,56,90]; -myArray0.join(";") // = "32;false;js;12;56;90" +myArray0.join(";"); // = "32;false;js;12;56;90" -// Get subarray of elements from index 1 (include) to 4 (exclude) -myArray0.slice(1,4); // = [false,"js",12] +// Get subarray of elements from index 1 (include) to 4 (exclude) +myArray0.slice(1,4); // = [false,"js",12] -// Remove 4 elements starting from index 2, and insert there strings -// "hi","wr" and "ld"; return removed subarray -myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90] -// myArray0 === [32,false,"hi","wr","ld"] +// Remove 4 elements starting from index 2, and insert there strings +// "hi","wr" and "ld"; return removed subarray +myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90] +// myArray0 === [32,false,"hi","wr","ld"] -// JavaScript's objects are equivalent to "dictionaries" or "maps" in other -// languages: an unordered collection of key-value pairs. +// JavaScript's objects are equivalent to "dictionaries" or "maps" in other +// languages: an unordered collection of key-value pairs. var myObj = {key1: "Hello", key2: "World"}; -// Keys are strings, but quotes aren't required if they're a valid -// JavaScript identifier. Values can be any type. +// 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 +// 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" +// ... 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. +// 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 +// If you try to access a value that's not yet set, you'll get undefined. +myObj.myFourthKey; // = undefined -/////////////////////////////////// -// 3. Logic and Control Structures +/////////////////////////////////// +// 3. Logic and Control Structures -// The `if` structure works as you'd expect. +// The `if` structure works as you'd expect. var count = 1; if (count == 3){ - // evaluated if count is 3 + // evaluated if count is 3 } else if (count == 4){ - // evaluated if count is 4 + // evaluated if count is 4 } else { - // evaluated if it's not either 3 or 4 + // evaluated if it's not either 3 or 4 } -// As does `while`. +// As does `while`. while (true){ - // An infinite loop! + // An infinite loop! } -// Do-while loops are like while loops, except they always run at least once. +// 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: -// initialization; continue condition; iteration. +// The `for` loop is the same as C and Java: +// initialization; continue condition; iteration. for (var i = 0; i < 5; i++){ - // will run 5 times + // will run 5 times } -// Breaking out of labeled loops is similar to Java +// Breaking out of labeled loops is similar to Java outer: for (var i = 0; i < 10; i++) {  for (var j = 0; j < 10; j++) {  if (i == 5 && j ==5) {  break outer; - // breaks out of outer loop instead of only the inner one + // breaks out of outer loop instead of only the inner one  }  } } -// The for/in statement allows iteration over properties of an object. +// The for/in statement allows iteration over properties of an object. var description = ""; var person = {fname:"Paul", lname:"Ken", age:18}; for (var x in person){  description += person[x] + " "; -} // description = 'Paul Ken 18 ' +} // description = 'Paul Ken 18 ' -// The for/of statement allows iteration over iterable objects (including the built-in String,  -// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set,  -// and user-defined iterables). +// The for/of statement allows iteration over iterable objects (including the built-in String,  +// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set,  +// and user-defined iterables). var myPets = ""; var pets = ["cat", "dog", "hamster", "hedgehog"]; for (var pet of pets){  myPets += pet + " "; -} // myPets = 'cat dog hamster hedgehog ' +} // myPets = 'cat dog hamster hedgehog ' -// && is logical and, || is logical or +// && 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 + // colour is either red or blue } -// && and || "short circuit", which is useful for setting default values. +// && and || "short circuit", which is useful for setting default values. var name = otherName || "default"; -// The `switch` statement checks for equality with `===`. -// Use 'break' after each case -// or the cases after the correct one will be executed too. +// The `switch` statement checks for equality with `===`. +// Use 'break' after each case +// or the cases after the correct one will be executed too. grade = 'B'; switch (grade) {  case 'A': @@ -282,172 +282,172 @@ } -/////////////////////////////////// -// 4. Functions, Scope and Closures +/////////////////////////////////// +// 4. Functions, Scope and Closures -// JavaScript functions are declared with the `function` keyword. +// JavaScript functions are declared with the `function` keyword. function myFunction(thing){  return thing.toUpperCase(); } -myFunction("foo"); // = "FOO" +myFunction("foo"); // = "FOO" -// Note that the value to be returned must start on the same line as the -// `return` keyword, otherwise you'll always return `undefined` due to -// automatic semicolon insertion. Watch out for this when using Allman style. +// Note that the value to be returned must start on the same line as the +// `return` keyword, otherwise you'll always return `undefined` due to +// automatic semicolon insertion. Watch out for this when using Allman style. function myFunction(){ - return // <- semicolon automatically inserted here + return // <- semicolon automatically inserted here  {thisIsAn: 'object literal'}; } -myFunction(); // = undefined +myFunction(); // = undefined -// 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: +// 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 + // this code will be called in 5 seconds' time } setTimeout(myFunction, 5000); -// Note: setTimeout isn't part of the JS language, but is provided by browsers -// and Node.js. +// Note: setTimeout isn't part of the JS language, but is provided by browsers +// and Node.js. -// Another function provided by browsers is setInterval +// Another function provided by browsers is setInterval function myFunction(){ - // this code will be called every 5 seconds + // this code will be called every 5 seconds } setInterval(myFunction, 5000); -// Function objects don't even have to be declared with a name - you can write -// an anonymous function definition directly into the arguments of another. +// Function objects don't even have to be declared with a name - you can write +// an anonymous function definition directly into the arguments of another. setTimeout(function(){ - // this code will be called in 5 seconds' time + // this code will be called in 5 seconds' time }, 5000); -// JavaScript has function scope; functions get their own scope but other blocks -// do not. +// 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 +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. +// 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 assigning 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. + // We can access the global scope by assigning 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; })(); -temporary; // raises ReferenceError -permanent; // = 10 +temporary; // raises ReferenceError +permanent; // = 10 -// 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, even after the outer function exits. +// 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, even after the outer function exits. function sayHelloInFiveSeconds(name){  var prompt = "Hello, " + name + "!"; - // Inner functions are put in the local scope by default, as if they were - // declared with `var`. + // Inner functions are put in the local scope by default, as if they were + // declared with `var`.  function inner(){  alert(prompt);  }  setTimeout(inner, 5000); - // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will - // exit immediately, and setTimeout will call inner afterwards. However, - // because inner is "closed over" sayHelloInFiveSeconds, inner still has - // access to the `prompt` variable when it is finally called. + // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will + // exit immediately, and setTimeout will call inner afterwards. However, + // because inner is "closed over" sayHelloInFiveSeconds, inner still has + // access to the `prompt` variable when it is finally called. } -sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s +sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s -/////////////////////////////////// -// 5. More about Objects; Constructors and Prototypes +/////////////////////////////////// +// 5. More about Objects; Constructors and Prototypes -// Objects can contain functions. +// Objects can contain functions. var myObj = {  myFunc: function(){  return "Hello world!";  } }; -myObj.myFunc(); // = "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. +// 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!" +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. +// 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 +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. +// 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!" +myObj.myOtherFunc(); // = "HELLO WORLD!" -// We can also specify a context for a function to execute in when we invoke it -// using `call` or `apply`. +// We can also specify a context for a function to execute in when we invoke it +// using `call` or `apply`. var anotherFunc = function(s){  return this.myString + s; }; -anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" -// The `apply` function is nearly identical, but takes an array for an argument -// list. +// The `apply` function is nearly identical, but takes an array for an argument +// list. -anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" -// This is useful when working with a function that accepts a sequence of -// arguments and you want to pass an array. +// This is useful when working with a function that accepts a sequence of +// arguments and you want to pass an array. -Math.min(42, 6, 27); // = 6 -Math.min([42, 6, 27]); // = NaN (uh-oh!) -Math.min.apply(Math, [42, 6, 27]); // = 6 +Math.min(42, 6, 27); // = 6 +Math.min([42, 6, 27]); // = NaN (uh-oh!) +Math.min.apply(Math, [42, 6, 27]); // = 6 -// But, `call` and `apply` are only temporary. When we want it to stick, we can -// use `bind`. +// But, `call` and `apply` are only temporary. When we want it to stick, we can +// use `bind`. var boundFunc = anotherFunc.bind(myObj); -boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" +boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" -// `bind` can also be used to partially apply (curry) a function. +// `bind` can also be used to partially apply (curry) a function. var product = function(a, b){ return a * b; }; var doubler = product.bind(this, 2); -doubler(8); // = 16 +doubler(8); // = 16 -// When you call a function with the `new` keyword, a new object is created, and -// made available to the function via the `this` keyword. Functions designed to be -// called like that are called constructors. +// When you call a function with the `new` keyword, a new object is created, and +// made available to the function via the `this` keyword. Functions designed to be +// called like that are called constructors. var MyConstructor = function(){  this.myNumber = 5; }; -myNewObj = new MyConstructor(); // = {myNumber: 5} -myNewObj.myNumber; // = 5 +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 -// Unlike most other popular object-oriented languages, JavaScript has no -// concept of 'instances' created from 'class' blueprints; instead, JavaScript -// combines instantiation and inheritance into a single concept: a 'prototype'. +// Unlike most other popular object-oriented languages, JavaScript has no +// concept of 'instances' created from 'class' blueprints; instead, JavaScript +// combines instantiation and inheritance into a single concept: a 'prototype'. -// 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. +// 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. +// 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!" }; @@ -459,58 +459,58 @@ }; myObj.__proto__ = myPrototype; -myObj.meaningOfLife; // = 42 +myObj.meaningOfLife; // = 42 -// This works for functions, too. -myObj.myFunc(); // = "hello world!" +// 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. +// 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 +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. +// 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 +myObj.meaningOfLife; // = 43 -// The for/in statement allows iteration over properties of an object, -// walking up the prototype chain until it sees a null prototype. +// The for/in statement allows iteration over properties of an object, +// walking up the prototype chain until it sees a null prototype. for (var x in myObj){  console.log(myObj[x]); } -///prints: -// Hello world! -// 43 -// [Function: myFunc] -// true +///prints: +// Hello world! +// 43 +// [Function: myFunc] +// true -// To only consider properties attached to the object itself -// and not its prototypes, use the `hasOwnProperty()` check. +// To only consider properties attached to the object itself +// and not its prototypes, use the `hasOwnProperty()` check. for (var x in myObj){  if (myObj.hasOwnProperty(x)){  console.log(myObj[x]);  } } -///prints: -// Hello world! +///prints: +// Hello world! -// We mentioned that `__proto__` was non-standard, and there's no standard way to -// change the prototype of an existing object. However, there are two ways to -// create a new object with a given prototype. +// We mentioned that `__proto__` was non-standard, and there's no standard way to +// change the prototype of an existing object. However, there are 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. +// 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 +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. +// 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 = {  myNumber: 5,  getMyNumber: function(){ @@ -518,47 +518,89 @@  } }; var myNewObj2 = new MyConstructor(); -myNewObj2.getMyNumber(); // = 5 +myNewObj2.getMyNumber(); // = 5 myNewObj2.myNumber = 6; -myNewObj2.getMyNumber(); // = 6 +myNewObj2.getMyNumber(); // = 6 -// Built-in types like strings and numbers also have constructors that create -// equivalent wrapper objects. +// 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 +myNumber == myNumberObj; // = true -// Except, they aren't exactly equivalent. -typeof myNumber; // = 'number' -typeof myNumberObj; // = 'object' -myNumber === myNumberObj; // = false +// 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. + // This code won't execute, because 0 is falsy. } if (new Number(0)){ - // This code will execute, because wrapped numbers are objects, and objects - // are always truthy. + // This code will execute, because wrapped numbers are objects, and objects + // are always truthy. } -// However, the wrapper objects and the regular builtins share a prototype, so -// you can actually add functionality to a string, for instance. +// 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" +"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. +// 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 +// 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 + // make a temporary constructor with the right prototype  var Constructor = function(){};  Constructor.prototype = proto; - // then use it to create a new, appropriately-prototyped object + // then use it to create a new, appropriately-prototyped object  return new Constructor();  }; } + +// ES6 Additions + +// The "let" keyword allows you to define variables in a lexical scope,  +// as opposed to a block scope like the var keyword does. +let name = "Billy"; + +// Variables defined with let can be reassigned new values. +name = "William"; + +// The "const" keyword allows you to define a variable in a lexical scope +// like with let, but you cannot reassign the value once one has been assigned. + +const pi = 3.14; + +pi = 4.13; // You cannot do this. + +// There is a new syntax for functions in ES6 known as "lambda syntax". +// This allows functions to be defined in a lexical scope like with variables +// defined by const and let.  + +const isEven = (number) => { + return number % 2 === 0; +}; + +isEven(7); // false + +// The "equivalent" of this function in the traditional syntax would look like this: + +function isEven(number) { + return number % 2 === 0; +}; + +// I put the word "equivalent" in double quotes because a function defined +// using the lambda syntax cannnot be called before the definition. +// The following is an example of invalid usage: + +add(1, 8); + +const add = (firstNumber, secondNumber) => { + return firstNumber + secondNumber; +}; diff --git a/tests/results/22 b/tests/results/22 index 47840a1..bfd13d3 100644 --- a/tests/results/22 +++ b/tests/results/22 @@ -1,270 +1,270 @@ -// Single-line comments start with two slashes. -/* Multiline comments start with slash-star, - and end with star-slash */ +// Single-line comments start with two slashes. +/* Multiline comments start with slash-star, + and end with star-slash */ -// Statements can be terminated by ; +// 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. +// ... but they don't have to be, as semicolons are automatically inserted +// wherever there's a newline, except in certain cases. doStuff() -// Because those cases can cause unexpected results, we'll keep on using -// semicolons in this guide. +// Because those cases can cause unexpected results, we'll keep on using +// semicolons in this guide. -/////////////////////////////////// -// 1. Numbers, Strings and Operators +/////////////////////////////////// +// 1. Numbers, Strings and Operators -// JavaScript has one number type (which is a 64-bit IEEE 754 double). -// Doubles have a 52-bit mantissa, which is enough to store integers -// up to about 9✕10¹⁵ precisely. -3; // = 3 -1.5; // = 1.5 +// JavaScript has one number type (which is a 64-bit IEEE 754 double). +// Doubles have a 52-bit mantissa, which is enough to store integers +// up to about 9✕10¹⁵ precisely. +3; // = 3 +1.5; // = 1.5 -// Some basic arithmetic works as you'd expect. -1 + 1; // = 2 -0.1 + 0.2; // = 0.30000000000000004 -8 - 1; // = 7 -10 * 2; // = 20 -35 / 5; // = 7 +// Some basic arithmetic works as you'd expect. +1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7 -// Including uneven division. -5 / 2; // = 2.5 +// Including uneven division. +5 / 2; // = 2.5 -// And modulo division. -10 % 2; // = 0 -30 % 4; // = 2 -18.5 % 7; // = 4.5 +// And modulo division. +10 % 2; // = 0 +30 % 4; // = 2 +18.5 % 7; // = 4.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 +// 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 +// 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, stands for 'Not a Number' +// 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, stands for 'Not a Number' -// There's also a boolean type. +// There's also a boolean type. true; false; -// Strings are created with ' or ". +// Strings are created with ' or ". 'abc'; "Hello, world"; -// Negation uses the ! symbol -!true; // = false -!false; // = true +// Negation uses the ! symbol +!true; // = false +!false; // = true -// Equality is === -1 === 1; // = true -2 === 1; // = false +// Equality is === +1 === 1; // = true +2 === 1; // = false -// Inequality is !== -1 !== 1; // = false -2 !== 1; // = true +// Inequality is !== +1 !== 1; // = false +2 !== 1; // = true -// More comparisons -1 < 10; // = true -1 > 10; // = false -2 <= 2; // = true -2 >= 2; // = true +// More comparisons +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true -// Strings are concatenated with + -"Hello " + "world!"; // = "Hello world!" +// Strings are concatenated with + +"Hello " + "world!"; // = "Hello world!" -// ... which works with more than just strings -"1, 2, " + 3; // = "1, 2, 3" -"Hello " + ["world", "!"]; // = "Hello world,!" +// ... which works with more than just strings +"1, 2, " + 3; // = "1, 2, 3" +"Hello " + ["world", "!"]; // = "Hello world,!" -// and are compared with < and > -"a" < "b"; // = true +// and are compared with < and > +"a" < "b"; // = true -// Type coercion is performed for comparisons with double equals... -"5" == 5; // = true -null == undefined; // = true +// Type coercion is performed for comparisons with double equals... +"5" == 5; // = true +null == undefined; // = true -// ...unless you use === -"5" === 5; // = false -null === undefined; // = false +// ...unless you use === +"5" === 5; // = false +null === undefined; // = false -// ...which can result in some weird behaviour... -13 + !0; // 14 -"13" + !0; // '13true' +// ...which can result in some weird behaviour... +13 + !0; // 14 +"13" + !0; // '13true' -// You can access characters in a string with `charAt` -"This is a string".charAt(0); // = 'T' +// You can access characters in a string with `charAt` +"This is a string".charAt(0); // = 'T' -// ...or use `substring` to get larger pieces. -"Hello world".substring(0, 5); // = "Hello" +// ...or use `substring` to get larger pieces. +"Hello world".substring(0, 5); // = "Hello" -// `length` is a property, so don't use (). -"Hello".length; // = 5 +// `length` is a property, so don't use (). +"Hello".length; // = 5 -// There's also `null` and `undefined`. -null; // used to indicate a deliberate non-value -undefined; // used to indicate a value is not currently present (although - // `undefined` is actually a value itself) +// There's also `null` and `undefined`. +null; // used to indicate a deliberate non-value +undefined; // used to indicate a value is not currently present (although + // `undefined` is actually a value itself) -// false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. -// Note that 0 is falsy and "0" is truthy, even though 0 == "0". +// false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. +// Note that 0 is falsy and "0" is truthy, even though 0 == "0". -/////////////////////////////////// -// 2. Variables, Arrays and Objects +/////////////////////////////////// +// 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. +// 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... +// 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. +// ...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 +// Variables declared without being assigned to are set to undefined. +var someThirdVar; // = undefined -// If you want to declare a couple of variables, then you could use a comma -// separator +// If you want to declare a couple of variables, then you could use a comma +// separator var someFourthVar = 2, someFifthVar = 4; -// 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 +// 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 +// 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. +// 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 +// Their members can be accessed using the square-brackets subscript syntax. +// Array indices start at zero. +myArray[1]; // = 45 -// Arrays are mutable and of variable length. +// Arrays are mutable and of variable length. myArray.push("World"); -myArray.length; // = 4 +myArray.length; // = 4 -// Add/Modify at specific index +// Add/Modify at specific index myArray[3] = "Hello"; -// Add and remove element from front or back end of an array -myArray.unshift(3); // Add as the first element -someVar = myArray.shift(); // Remove first element and return it -myArray.push(3); // Add as the last element -someVar = myArray.pop(); // Remove last element and return it +// Add and remove element from front or back end of an array +myArray.unshift(3); // Add as the first element +someVar = myArray.shift(); // Remove first element and return it +myArray.push(3); // Add as the last element +someVar = myArray.pop(); // Remove last element and return it -// Join all elements of an array with semicolon +// Join all elements of an array with semicolon var myArray0 = [32,false,"js",12,56,90]; -myArray0.join(";") // = "32;false;js;12;56;90" +myArray0.join(";"); // = "32;false;js;12;56;90" -// Get subarray of elements from index 1 (include) to 4 (exclude) -myArray0.slice(1,4); // = [false,"js",12] +// Get subarray of elements from index 1 (include) to 4 (exclude) +myArray0.slice(1,4); // = [false,"js",12] -// Remove 4 elements starting from index 2, and insert there strings -// "hi","wr" and "ld"; return removed subarray -myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90] -// myArray0 === [32,false,"hi","wr","ld"] +// Remove 4 elements starting from index 2, and insert there strings +// "hi","wr" and "ld"; return removed subarray +myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90] +// myArray0 === [32,false,"hi","wr","ld"] -// JavaScript's objects are equivalent to "dictionaries" or "maps" in other -// languages: an unordered collection of key-value pairs. +// JavaScript's objects are equivalent to "dictionaries" or "maps" in other +// languages: an unordered collection of key-value pairs. var myObj = {key1: "Hello", key2: "World"}; -// Keys are strings, but quotes aren't required if they're a valid -// JavaScript identifier. Values can be any type. +// 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 +// 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" +// ... 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. +// 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 +// If you try to access a value that's not yet set, you'll get undefined. +myObj.myFourthKey; // = undefined -/////////////////////////////////// -// 3. Logic and Control Structures +/////////////////////////////////// +// 3. Logic and Control Structures -// The `if` structure works as you'd expect. +// The `if` structure works as you'd expect. var count = 1; if (count == 3){ - // evaluated if count is 3 + // evaluated if count is 3 } else if (count == 4){ - // evaluated if count is 4 + // evaluated if count is 4 } else { - // evaluated if it's not either 3 or 4 + // evaluated if it's not either 3 or 4 } -// As does `while`. +// As does `while`. while (true){ - // An infinite loop! + // An infinite loop! } -// Do-while loops are like while loops, except they always run at least once. +// 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: -// initialization; continue condition; iteration. +// The `for` loop is the same as C and Java: +// initialization; continue condition; iteration. for (var i = 0; i < 5; i++){ - // will run 5 times + // will run 5 times } -// Breaking out of labeled loops is similar to Java +// Breaking out of labeled loops is similar to Java outer: for (var i = 0; i < 10; i++) {  for (var j = 0; j < 10; j++) {  if (i == 5 && j ==5) {  break outer; - // breaks out of outer loop instead of only the inner one + // breaks out of outer loop instead of only the inner one  }  } } -// The for/in statement allows iteration over properties of an object. +// The for/in statement allows iteration over properties of an object. var description = ""; var person = {fname:"Paul", lname:"Ken", age:18}; for (var x in person){  description += person[x] + " "; -} // description = 'Paul Ken 18 ' +} // description = 'Paul Ken 18 ' -// The for/of statement allows iteration over iterable objects (including the built-in String,  -// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set,  -// and user-defined iterables). +// The for/of statement allows iteration over iterable objects (including the built-in String,  +// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set,  +// and user-defined iterables). var myPets = ""; var pets = ["cat", "dog", "hamster", "hedgehog"]; for (var pet of pets){  myPets += pet + " "; -} // myPets = 'cat dog hamster hedgehog ' +} // myPets = 'cat dog hamster hedgehog ' -// && is logical and, || is logical or +// && 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 + // colour is either red or blue } -// && and || "short circuit", which is useful for setting default values. +// && and || "short circuit", which is useful for setting default values. var name = otherName || "default"; -// The `switch` statement checks for equality with `===`. -// Use 'break' after each case -// or the cases after the correct one will be executed too. +// The `switch` statement checks for equality with `===`. +// Use 'break' after each case +// or the cases after the correct one will be executed too. grade = 'B'; switch (grade) {  case 'A': @@ -282,172 +282,172 @@ } -/////////////////////////////////// -// 4. Functions, Scope and Closures +/////////////////////////////////// +// 4. Functions, Scope and Closures -// JavaScript functions are declared with the `function` keyword. +// JavaScript functions are declared with the `function` keyword. function myFunction(thing){  return thing.toUpperCase(); } -myFunction("foo"); // = "FOO" +myFunction("foo"); // = "FOO" -// Note that the value to be returned must start on the same line as the -// `return` keyword, otherwise you'll always return `undefined` due to -// automatic semicolon insertion. Watch out for this when using Allman style. +// Note that the value to be returned must start on the same line as the +// `return` keyword, otherwise you'll always return `undefined` due to +// automatic semicolon insertion. Watch out for this when using Allman style. function myFunction(){ - return // <- semicolon automatically inserted here + return // <- semicolon automatically inserted here  {thisIsAn: 'object literal'}; } -myFunction(); // = undefined +myFunction(); // = undefined -// 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: +// 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 + // this code will be called in 5 seconds' time } setTimeout(myFunction, 5000); -// Note: setTimeout isn't part of the JS language, but is provided by browsers -// and Node.js. +// Note: setTimeout isn't part of the JS language, but is provided by browsers +// and Node.js. -// Another function provided by browsers is setInterval +// Another function provided by browsers is setInterval function myFunction(){ - // this code will be called every 5 seconds + // this code will be called every 5 seconds } setInterval(myFunction, 5000); -// Function objects don't even have to be declared with a name - you can write -// an anonymous function definition directly into the arguments of another. +// Function objects don't even have to be declared with a name - you can write +// an anonymous function definition directly into the arguments of another. setTimeout(function(){ - // this code will be called in 5 seconds' time + // this code will be called in 5 seconds' time }, 5000); -// JavaScript has function scope; functions get their own scope but other blocks -// do not. +// 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 +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. +// 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 assigning 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. + // We can access the global scope by assigning 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; })(); -temporary; // raises ReferenceError -permanent; // = 10 +temporary; // raises ReferenceError +permanent; // = 10 -// 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, even after the outer function exits. +// 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, even after the outer function exits. function sayHelloInFiveSeconds(name){  var prompt = "Hello, " + name + "!"; - // Inner functions are put in the local scope by default, as if they were - // declared with `var`. + // Inner functions are put in the local scope by default, as if they were + // declared with `var`.  function inner(){  alert(prompt);  }  setTimeout(inner, 5000); - // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will - // exit immediately, and setTimeout will call inner afterwards. However, - // because inner is "closed over" sayHelloInFiveSeconds, inner still has - // access to the `prompt` variable when it is finally called. + // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will + // exit immediately, and setTimeout will call inner afterwards. However, + // because inner is "closed over" sayHelloInFiveSeconds, inner still has + // access to the `prompt` variable when it is finally called. } -sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s +sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s -/////////////////////////////////// -// 5. More about Objects; Constructors and Prototypes +/////////////////////////////////// +// 5. More about Objects; Constructors and Prototypes -// Objects can contain functions. +// Objects can contain functions. var myObj = {  myFunc: function(){  return "Hello world!";  } }; -myObj.myFunc(); // = "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. +// 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!" +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. +// 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 +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. +// 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!" +myObj.myOtherFunc(); // = "HELLO WORLD!" -// We can also specify a context for a function to execute in when we invoke it -// using `call` or `apply`. +// We can also specify a context for a function to execute in when we invoke it +// using `call` or `apply`. var anotherFunc = function(s){  return this.myString + s; }; -anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" -// The `apply` function is nearly identical, but takes an array for an argument -// list. +// The `apply` function is nearly identical, but takes an array for an argument +// list. -anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" -// This is useful when working with a function that accepts a sequence of -// arguments and you want to pass an array. +// This is useful when working with a function that accepts a sequence of +// arguments and you want to pass an array. -Math.min(42, 6, 27); // = 6 -Math.min([42, 6, 27]); // = NaN (uh-oh!) -Math.min.apply(Math, [42, 6, 27]); // = 6 +Math.min(42, 6, 27); // = 6 +Math.min([42, 6, 27]); // = NaN (uh-oh!) +Math.min.apply(Math, [42, 6, 27]); // = 6 -// But, `call` and `apply` are only temporary. When we want it to stick, we can -// use `bind`. +// But, `call` and `apply` are only temporary. When we want it to stick, we can +// use `bind`. var boundFunc = anotherFunc.bind(myObj); -boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" +boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" -// `bind` can also be used to partially apply (curry) a function. +// `bind` can also be used to partially apply (curry) a function. var product = function(a, b){ return a * b; }; var doubler = product.bind(this, 2); -doubler(8); // = 16 +doubler(8); // = 16 -// When you call a function with the `new` keyword, a new object is created, and -// made available to the function via the `this` keyword. Functions designed to be -// called like that are called constructors. +// When you call a function with the `new` keyword, a new object is created, and +// made available to the function via the `this` keyword. Functions designed to be +// called like that are called constructors. var MyConstructor = function(){  this.myNumber = 5; }; -myNewObj = new MyConstructor(); // = {myNumber: 5} -myNewObj.myNumber; // = 5 +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 -// Unlike most other popular object-oriented languages, JavaScript has no -// concept of 'instances' created from 'class' blueprints; instead, JavaScript -// combines instantiation and inheritance into a single concept: a 'prototype'. +// Unlike most other popular object-oriented languages, JavaScript has no +// concept of 'instances' created from 'class' blueprints; instead, JavaScript +// combines instantiation and inheritance into a single concept: a 'prototype'. -// 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. +// 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. +// 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!" }; @@ -459,58 +459,58 @@ }; myObj.__proto__ = myPrototype; -myObj.meaningOfLife; // = 42 +myObj.meaningOfLife; // = 42 -// This works for functions, too. -myObj.myFunc(); // = "hello world!" +// 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. +// 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 +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. +// 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 +myObj.meaningOfLife; // = 43 -// The for/in statement allows iteration over properties of an object, -// walking up the prototype chain until it sees a null prototype. +// The for/in statement allows iteration over properties of an object, +// walking up the prototype chain until it sees a null prototype. for (var x in myObj){  console.log(myObj[x]); } -///prints: -// Hello world! -// 43 -// [Function: myFunc] -// true +///prints: +// Hello world! +// 43 +// [Function: myFunc] +// true -// To only consider properties attached to the object itself -// and not its prototypes, use the `hasOwnProperty()` check. +// To only consider properties attached to the object itself +// and not its prototypes, use the `hasOwnProperty()` check. for (var x in myObj){  if (myObj.hasOwnProperty(x)){  console.log(myObj[x]);  } } -///prints: -// Hello world! +///prints: +// Hello world! -// We mentioned that `__proto__` was non-standard, and there's no standard way to -// change the prototype of an existing object. However, there are two ways to -// create a new object with a given prototype. +// We mentioned that `__proto__` was non-standard, and there's no standard way to +// change the prototype of an existing object. However, there are 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. +// 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 +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. +// 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 = {  myNumber: 5,  getMyNumber: function(){ @@ -518,47 +518,89 @@  } }; var myNewObj2 = new MyConstructor(); -myNewObj2.getMyNumber(); // = 5 +myNewObj2.getMyNumber(); // = 5 myNewObj2.myNumber = 6; -myNewObj2.getMyNumber(); // = 6 +myNewObj2.getMyNumber(); // = 6 -// Built-in types like strings and numbers also have constructors that create -// equivalent wrapper objects. +// 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 +myNumber == myNumberObj; // = true -// Except, they aren't exactly equivalent. -typeof myNumber; // = 'number' -typeof myNumberObj; // = 'object' -myNumber === myNumberObj; // = false +// 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. + // This code won't execute, because 0 is falsy. } if (new Number(0)){ - // This code will execute, because wrapped numbers are objects, and objects - // are always truthy. + // This code will execute, because wrapped numbers are objects, and objects + // are always truthy. } -// However, the wrapper objects and the regular builtins share a prototype, so -// you can actually add functionality to a string, for instance. +// 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" +"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. +// 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 +// 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 + // make a temporary constructor with the right prototype  var Constructor = function(){};  Constructor.prototype = proto; - // then use it to create a new, appropriately-prototyped object + // then use it to create a new, appropriately-prototyped object  return new Constructor();  }; } + +// ES6 Additions + +// The "let" keyword allows you to define variables in a lexical scope,  +// as opposed to a block scope like the var keyword does. +let name = "Billy"; + +// Variables defined with let can be reassigned new values. +name = "William"; + +// The "const" keyword allows you to define a variable in a lexical scope +// like with let, but you cannot reassign the value once one has been assigned. + +const pi = 3.14; + +pi = 4.13; // You cannot do this. + +// There is a new syntax for functions in ES6 known as "lambda syntax". +// This allows functions to be defined in a lexical scope like with variables +// defined by const and let.  + +const isEven = (number) => { + return number % 2 === 0; +}; + +isEven(7); // false + +// The "equivalent" of this function in the traditional syntax would look like this: + +function isEven(number) { + return number % 2 === 0; +}; + +// I put the word "equivalent" in double quotes because a function defined +// using the lambda syntax cannnot be called before the definition. +// The following is an example of invalid usage: + +add(1, 8); + +const add = (firstNumber, secondNumber) => { + return firstNumber + secondNumber; +}; diff --git a/tests/results/3 b/tests/results/3 index 41a116a..cfff5cc 100644 --- a/tests/results/3 +++ b/tests/results/3 @@ -1,17 +1,17 @@ -# Displays everything in the target directory -ls path/to/the/target/directory +# To display everything in , excluding hidden files: +ls -# Displays everything including hidden files -ls -a +# To display everything in , including hidden files: +ls -a -# Displays all files, along with the size (with unit suffixes) and timestamp -ls -lh +# To display all files, along with the size (with unit suffixes) and timestamp +ls -lh -# Display files, sorted by size -ls -S +# To display files, sorted by size: +ls -S -# Display directories only -ls -d */ +# To display directories only: +ls -d */ -# Display directories only, include hidden -ls -d .*/ */ +# To display directories only, include hidden: +ls -d .*/ */ diff --git a/tests/results/4 b/tests/results/4 index 10b9309..73d1846 100644 --- a/tests/results/4 +++ b/tests/results/4 @@ -1,54 +1,54 @@ -# Create a btrfs file system on /dev/sdb, /dev/sdc, and /dev/sdd +# Create a btrfs file system on /dev/sdb, /dev/sdc, and /dev/sdd mkfs.btrfs /dev/sdb /dev/sdc /dev/sdd -# btrfs with just one hard drive, metadata not redundant  -# (this is danegerous: if your metadata is lost, your data is lost as well) +# btrfs with just one hard drive, metadata not redundant +# (this is danegerous: if your metadata is lost, your data is lost as well) mkfs.btrfs -m single /dev/sdb -# data to be redundant and metadata to be non-redundant: +# data to be redundant and metadata to be non-redundant: mkfs.btrfs -m raid0 -d raid1 /dev/sdb /dev/sdc /dev/sdd -# both data and metadata to be redundan +# both data and metadata to be redundan mkfs.btrfs -d raid1 /dev/sdb /dev/sdc /dev/sdd -# To get a list of all btrfs file systems +# To get a list of all btrfs file systems btrfs filesystem show -# detailed df for a fileesystem (mounted in /mnt) +# detailed df for a fileesystem (mounted in /mnt) btrfs filesystem df /mnt -# resize btrfs online (-2g decreases, +2g increases) +# resize btrfs online (-2g decreases, +2g increases) btrfs filesystem resize -2g /mnt -# use maximum space +# use maximum space btrfs filesystem resize max /mnt -# add new device to a filesystem +# add new device to a filesystem btrfs device add /dev/sdf /mnt -# remove devices from a filesystem +# remove devices from a filesystem btrfs device delete missing /mnt -# create the subvolume /mnt/sv1 in the /mnt volume +# create the subvolume /mnt/sv1 in the /mnt volume btrfs subvolume create /mnt/sv1 -# list subvolumes +# list subvolumes btrfs subvolume list /mnt -# mount subvolume without mounting the main filesystem +# mount subvolume without mounting the main filesystem mount -o subvol=sv1 /dev/sdb /mnt -# delete subvolume +# delete subvolume btrfs subvolume delete /mnt/sv1 -# taking snapshot of a subvolume +# taking snapshot of a subvolume btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot -# taking snapshot of a file (copy file by reference) +# taking snapshot of a file (copy file by reference) cp --reflink /mnt/sv1/test1 /mnt/sv1/test3 -# convert ext3/ext4 to btrfs +# convert ext3/ext4 to btrfs btrfs-convert /dev/sdb1 -# convert btrfs to ext3/ext4 +# convert btrfs to ext3/ext4 btrfs-convert -r /dev/sdb1 diff --git a/tests/results/5 b/tests/results/5 index 317da29..5f6c2ee 100644 --- a/tests/results/5 +++ b/tests/results/5 @@ -1,3 +1,3 @@  btrfs  -# create the subvolume /mnt/sv1 in the /mnt volume +# create the subvolume /mnt/sv1 in the /mnt volume btrfs subvolume create /mnt/sv1