From d340f2c9bda2645e9fff20afd5369948cdca6cb4 Mon Sep 17 00:00:00 2001 From: poojankhanpara Date: Thu, 7 Jul 2022 14:45:42 -0700 Subject: [PATCH 1/2] added ?T option to run-tests.sh to ignore ansi styling mismatch errors and recaptured the outputs --- tests/results/10 | 26 +- tests/results/11 | 4 +- tests/results/13 | 60 +- tests/results/14 | 60 +- tests/results/15 | 1902 ++++++++++++++++++++++---------------------- tests/results/16 | 66 +- tests/results/17 | 176 ++-- tests/results/18 | 40 +- tests/results/2 | 78 +- tests/results/21 | 1148 +++++++++++++------------- tests/results/22 | 1148 +++++++++++++------------- tests/results/3 | 13 + tests/results/4 | 106 +-- tests/results/5 | 111 +-- tests/results/6 | 160 ++-- tests/results/9 | 26 +- tests/run-tests.sh | 13 +- 17 files changed, 2582 insertions(+), 2555 deletions(-) diff --git a/tests/results/10 b/tests/results/10 index a8eca4f0..cbe8793c 100644 --- a/tests/results/10 +++ b/tests/results/10 @@ -1,16 +1,16 @@ -# How do I copy a file in Python? -#  -# shutil (http://docs.python.org/3/library/shutil.html) has many methods -# you can use. One of which is: +# How do I copy a file in Python? +# +# shutil (http://docs.python.org/3/library/shutil.html) has many methods +# you can use. One of which is: -from shutil import copyfile +from shutil import copyfile -copyfile(src, dst) +copyfile(src, dst) -# Copy the contents of the file named src to a file named dst. The -# destination location must be writable; otherwise, an IOError exception -# will be raised. If dst already exists, it will be replaced. Special -# files such as character or block devices and pipes cannot be copied -# with this function. src and dst are path names given as strings. -#  -# [Swati] [so/q/123198] [cc by-sa 3.0] +# Copy the contents of the file named src to a file named dst. The +# destination location must be writable; otherwise, an IOError exception +# will be raised. If dst already exists, it will be replaced. Special +# files such as character or block devices and pipes cannot be copied +# with this function. src and dst are path names given as strings. +# +# [Swati] [so/q/123198] [cc by-sa 3.0] diff --git a/tests/results/11 b/tests/results/11 index d0db3d4e..7c532658 100644 --- a/tests/results/11 +++ b/tests/results/11 @@ -1,3 +1,3 @@ -from shutil import copyfile +from shutil import copyfile -copyfile(src, dst) +copyfile(src, dst) diff --git a/tests/results/13 b/tests/results/13 index 8794df4b..21e74889 100644 --- a/tests/results/13 +++ b/tests/results/13 @@ -1,32 +1,32 @@ - _ _ _ __    - ___| |__ ___ __ _| |_ ___| |__ \ \      The only cheat sheet you need    - / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \  Unified access to the best     -| (__| | | | __/ (_| | |_ _\__ \ | | |/ /  community driven documentation - \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/   repositories of the world      + _ _ _ __ + ___| |__ ___ __ _| |_ ___| |__ \ \ The only cheat sheet you need + / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \ Unified access to the best +| (__| | | | __/ (_| | |_ _\__ \ | | |/ / community driven documentation + \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/ repositories of the world -+------------------------+ +------------------------+ +------------------------+ -| $ curl cheat.sh/ls     | | $ cht.sh btrfs         | | $ cht.sh lua/:learn | -| $ curl cht.sh/btrfs    | | $ cht.sh tar~list      | | Learn any* programming | -| $ curl cht.sh/tar~list | | | | language not leaving | -| $ curl https://cht.sh  | | | | your shell | -| | | | | *) any of 60 | -| | | | | | -+-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ -+------------------------+ +------------------------+ +------------------------+ -| $ cht.sh go/f<tab><tab>| | $ cht.sh --shell | | $ cht.sh go zip lists | -| go/for go/func | | cht.sh> help | | Ask any question using | -| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | -| ... | | | | /go/zip+lists | -| | | | | (use /,+ when curling) | -| | | | | | -+---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ -+------------------------+ +------------------------+ +------------------------+ -| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | -| see /:help and /:intro | | ... | | ... | -| for usage information | | zip lists _ | | real 0m0.075s | -| and README.md on GitHub| | <leader>KK | | | -| for the details | | *awesome* | | | -| *start here*| | | | | -+--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cheat.sh/ls | | $ cht.sh btrfs | | $ cht.sh lua/:learn | +| $ curl cht.sh/btrfs | | $ cht.sh tar~list | | Learn any* programming | +| $ curl cht.sh/tar~list | | | | language not leaving | +| $ curl https://cht.sh | | | | your shell | +| | | | | *) any of 60 | +| | | | | | ++-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ ++------------------------+ +------------------------+ +------------------------+ +| $ cht.sh go/f| | $ cht.sh --shell | | $ cht.sh go zip lists | +| go/for go/func | | cht.sh> help | | Ask any question using | +| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | +| ... | | | | /go/zip+lists | +| | | | | (use /,+ when curling) | +| | | | | | ++---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | +| see /:help and /:intro | | ... | | ... | +| for usage information | | zip lists _ | | real 0m0.075s | +| and README.md on GitHub| | KK | | | +| for the details | | *awesome* | | | +| *start here*| | | | | ++--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ -[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] +[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] diff --git a/tests/results/14 b/tests/results/14 index 8794df4b..21e74889 100644 --- a/tests/results/14 +++ b/tests/results/14 @@ -1,32 +1,32 @@ - _ _ _ __    - ___| |__ ___ __ _| |_ ___| |__ \ \      The only cheat sheet you need    - / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \  Unified access to the best     -| (__| | | | __/ (_| | |_ _\__ \ | | |/ /  community driven documentation - \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/   repositories of the world      + _ _ _ __ + ___| |__ ___ __ _| |_ ___| |__ \ \ The only cheat sheet you need + / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \ Unified access to the best +| (__| | | | __/ (_| | |_ _\__ \ | | |/ / community driven documentation + \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/ repositories of the world -+------------------------+ +------------------------+ +------------------------+ -| $ curl cheat.sh/ls     | | $ cht.sh btrfs         | | $ cht.sh lua/:learn | -| $ curl cht.sh/btrfs    | | $ cht.sh tar~list      | | Learn any* programming | -| $ curl cht.sh/tar~list | | | | language not leaving | -| $ curl https://cht.sh  | | | | your shell | -| | | | | *) any of 60 | -| | | | | | -+-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ -+------------------------+ +------------------------+ +------------------------+ -| $ cht.sh go/f<tab><tab>| | $ cht.sh --shell | | $ cht.sh go zip lists | -| go/for go/func | | cht.sh> help | | Ask any question using | -| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | -| ... | | | | /go/zip+lists | -| | | | | (use /,+ when curling) | -| | | | | | -+---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ -+------------------------+ +------------------------+ +------------------------+ -| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | -| see /:help and /:intro | | ... | | ... | -| for usage information | | zip lists _ | | real 0m0.075s | -| and README.md on GitHub| | <leader>KK | | | -| for the details | | *awesome* | | | -| *start here*| | | | | -+--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cheat.sh/ls | | $ cht.sh btrfs | | $ cht.sh lua/:learn | +| $ curl cht.sh/btrfs | | $ cht.sh tar~list | | Learn any* programming | +| $ curl cht.sh/tar~list | | | | language not leaving | +| $ curl https://cht.sh | | | | your shell | +| | | | | *) any of 60 | +| | | | | | ++-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ ++------------------------+ +------------------------+ +------------------------+ +| $ cht.sh go/f| | $ cht.sh --shell | | $ cht.sh go zip lists | +| go/for go/func | | cht.sh> help | | Ask any question using | +| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | +| ... | | | | /go/zip+lists | +| | | | | (use /,+ when curling) | +| | | | | | ++---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | +| see /:help and /:intro | | ... | | ... | +| for usage information | | zip lists _ | | real 0m0.075s | +| and README.md on GitHub| | KK | | | +| for the details | | *awesome* | | | +| *start here*| | | | | ++--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ -[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] +[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] diff --git a/tests/results/15 b/tests/results/15 index ad1f1a9e..09c57d95 100644 --- a/tests/results/15 +++ b/tests/results/15 @@ -1,1001 +1,1001 @@ -# Single line comments start with a number symbol. - -""" Multiline strings can be written - using three "s, and are often used - as documentation. -""" - -#################################################### -## 1. Primitive Datatypes and Operators -#################################################### - -# You have numbers -3 # => 3 - -# Math is what you would expect -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 -35 / 5 # => 7.0 - -# 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 - -# The result of division is always a float -10.0 / 3 # => 3.3333333333333335 - -# Modulo operation -7 % 3 # => 1 -# i % j have the same sign as j, unlike C --7 % 3 # => 2 - -# Exponentiation (x**y, x to the yth power) -2**3 # => 8 - -# Enforce precedence with parentheses -1 + 3 * 2 # => 7 -(1 + 3) * 2 # => 8 - -# Boolean values are primitives (Note: the capitalization) -True # => True -False # => False - -# negate with not -not True # => False -not False # => 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 - -# Comparison operators look at the numerical value of True and False -0 == False # => True -1 == True # => True -2 == True # => False --5 != 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 - -# Inequality is != -1 != 1 # => False -2 != 1 # => True - -# More comparisons -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# 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 - -# (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!" -# String literals (but not variables) can be concatenated without using '+' -"Hello " "world!" # => "Hello world!" - -# A string can be treated like a list of characters -"Hello world!"[0] # => 'H' - -# You can find the length of a string -len("This is a string") # => 16 - -# 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 expression inside the braces and it will be output in the string. -f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." - -# None is an object -None # => None - -# 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 - -# 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 - -#################################################### -## 2. Variables and Collections -#################################################### - -# Python has a print function -print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! - -# 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! - -# Simple way to get input data from console -input_string_var = input("Enter some data: ") # Returns the data as a string - -# 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 -"yay!" if 0 > 1 else "nay!" # => "nay!" - -# Lists store sequences -li = [] -# 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. - -# 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 - -# 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] - -# Make a one layer deep copy using slices -li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false. - -# Remove arbitrary elements from a list with "del" -del li[2] # li is now [1, 2, 3] - -# 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 - -# Insert an element at a specific index -li.insert(1, 2) # li is now [1, 2, 3] 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 - -# You can add lists -# Note: values for li and for other_li are not modified. -li + other_li # => [1, 2, 3, 4, 5, 6] - -# Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] - -# Check for existence in a list with "in" -1 in li # => True - -# 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 - -# 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 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 - -# 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 -filled_dict = {"one": 1, "two": 2, "three": 3} - -# 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. - -# Look up values with [] -filled_dict["one"] # => 1 - -# 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 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+ - -# Check for existence of keys in a dictionary with "in" -"one" in filled_dict # => True -1 in filled_dict # => False - -# Looking up a non-existing key is a KeyError -filled_dict["four"] # KeyError - -# Use "get()" method to avoid the KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None -# The get method supports a default argument when the value is missing -filled_dict.get("one", 4) # => 1 -filled_dict.get("four", 4) # => 4 - -# "setdefault()" 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 - -# 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. 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} - -# 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} - -# 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} - -# Do set intersection with & -other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} - -# 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 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 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 - -# 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 and Iterables -#################################################### - -# Let's just make a variable -some_var = 5 - -# 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.") - - -""" -For loops iterate over lists -prints: - dog is a mammal - cat is a mammal - mouse is a mammal -""" -for animal in ["dog", "cat", "mouse"]: - # You can use format() to interpolate formatted strings - print("{} is a mammal".format(animal)) - -""" -"range(number)" returns an iterable of numbers -from zero to the given number -prints: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(lower, upper)" returns an iterable of numbers -from the lower number to the upper number -prints: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - 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. -prints: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Shorthand for x = x + 1 - -# Handle exceptions with a try/except block -try: - # 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. -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") - -# 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) - -# 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} - - -# 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. - -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 {} 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 - -# 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 arguments -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - -# 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"} +# Single line comments start with a number symbol. + +""" Multiline strings can be written + using three "s, and are often used + as documentation. +""" + +#################################################### +## 1. Primitive Datatypes and Operators +#################################################### + +# You have numbers +3 # => 3 + +# Math is what you would expect +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# 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 + +# The result of division is always a float +10.0 / 3 # => 3.3333333333333335 + +# Modulo operation +7 % 3 # => 1 +# i % j have the same sign as j, unlike C +-7 % 3 # => 2 + +# Exponentiation (x**y, x to the yth power) +2**3 # => 8 + +# Enforce precedence with parentheses +1 + 3 * 2 # => 7 +(1 + 3) * 2 # => 8 + +# Boolean values are primitives (Note: the capitalization) +True # => True +False # => False + +# negate with not +not True # => False +not False # => 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 + +# Comparison operators look at the numerical value of True and False +0 == False # => True +1 == True # => True +2 == True # => False +-5 != 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 + +# Inequality is != +1 != 1 # => False +2 != 1 # => True + +# More comparisons +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# 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 + +# (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!" +# String literals (but not variables) can be concatenated without using '+' +"Hello " "world!" # => "Hello world!" + +# A string can be treated like a list of characters +"Hello world!"[0] # => 'H' + +# You can find the length of a string +len("This is a string") # => 16 + +# 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 expression inside the braces and it will be output in the string. +f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." + +# None is an object +None # => None + +# 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 + +# 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 + +#################################################### +## 2. Variables and Collections +#################################################### + +# Python has a print function +print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! + +# 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! + +# Simple way to get input data from console +input_string_var = input("Enter some data: ") # Returns the data as a string + +# 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 +"yay!" if 0 > 1 else "nay!" # => "nay!" + +# Lists store sequences +li = [] +# 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. + +# 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 + +# 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] + +# Make a one layer deep copy using slices +li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false. + +# Remove arbitrary elements from a list with "del" +del li[2] # li is now [1, 2, 3] + +# 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 + +# Insert an element at a specific index +li.insert(1, 2) # li is now [1, 2, 3] 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 + +# You can add lists +# Note: values for li and for other_li are not modified. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# Check for existence in a list with "in" +1 in li # => True + +# 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 + +# 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 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 + +# 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 +filled_dict = {"one": 1, "two": 2, "three": 3} + +# 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. + +# Look up values with [] +filled_dict["one"] # => 1 + +# 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 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+ + +# Check for existence of keys in a dictionary with "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# Looking up a non-existing key is a KeyError +filled_dict["four"] # KeyError + +# Use "get()" method to avoid the KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# The get method supports a default argument when the value is missing +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# "setdefault()" 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 + +# 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. 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} + +# 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} + +# 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} + +# Do set intersection with & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# 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 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 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 + +# 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 and Iterables +#################################################### + +# Let's just make a variable +some_var = 5 + +# 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.") + + +""" +For loops iterate over lists +prints: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # You can use format() to interpolate formatted strings + print("{} is a mammal".format(animal)) + +""" +"range(number)" returns an iterable of numbers +from zero to the given number +prints: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +"range(lower, upper)" returns an iterable of numbers +from the lower number to the upper number +prints: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + 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. +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Shorthand for x = x + 1 + +# Handle exceptions with a try/except block +try: + # 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. +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") + +# 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) + +# 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} + + +# 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. + +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 {} 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 + +# 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 arguments +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + +# 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"} -# You can do both at once, if you like -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) prints: - (1, 2) - {"a": 3, "b": 4} -""" +# You can do both at once, if you like +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" -# 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) +# 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) -# 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) +# 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) -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. +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 -x = 5 - -def set_x(num): - # Local var x not the same as global variable x - x = num # => 43 - print(x) # => 43 +# Function Scope +x = 5 + +def set_x(num): + # 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 +def set_global_x(num): + global x + print(x) # => 5 + x = num # global var x is now set to 6 + print(x) # => 6 -set_x(43) -set_global_x(6) +set_x(43) +set_global_x(6) -# 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 - -# 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 -list(map(add_10, [1, 2, 3])) # => [11, 12, 13] -list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] - -list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [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 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. 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 - -# 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. 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 - self.name = name - - # Initialize property - self._age = 0 - - # An instance method. All methods take "self" as the first argument - def say(self, msg): - print("{name}: {message}".format(name=self.name, message=msg)) - - # 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 - @staticmethod - def grunt(): - return "*grunt*" - - # A property is just like a getter. - # It turns the method age() into a 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 - def age(self, age): - self._age = age - - # This allows the property to be deleted - @age.deleter - def age(self): - del self._age - - -# 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 - - # 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 the static method - print(Human.grunt()) # => "*grunt*" - - # Static methods can be called by instances too - print(i.grunt()) # => "*grunt*" - - # 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 - - -#################################################### -## 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 - - -# Specify the parent class(es) as parameters to the class definition -class Superhero(Human): - - # 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 - - # 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 +# 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 + +# 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 +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [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 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. 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 + +# 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. 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 + self.name = name + + # Initialize property + self._age = 0 + + # An instance method. All methods take "self" as the first argument + def say(self, msg): + print("{name}: {message}".format(name=self.name, message=msg)) + + # 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 + @staticmethod + def grunt(): + return "*grunt*" + + # A property is just like a getter. + # It turns the method age() into a 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 + def age(self, age): + self._age = age + + # This allows the property to be deleted + @age.deleter + def age(self): + del self._age + + +# 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 + + # 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 the static method + print(Human.grunt()) # => "*grunt*" + + # Static methods can be called by instances too + print(i.grunt()) # => "*grunt*" + + # 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 + + +#################################################### +## 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 + + +# Specify the parent class(es) as parameters to the class definition +class Superhero(Human): + + # 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 + + # 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 overridden method + print(sup.sing()) # => Dun, dun, DUN! - # Calls method from Human - sup.say('Spoon') # => Tick: Spoon + # 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! + # 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 + # Inherited class attribute + sup.age = 31 + print(sup.age) # => 31 - # Attribute that only exists within Superhero - print('Am I Oscar eligible? ' + str(sup.movie)) + # Attribute that only exists within Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) -#################################################### -## 6.2 Multiple Inheritance -#################################################### +#################################################### +## 6.2 Multiple Inheritance +#################################################### -# Another class definition -# bat.py -class Bat: +# Another class definition +# bat.py +class Bat: - species = 'Baty' + species = 'Baty' - def __init__(self, can_fly=True): - self.fly = can_fly + def __init__(self, can_fly=True): + self.fly = can_fly - # This class also has a say method - def say(self, msg): - msg = '... ... ...' - return msg + # This class also has a say method + def say(self, msg): + msg = '... ... ...' + return msg - # And its own method as well - def sonar(self): - return '))) ... (((' + # 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 +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): +# 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 __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!' + def sing(self): + return 'nan nan nan nan nan batman!' -if __name__ == '__main__': - sup = 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__) # => (, - # => , - # => , - # => , ) + # 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 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 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 + # 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()) # => ))) ... ((( + # Call method that exists only in 2nd ancestor + print(sup.sonar()) # => ))) ... ((( - # Inherited class attribute - sup.age = 100 - print(sup.age) # => 100 + # 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 + # Inherited attribute from 2nd ancestor whose default value was overridden. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False -#################################################### -## 7. Advanced -#################################################### +#################################################### +## 7. Advanced +#################################################### -# Generators help you make lazy code. -def double_numbers(iterable): - for i in iterable: - yield i + i +# Generators help you make lazy code. +def double_numbers(iterable): + for i in iterable: + yield i + i -# 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 +# 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 -# 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 +# 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 -# 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] +# 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] -# Decorators -# In this example `beg` wraps `say`. If say_please is True then it -# will change the returned message. -from functools import wraps +# Decorators +# In this example `beg` wraps `say`. If say_please is True then it +# will change the returned message. +from functools import wraps -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg - return wrapper + return wrapper -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please +@beg +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 b653ffd5..db3e5ed3 100644 --- a/tests/results/16 +++ b/tests/results/16 @@ -1,35 +1,35 @@ -# Latency numbers every programmer should know  +# Latency numbers every programmer should know 1ns Main memory reference: Send 2,000 bytes Read 1,000,000 bytes -▗▖ 100ns over commodity network: sequentially from SSD: - ▗▖ 31ns 38.876us -L1 cache reference: 1ns ▗ ▗  -▗▖ 1.0us - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ SSD random read: 16.0us Disk seek: 2.332582ms -Branch mispredict: 3ns  ▗▖▗ ▗▖▗▖  -▗▖▗▖▗▖  - 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: -▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 2.355us 717.936us - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗ ▗  -Mutex lock/unlock: 16ns   -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  Round trip Packet roundtrip -▗▖▗▖▗▖▗▖▗▖▗▖▗ 10.0us = ▗▖ in same datacenter: 500.0us CA to Netherlands: 150.0ms - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -100ns = ▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 1.0ms = ▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -  ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -# [github.com/chubin/late.nz] [MIT License] ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  -# Console port of "Jeff Dean's latency numbers" ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖   -# from [github.com/colin-scott/interactive_latencies] ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  - ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖  +▗▖ 100ns over commodity network: sequentially from SSD: + ▗▖ 22ns 30.856us +L1 cache reference: 1ns ▗ ▗ +▗▖ 1.0us + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ SSD random read: 16.0us Disk seek: +Branch mispredict: 3ns ▗▖▗ 2.1763760000000003ms +▗▖▗▖▗▖ ▗▖▗▖ + Compress 1KB wth Snappy: Read 1,000,000 bytes +L2 cache reference: 4ns 2.0us sequentially from memory: Read 1,000,000 bytes +▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 1.869us sequentially from disk: + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗ 624.999us +Mutex lock/unlock: 16ns ▗ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ Round trip +▗▖▗▖▗▖▗▖▗▖▗▖▗ 10.0us = ▗▖ in same datacenter: 500.0us Packet roundtrip + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ CA to Netherlands: 150.0ms +100ns = ▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ 1.0ms = ▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +# [github.com/chubin/late.nz] [MIT License] ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +# Console port of "Jeff Dean's latency numbers" ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ +# from [github.com/colin-scott/interactive_latencies] ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ + ▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖ diff --git a/tests/results/17 b/tests/results/17 index 6fb087ff..c879ee31 100644 --- a/tests/results/17 +++ b/tests/results/17 @@ -1,120 +1,120 @@ - cheat.sheets:az  -# Microsoft Azure CLI 2.0 -# Command-line tools for Azure +#[cheat.sheets:az] +# Microsoft Azure CLI 2.0 +# Command-line tools for Azure -# Install Azure CLI 2.0 with one curl command. -curl -L https://aka.ms/InstallAzureCli | bash +# Install Azure CLI 2.0 with one curl command. +curl -L https://aka.ms/InstallAzureCli | bash -# create a resource group named "MyRG" in the 'westus2' region -az group create -n MyRG -l westus2 +# create a resource group named "MyRG" in the 'westus2' region +az group create -n MyRG -l westus2 -# 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 MyRG \ - --ssh-key-value $HOME/.ssh/id_rsa.pub --image UbuntuLTS \ - --data-disk-sizes-gb 10 20 +# 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 MyRG \ + --ssh-key-value $HOME/.ssh/id_rsa.pub --image UbuntuLTS \ + --data-disk-sizes-gb 10 20 -# list VMs -az vm list --output table +# list VMs +az vm list --output table -# list only VMs having distinct state -az vm list -d --query "[?powerState=='VM running']" --output table +# 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 MyRG) -az vm delete -g MyRG -n MyLinuxVM --yes +# delete VM (with the name MyLinuxVM in the group MyRG) +az vm delete -g MyRG -n MyLinuxVM --yes -# Delete all VMs in a resource group -az vm delete --ids $(az vm list -g MyRG --query "[].id" -o tsv) +# Delete all VMs in a resource group +az vm delete --ids $(az vm list -g MyRG --query "[].id" -o tsv) -# Create an Image based on a running VM -az vm deallocate -g MyRG -n MyLinuxVM -az vm generalize -g MyRG -n MyLinuxVM -az image create --resource-group MyRG --name MyTestImage --source MyLinuxVM +# Create an Image based on a running VM +az vm deallocate -g MyRG -n MyLinuxVM +az vm generalize -g MyRG -n MyLinuxVM +az image create --resource-group MyRG --name MyTestImage --source MyLinuxVM -# Running VM based on a VHD -az storage blob upload --account-name "${account_name}" \ - --account-key "${account_key}" --container-name "${container}" --type page \ - --file "${file}" --name "${vhd}" -az disk create \ - --resource-group "${resource_group}" \ - --name myManagedDisk \ - --source "https://${account_name}.blob.core.windows.net/${container}/${vhd}" +# Running VM based on a VHD +az storage blob upload --account-name "${account_name}" \ + --account-key "${account_key}" --container-name "${container}" --type page \ + --file "${file}" --name "${vhd}" +az disk create \ + --resource-group "${resource_group}" \ + --name myManagedDisk \ + --source "https://${account_name}.blob.core.windows.net/${container}/${vhd}" -# open port -az vm open-port --resource-group MyRG --name MyLinuxVM --port 443 --priority 899 +# open port +az vm open-port --resource-group MyRG --name MyLinuxVM --port 443 --priority 899 -# Show storage accounts -az storage account list --output table +# Show storage accounts +az storage account list --output table -# Show containers for an account -az storage container list --account-name mystorageaccount --output table +# Show containers for an account +az storage container list --account-name mystorageaccount --output table -# Show blobs in a container -az storage blob list --account-name mystorageaccount \ - --container-name mycontainer --output table +# Show blobs in a container +az storage blob list --account-name mystorageaccount \ + --container-name mycontainer --output table -# list account keys -az storage account keys list --account-name STORAGE_NAME --resource-group RESOURCE_GROUP +# list account keys +az storage account keys list --account-name STORAGE_NAME --resource-group RESOURCE_GROUP -# Show own images -az image list --output table +# Show own images +az image list --output table -# Configure default storage location -az configure --defaults location=eastus2 +# Configure default storage location +az configure --defaults location=eastus2 -# Show disks -az disk list --output table +# Show disks +az disk list --output table -# Copy blob -az storage blob copy start \ - --source-uri 'https://xxx.blob.core.windows.net/jzwuuuzzapn0/abcd?...' \ - --account-key XXXXXXXXXX== \ - --account-name destaccount \ - --destination-container vms \ - --destination-blob DESTINATION-blob.vhd +# Copy blob +az storage blob copy start \ + --source-uri 'https://xxx.blob.core.windows.net/jzwuuuzzapn0/abcd?...' \ + --account-key XXXXXXXXXX== \ + --account-name destaccount \ + --destination-container vms \ + --destination-blob DESTINATION-blob.vhd -# List virtual networks -az network vnet list --output table +# List virtual networks +az network vnet list --output table -# List virtual networks adapters -az network nic list --output table +# List virtual networks adapters +az network nic list --output table -# List public IP addresses used by the VMs -az vm list-ip-addresses --output table +# List public IP addresses used by the VMs +az vm list-ip-addresses --output table -# create snapshot -az snapshot create --resource-group IC-EXASOL-001 --source vm1-disk1 -n vm1-snap1 +# create snapshot +az snapshot create --resource-group IC-EXASOL-001 --source vm1-disk1 -n vm1-snap1 -# 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 +# 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 -az vm disk attach --vm-name vm1 -g RESOURCE_GROUP --disk DISK1_ID +# attach disk +az vm disk attach --vm-name vm1 -g RESOURCE_GROUP --disk DISK1_ID -# detach disk -az vm disk detach --vm-name vm1 -g RESOURCE_GROUP --name DISK1_ID +# detach disk +az vm disk detach --vm-name vm1 -g RESOURCE_GROUP --name DISK1_ID - tldr:az  -# az -# The official CLI tool for Microsoft Azure. -# Some subcommands such as `az login` have their own usage documentation. -# More information: . +#[tldr:az] +# az +# The official CLI tool for Microsoft Azure. +# Some subcommands such as `az login` have their own usage documentation. +# More information: . -# Log in to Azure: -az login +# Log in to Azure: +az login -# Manage azure subscription information: -az account +# Manage azure subscription information: +az account -# List all Azure Managed Disks: -az disk list +# List all Azure Managed Disks: +az disk list -# List all Azure virtual machines: -az vm list +# List all Azure virtual machines: +az vm list -# Manage Azure Kubernetes Services: -az aks +# Manage Azure Kubernetes Services: +az aks -# Manage Azure Network resources: -az network +# Manage Azure Network resources: +az network diff --git a/tests/results/18 b/tests/results/18 index 651c8c08..cf255ee2 100644 --- a/tests/results/18 +++ b/tests/results/18 @@ -1,20 +1,20 @@ ->>> s = 'abcdefgh' ->>> n, m, char, chars = 2, 3, 'd', 'cd' ->>> # 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; ->>> s[n-1:] -'bcdefgh' ->>> # whole string minus last character; ->>> s[:-1] -'abcdefg' ->>> # 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. ->>> indx = s.index(chars) ->>> s[indx:indx+m] -'cde' ->>> +>>> s = 'abcdefgh' +>>> n, m, char, chars = 2, 3, 'd', 'cd' +>>> # 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; +>>> s[n-1:] +'bcdefgh' +>>> # whole string minus last character; +>>> s[:-1] +'abcdefg' +>>> # 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. +>>> indx = s.index(chars) +>>> s[indx:indx+m] +'cde' +>>> diff --git a/tests/results/2 b/tests/results/2 index 3d5b767b..4d9962fe 100644 --- a/tests/results/2 +++ b/tests/results/2 @@ -1,47 +1,59 @@ - cheat:ls  -# To display everything in , excluding hidden files: -ls <dir> +#[cheat:ls] +# To display everything in , excluding hidden files: +ls -# To display everything in , including hidden files: -ls -a <dir> +# To display everything in , including hidden files: +ls -a -# To display all files, along with the size (with unit suffixes) and timestamp -ls -lh <dir> +# To display all files, along with the size (with unit suffixes) and timestamp +ls -lh -# To display files, sorted by size: -ls -S <dir> +# To display files, sorted by size: +ls -S -# To display directories only: -ls -d */ <dir> +# To display directories only: +ls -d */ -# To display directories only, include hidden: -ls -d .*/ */ <dir> +# To display directories only, include hidden: +ls -d .*/ */ - tldr:ls  -# ls -# List directory contents. -# More information: . +# To display all files sorted by changed date, most recent first: +ls -ltc -# List files one per line: -ls -1 +# To display files sorted by create time: +ls -lt -# List all files, including hidden files: -ls -a +# To display files in a single column: +ls -1 -# List all files, with trailing `/` added to directory names: -ls -F +# To show ACLs (MacOS): +# see also `cheat chmod` for `/bin/chmod` options for ACLs +/bin/ls -le +#[tldr:ls] +# ls +# List directory contents. +# More information: . -# Long format list (permissions, ownership, size, and modification date) of all files: -ls -la +# List files one per line: +ls -1 -# Long format list with size displayed using human-readable units (KiB, MiB, GiB): -ls -lh +# List all files, including hidden files: +ls -a -# Long format list sorted by size (descending): -ls -lS +# List all files, with trailing `/` added to directory names: +ls -F -# Long format list of all files, sorted by modification date (oldest first): -ls -ltr +# Long format list (permissions, ownership, size, and modification date) of all files: +ls -la -# Only list directories: -ls -d */ +# Long format list with size displayed using human-readable units (KiB, MiB, GiB): +ls -lh + +# Long format list sorted by size (descending): +ls -lS + +# Long format list of all files, sorted by modification date (oldest first): +ls -ltr + +# Only list directories: +ls -d */ diff --git a/tests/results/21 b/tests/results/21 index bfd13d39..064340c5 100644 --- a/tests/results/21 +++ b/tests/results/21 @@ -1,606 +1,606 @@ -// 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 ; -doStuff(); +// Statements can be terminated by ; +doStuff(); -// ... but they don't have to be, as semicolons are automatically inserted -// wherever there's a newline, except in certain cases. -doStuff() +// ... 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. -true; -false; +// There's also a boolean type. +true; +false; -// Strings are created with ' or ". -'abc'; -"Hello, world"; +// 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 - -// 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; +/////////////////////////////////// +// 2. Variables, Arrays and Objects + +// Variables are declared with the `var` keyword. JavaScript is dynamically +// typed, so you don't need to specify type. Assignment uses a single `=` +// character. +var someVar = 5; -// If you leave the var keyword off, you won't get an error... -someOtherVar = 10; +// 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 - -// 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 - -// and an even-shorter-hand for adding or subtracting 1 -someVar++; // now someVar is 101 -someVar--; // back to 100 - -// Arrays are ordered lists of values, of any type. -var myArray = ["Hello", 45, true]; - -// Their members can be accessed using the square-brackets subscript syntax. -// Array indices start at zero. -myArray[1]; // = 45 - -// Arrays are mutable and of variable length. -myArray.push("World"); -myArray.length; // = 4 - -// 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 - -// Join all elements of an array with semicolon -var myArray0 = [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] - -// 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. -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. -var myObj = {myKey: "myValue", "my other key": 4}; - -// Object attributes can also be accessed using the subscript syntax, -myObj["my other key"]; // = 4 - -// ... or using the dot syntax, provided the key is a valid identifier. -myObj.myKey; // = "myValue" - -// Objects are mutable; values can be changed and new keys added. -myObj.myThirdKey = true; - -// If you try to access a value that's not yet set, you'll get undefined. -myObj.myFourthKey; // = undefined - -/////////////////////////////////// -// 3. Logic and Control Structures - -// The `if` structure works as you'd expect. -var count = 1; -if (count == 3){ - // evaluated if count is 3 -} else if (count == 4){ - // evaluated if count is 4 -} else { - // evaluated if it's not either 3 or 4 -} - -// As does `while`. -while (true){ - // An infinite loop! -} - -// Do-while loops are like while loops, except they always run at least once. -var input; -do { - input = getInput(); -} while (!isValid(input)); - -// The `for` loop is the same as C and Java: -// initialization; continue condition; iteration. -for (var i = 0; i < 5; i++){ - // will run 5 times -} - -// 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 - } - } -} - -// 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 ' - -// 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 ' - -// && is logical and, || is logical or -if (house.size == "big" && house.colour == "blue"){ - house.contains = "bear"; -} -if (colour == "red" || colour == "blue"){ - // colour is either red or blue -} - -// && and || "short circuit", which is useful for setting default values. -var name = otherName || "default"; - -// 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': - console.log("Great job"); - break; - case 'B': - console.log("OK job"); - break; - case 'C': - console.log("You can do better"); - break; - default: - console.log("Oy vey"); - break; -} - - -/////////////////////////////////// -// 4. Functions, Scope and Closures - -// JavaScript functions are declared with the `function` keyword. -function myFunction(thing){ - return thing.toUpperCase(); -} -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. -function myFunction(){ - return // <- semicolon automatically inserted here - {thisIsAn: 'object literal'}; -} -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: -function myFunction(){ - // 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. - -// Another function provided by browsers is setInterval -function myFunction(){ - // 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. -setTimeout(function(){ - // this code will be called in 5 seconds' time -}, 5000); - -// JavaScript has function scope; functions get their own scope but other blocks -// do not. -if (true){ - var i = 5; -} -i; // = 5 - not undefined as you'd expect in a block-scoped language - -// This has led to a common pattern of "immediately-executing anonymous -// functions", which prevent temporary variables from leaking into the global -// scope. -(function(){ - var temporary = 5; - // We can access the global scope by 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 - -// 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`. - 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. -} -sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s - -/////////////////////////////////// -// 5. More about Objects; Constructors and Prototypes - -// Objects can contain functions. -var myObj = { - myFunc: function(){ - return "Hello world!"; - } -}; -myObj.myFunc(); // = "Hello world!" - -// When functions attached to an object are called, they can access the object -// they're attached to using the `this` keyword. -myObj = { - myString: "Hello world!", - myFunc: function(){ - return this.myString; - } -}; -myObj.myFunc(); // = "Hello world!" - -// What this is set to has to do with how the function is called, not where -// it's defined. So, our function doesn't work if it isn't called in the -// context of the object. -var myFunc = myObj.myFunc; -myFunc(); // = undefined - -// Inversely, a function can be assigned to the object and gain access to it -// through `this`, even if it wasn't attached when it was defined. -var myOtherFunc = function(){ - return this.myString.toUpperCase(); -}; -myObj.myOtherFunc = myOtherFunc; -myObj.myOtherFunc(); // = "HELLO WORLD!" - -// 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!" - -// 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!" - -// 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 - -// 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!" - -// `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 - -// 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 - -// 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. - -// Some JS implementations let you access an object's prototype on the magic -// property `__proto__`. While this is useful for explaining prototypes it's not -// part of the standard; we'll get to standard ways of using prototypes later. -var myObj = { - myString: "Hello world!" -}; -var myPrototype = { - meaningOfLife: 42, - myFunc: function(){ - return this.myString.toLowerCase(); - } -}; - -myObj.__proto__ = myPrototype; -myObj.meaningOfLife; // = 42 - -// This works for functions, too. -myObj.myFunc(); // = "hello world!" - -// Of course, if your property isn't on your prototype, the prototype's -// prototype is searched, and so on. -myPrototype.__proto__ = { - myBoolean: true -}; -myObj.myBoolean; // = true - -// There's no copying involved here; each object stores a reference to its -// prototype. This means we can alter the prototype and our changes will be -// reflected everywhere. -myPrototype.meaningOfLife = 43; -myObj.meaningOfLife; // = 43 - -// 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 - -// 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! - -// 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. -var myObj = Object.create(myPrototype); -myObj.meaningOfLife; // = 43 - -// The second way, which works anywhere, has to do with constructors. -// Constructors have a property called prototype. This is *not* the prototype of -// the constructor function itself; instead, it's the prototype that new objects -// are given when they're created with that constructor and the new keyword. -MyConstructor.prototype = { - myNumber: 5, - getMyNumber: function(){ - return this.myNumber; - } -}; -var myNewObj2 = new MyConstructor(); -myNewObj2.getMyNumber(); // = 5 -myNewObj2.myNumber = 6; -myNewObj2.getMyNumber(); // = 6 - -// Built-in types like strings and numbers also have constructors that create -// equivalent wrapper objects. -var myNumber = 12; -var myNumberObj = new Number(12); -myNumber == myNumberObj; // = true - -// Except, they aren't exactly equivalent. -typeof myNumber; // = 'number' -typeof myNumberObj; // = 'object' -myNumber === myNumberObj; // = false -if (0){ - // This code won't execute, because 0 is falsy. -} -if (new Number(0)){ - // 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. -String.prototype.firstCharacter = function(){ - return this.charAt(0); -}; -"abc".firstCharacter(); // = "a" - -// This fact is often used in "polyfilling", which is implementing newer -// features of JavaScript in an older subset of JavaScript, so that they can be -// used in older environments such as outdated browsers. - -// For instance, we mentioned that Object.create isn't yet available in all -// implementations, but we can still use it with this polyfill: -if (Object.create === undefined){ // don't overwrite it if it exists - Object.create = function(proto){ - // make a temporary constructor with the right prototype - var Constructor = function(){}; - Constructor.prototype = proto; - // then use it to create a new, appropriately-prototyped object - return new Constructor(); - }; -} - -// 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; -}; +// 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 +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 + +// and an even-shorter-hand for adding or subtracting 1 +someVar++; // now someVar is 101 +someVar--; // back to 100 + +// Arrays are ordered lists of values, of any type. +var myArray = ["Hello", 45, true]; + +// Their members can be accessed using the square-brackets subscript syntax. +// Array indices start at zero. +myArray[1]; // = 45 + +// Arrays are mutable and of variable length. +myArray.push("World"); +myArray.length; // = 4 + +// 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 + +// Join all elements of an array with semicolon +var myArray0 = [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] + +// 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. +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. +var myObj = {myKey: "myValue", "my other key": 4}; + +// Object attributes can also be accessed using the subscript syntax, +myObj["my other key"]; // = 4 + +// ... or using the dot syntax, provided the key is a valid identifier. +myObj.myKey; // = "myValue" + +// Objects are mutable; values can be changed and new keys added. +myObj.myThirdKey = true; + +// If you try to access a value that's not yet set, you'll get undefined. +myObj.myFourthKey; // = undefined + +/////////////////////////////////// +// 3. Logic and Control Structures + +// The `if` structure works as you'd expect. +var count = 1; +if (count == 3){ + // evaluated if count is 3 +} else if (count == 4){ + // evaluated if count is 4 +} else { + // evaluated if it's not either 3 or 4 +} + +// As does `while`. +while (true){ + // An infinite loop! +} + +// Do-while loops are like while loops, except they always run at least once. +var input; +do { + input = getInput(); +} while (!isValid(input)); + +// The `for` loop is the same as C and Java: +// initialization; continue condition; iteration. +for (var i = 0; i < 5; i++){ + // will run 5 times +} + +// 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 + } + } +} + +// 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 ' + +// 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 ' + +// && is logical and, || is logical or +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear"; +} +if (colour == "red" || colour == "blue"){ + // colour is either red or blue +} + +// && and || "short circuit", which is useful for setting default values. +var name = otherName || "default"; + +// 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': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} + + +/////////////////////////////////// +// 4. Functions, Scope and Closures + +// JavaScript functions are declared with the `function` keyword. +function myFunction(thing){ + return thing.toUpperCase(); +} +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. +function myFunction(){ + return // <- semicolon automatically inserted here + {thisIsAn: 'object literal'}; +} +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: +function myFunction(){ + // 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. + +// Another function provided by browsers is setInterval +function myFunction(){ + // 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. +setTimeout(function(){ + // this code will be called in 5 seconds' time +}, 5000); + +// JavaScript has function scope; functions get their own scope but other blocks +// do not. +if (true){ + var i = 5; +} +i; // = 5 - not undefined as you'd expect in a block-scoped language + +// This has led to a common pattern of "immediately-executing anonymous +// functions", which prevent temporary variables from leaking into the global +// scope. +(function(){ + var temporary = 5; + // We can access the global scope by 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 + +// 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`. + 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. +} +sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s + +/////////////////////////////////// +// 5. More about Objects; Constructors and Prototypes + +// Objects can contain functions. +var myObj = { + myFunc: function(){ + return "Hello world!"; + } +}; +myObj.myFunc(); // = "Hello world!" + +// When functions attached to an object are called, they can access the object +// they're attached to using the `this` keyword. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString; + } +}; +myObj.myFunc(); // = "Hello world!" + +// What this is set to has to do with how the function is called, not where +// it's defined. So, our function doesn't work if it isn't called in the +// context of the object. +var myFunc = myObj.myFunc; +myFunc(); // = undefined + +// Inversely, a function can be assigned to the object and gain access to it +// through `this`, even if it wasn't attached when it was defined. +var myOtherFunc = function(){ + return this.myString.toUpperCase(); +}; +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// 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!" + +// 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!" + +// 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 + +// 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!" + +// `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 + +// 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 + +// 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. + +// Some JS implementations let you access an object's prototype on the magic +// property `__proto__`. While this is useful for explaining prototypes it's not +// part of the standard; we'll get to standard ways of using prototypes later. +var myObj = { + myString: "Hello world!" +}; +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase(); + } +}; + +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42 + +// This works for functions, too. +myObj.myFunc(); // = "hello world!" + +// Of course, if your property isn't on your prototype, the prototype's +// prototype is searched, and so on. +myPrototype.__proto__ = { + myBoolean: true +}; +myObj.myBoolean; // = true + +// There's no copying involved here; each object stores a reference to its +// prototype. This means we can alter the prototype and our changes will be +// reflected everywhere. +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// 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 + +// 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! + +// 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. +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// The second way, which works anywhere, has to do with constructors. +// Constructors have a property called prototype. This is *not* the prototype of +// the constructor function itself; instead, it's the prototype that new objects +// are given when they're created with that constructor and the new keyword. +MyConstructor.prototype = { + myNumber: 5, + getMyNumber: function(){ + return this.myNumber; + } +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 +myNewObj2.myNumber = 6; +myNewObj2.getMyNumber(); // = 6 + +// Built-in types like strings and numbers also have constructors that create +// equivalent wrapper objects. +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true + +// Except, they aren't exactly equivalent. +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false +if (0){ + // This code won't execute, because 0 is falsy. +} +if (new Number(0)){ + // 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. +String.prototype.firstCharacter = function(){ + return this.charAt(0); +}; +"abc".firstCharacter(); // = "a" + +// This fact is often used in "polyfilling", which is implementing newer +// features of JavaScript in an older subset of JavaScript, so that they can be +// used in older environments such as outdated browsers. + +// For instance, we mentioned that Object.create isn't yet available in all +// implementations, but we can still use it with this polyfill: +if (Object.create === undefined){ // don't overwrite it if it exists + Object.create = function(proto){ + // make a temporary constructor with the right prototype + var Constructor = function(){}; + Constructor.prototype = proto; + // then use it to create a new, appropriately-prototyped object + return new Constructor(); + }; +} + +// ES6 Additions + +// The "let" keyword allows you to define variables in a lexical scope, +// as opposed to a function 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 bfd13d39..064340c5 100644 --- a/tests/results/22 +++ b/tests/results/22 @@ -1,606 +1,606 @@ -// 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 ; -doStuff(); +// Statements can be terminated by ; +doStuff(); -// ... but they don't have to be, as semicolons are automatically inserted -// wherever there's a newline, except in certain cases. -doStuff() +// ... 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. -true; -false; +// There's also a boolean type. +true; +false; -// Strings are created with ' or ". -'abc'; -"Hello, world"; +// 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 - -// 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; +/////////////////////////////////// +// 2. Variables, Arrays and Objects + +// Variables are declared with the `var` keyword. JavaScript is dynamically +// typed, so you don't need to specify type. Assignment uses a single `=` +// character. +var someVar = 5; -// If you leave the var keyword off, you won't get an error... -someOtherVar = 10; +// 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 - -// 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 - -// and an even-shorter-hand for adding or subtracting 1 -someVar++; // now someVar is 101 -someVar--; // back to 100 - -// Arrays are ordered lists of values, of any type. -var myArray = ["Hello", 45, true]; - -// Their members can be accessed using the square-brackets subscript syntax. -// Array indices start at zero. -myArray[1]; // = 45 - -// Arrays are mutable and of variable length. -myArray.push("World"); -myArray.length; // = 4 - -// 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 - -// Join all elements of an array with semicolon -var myArray0 = [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] - -// 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. -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. -var myObj = {myKey: "myValue", "my other key": 4}; - -// Object attributes can also be accessed using the subscript syntax, -myObj["my other key"]; // = 4 - -// ... or using the dot syntax, provided the key is a valid identifier. -myObj.myKey; // = "myValue" - -// Objects are mutable; values can be changed and new keys added. -myObj.myThirdKey = true; - -// If you try to access a value that's not yet set, you'll get undefined. -myObj.myFourthKey; // = undefined - -/////////////////////////////////// -// 3. Logic and Control Structures - -// The `if` structure works as you'd expect. -var count = 1; -if (count == 3){ - // evaluated if count is 3 -} else if (count == 4){ - // evaluated if count is 4 -} else { - // evaluated if it's not either 3 or 4 -} - -// As does `while`. -while (true){ - // An infinite loop! -} - -// Do-while loops are like while loops, except they always run at least once. -var input; -do { - input = getInput(); -} while (!isValid(input)); - -// The `for` loop is the same as C and Java: -// initialization; continue condition; iteration. -for (var i = 0; i < 5; i++){ - // will run 5 times -} - -// 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 - } - } -} - -// 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 ' - -// 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 ' - -// && is logical and, || is logical or -if (house.size == "big" && house.colour == "blue"){ - house.contains = "bear"; -} -if (colour == "red" || colour == "blue"){ - // colour is either red or blue -} - -// && and || "short circuit", which is useful for setting default values. -var name = otherName || "default"; - -// 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': - console.log("Great job"); - break; - case 'B': - console.log("OK job"); - break; - case 'C': - console.log("You can do better"); - break; - default: - console.log("Oy vey"); - break; -} - - -/////////////////////////////////// -// 4. Functions, Scope and Closures - -// JavaScript functions are declared with the `function` keyword. -function myFunction(thing){ - return thing.toUpperCase(); -} -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. -function myFunction(){ - return // <- semicolon automatically inserted here - {thisIsAn: 'object literal'}; -} -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: -function myFunction(){ - // 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. - -// Another function provided by browsers is setInterval -function myFunction(){ - // 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. -setTimeout(function(){ - // this code will be called in 5 seconds' time -}, 5000); - -// JavaScript has function scope; functions get their own scope but other blocks -// do not. -if (true){ - var i = 5; -} -i; // = 5 - not undefined as you'd expect in a block-scoped language - -// This has led to a common pattern of "immediately-executing anonymous -// functions", which prevent temporary variables from leaking into the global -// scope. -(function(){ - var temporary = 5; - // We can access the global scope by 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 - -// 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`. - 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. -} -sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s - -/////////////////////////////////// -// 5. More about Objects; Constructors and Prototypes - -// Objects can contain functions. -var myObj = { - myFunc: function(){ - return "Hello world!"; - } -}; -myObj.myFunc(); // = "Hello world!" - -// When functions attached to an object are called, they can access the object -// they're attached to using the `this` keyword. -myObj = { - myString: "Hello world!", - myFunc: function(){ - return this.myString; - } -}; -myObj.myFunc(); // = "Hello world!" - -// What this is set to has to do with how the function is called, not where -// it's defined. So, our function doesn't work if it isn't called in the -// context of the object. -var myFunc = myObj.myFunc; -myFunc(); // = undefined - -// Inversely, a function can be assigned to the object and gain access to it -// through `this`, even if it wasn't attached when it was defined. -var myOtherFunc = function(){ - return this.myString.toUpperCase(); -}; -myObj.myOtherFunc = myOtherFunc; -myObj.myOtherFunc(); // = "HELLO WORLD!" - -// 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!" - -// 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!" - -// 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 - -// 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!" - -// `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 - -// 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 - -// 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. - -// Some JS implementations let you access an object's prototype on the magic -// property `__proto__`. While this is useful for explaining prototypes it's not -// part of the standard; we'll get to standard ways of using prototypes later. -var myObj = { - myString: "Hello world!" -}; -var myPrototype = { - meaningOfLife: 42, - myFunc: function(){ - return this.myString.toLowerCase(); - } -}; - -myObj.__proto__ = myPrototype; -myObj.meaningOfLife; // = 42 - -// This works for functions, too. -myObj.myFunc(); // = "hello world!" - -// Of course, if your property isn't on your prototype, the prototype's -// prototype is searched, and so on. -myPrototype.__proto__ = { - myBoolean: true -}; -myObj.myBoolean; // = true - -// There's no copying involved here; each object stores a reference to its -// prototype. This means we can alter the prototype and our changes will be -// reflected everywhere. -myPrototype.meaningOfLife = 43; -myObj.meaningOfLife; // = 43 - -// 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 - -// 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! - -// 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. -var myObj = Object.create(myPrototype); -myObj.meaningOfLife; // = 43 - -// The second way, which works anywhere, has to do with constructors. -// Constructors have a property called prototype. This is *not* the prototype of -// the constructor function itself; instead, it's the prototype that new objects -// are given when they're created with that constructor and the new keyword. -MyConstructor.prototype = { - myNumber: 5, - getMyNumber: function(){ - return this.myNumber; - } -}; -var myNewObj2 = new MyConstructor(); -myNewObj2.getMyNumber(); // = 5 -myNewObj2.myNumber = 6; -myNewObj2.getMyNumber(); // = 6 - -// Built-in types like strings and numbers also have constructors that create -// equivalent wrapper objects. -var myNumber = 12; -var myNumberObj = new Number(12); -myNumber == myNumberObj; // = true - -// Except, they aren't exactly equivalent. -typeof myNumber; // = 'number' -typeof myNumberObj; // = 'object' -myNumber === myNumberObj; // = false -if (0){ - // This code won't execute, because 0 is falsy. -} -if (new Number(0)){ - // 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. -String.prototype.firstCharacter = function(){ - return this.charAt(0); -}; -"abc".firstCharacter(); // = "a" - -// This fact is often used in "polyfilling", which is implementing newer -// features of JavaScript in an older subset of JavaScript, so that they can be -// used in older environments such as outdated browsers. - -// For instance, we mentioned that Object.create isn't yet available in all -// implementations, but we can still use it with this polyfill: -if (Object.create === undefined){ // don't overwrite it if it exists - Object.create = function(proto){ - // make a temporary constructor with the right prototype - var Constructor = function(){}; - Constructor.prototype = proto; - // then use it to create a new, appropriately-prototyped object - return new Constructor(); - }; -} - -// 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; -}; +// 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 +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 + +// and an even-shorter-hand for adding or subtracting 1 +someVar++; // now someVar is 101 +someVar--; // back to 100 + +// Arrays are ordered lists of values, of any type. +var myArray = ["Hello", 45, true]; + +// Their members can be accessed using the square-brackets subscript syntax. +// Array indices start at zero. +myArray[1]; // = 45 + +// Arrays are mutable and of variable length. +myArray.push("World"); +myArray.length; // = 4 + +// 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 + +// Join all elements of an array with semicolon +var myArray0 = [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] + +// 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. +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. +var myObj = {myKey: "myValue", "my other key": 4}; + +// Object attributes can also be accessed using the subscript syntax, +myObj["my other key"]; // = 4 + +// ... or using the dot syntax, provided the key is a valid identifier. +myObj.myKey; // = "myValue" + +// Objects are mutable; values can be changed and new keys added. +myObj.myThirdKey = true; + +// If you try to access a value that's not yet set, you'll get undefined. +myObj.myFourthKey; // = undefined + +/////////////////////////////////// +// 3. Logic and Control Structures + +// The `if` structure works as you'd expect. +var count = 1; +if (count == 3){ + // evaluated if count is 3 +} else if (count == 4){ + // evaluated if count is 4 +} else { + // evaluated if it's not either 3 or 4 +} + +// As does `while`. +while (true){ + // An infinite loop! +} + +// Do-while loops are like while loops, except they always run at least once. +var input; +do { + input = getInput(); +} while (!isValid(input)); + +// The `for` loop is the same as C and Java: +// initialization; continue condition; iteration. +for (var i = 0; i < 5; i++){ + // will run 5 times +} + +// 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 + } + } +} + +// 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 ' + +// 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 ' + +// && is logical and, || is logical or +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear"; +} +if (colour == "red" || colour == "blue"){ + // colour is either red or blue +} + +// && and || "short circuit", which is useful for setting default values. +var name = otherName || "default"; + +// 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': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} + + +/////////////////////////////////// +// 4. Functions, Scope and Closures + +// JavaScript functions are declared with the `function` keyword. +function myFunction(thing){ + return thing.toUpperCase(); +} +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. +function myFunction(){ + return // <- semicolon automatically inserted here + {thisIsAn: 'object literal'}; +} +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: +function myFunction(){ + // 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. + +// Another function provided by browsers is setInterval +function myFunction(){ + // 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. +setTimeout(function(){ + // this code will be called in 5 seconds' time +}, 5000); + +// JavaScript has function scope; functions get their own scope but other blocks +// do not. +if (true){ + var i = 5; +} +i; // = 5 - not undefined as you'd expect in a block-scoped language + +// This has led to a common pattern of "immediately-executing anonymous +// functions", which prevent temporary variables from leaking into the global +// scope. +(function(){ + var temporary = 5; + // We can access the global scope by 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 + +// 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`. + 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. +} +sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s + +/////////////////////////////////// +// 5. More about Objects; Constructors and Prototypes + +// Objects can contain functions. +var myObj = { + myFunc: function(){ + return "Hello world!"; + } +}; +myObj.myFunc(); // = "Hello world!" + +// When functions attached to an object are called, they can access the object +// they're attached to using the `this` keyword. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString; + } +}; +myObj.myFunc(); // = "Hello world!" + +// What this is set to has to do with how the function is called, not where +// it's defined. So, our function doesn't work if it isn't called in the +// context of the object. +var myFunc = myObj.myFunc; +myFunc(); // = undefined + +// Inversely, a function can be assigned to the object and gain access to it +// through `this`, even if it wasn't attached when it was defined. +var myOtherFunc = function(){ + return this.myString.toUpperCase(); +}; +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// 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!" + +// 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!" + +// 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 + +// 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!" + +// `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 + +// 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 + +// 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. + +// Some JS implementations let you access an object's prototype on the magic +// property `__proto__`. While this is useful for explaining prototypes it's not +// part of the standard; we'll get to standard ways of using prototypes later. +var myObj = { + myString: "Hello world!" +}; +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase(); + } +}; + +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42 + +// This works for functions, too. +myObj.myFunc(); // = "hello world!" + +// Of course, if your property isn't on your prototype, the prototype's +// prototype is searched, and so on. +myPrototype.__proto__ = { + myBoolean: true +}; +myObj.myBoolean; // = true + +// There's no copying involved here; each object stores a reference to its +// prototype. This means we can alter the prototype and our changes will be +// reflected everywhere. +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// 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 + +// 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! + +// 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. +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// The second way, which works anywhere, has to do with constructors. +// Constructors have a property called prototype. This is *not* the prototype of +// the constructor function itself; instead, it's the prototype that new objects +// are given when they're created with that constructor and the new keyword. +MyConstructor.prototype = { + myNumber: 5, + getMyNumber: function(){ + return this.myNumber; + } +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 +myNewObj2.myNumber = 6; +myNewObj2.getMyNumber(); // = 6 + +// Built-in types like strings and numbers also have constructors that create +// equivalent wrapper objects. +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true + +// Except, they aren't exactly equivalent. +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false +if (0){ + // This code won't execute, because 0 is falsy. +} +if (new Number(0)){ + // 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. +String.prototype.firstCharacter = function(){ + return this.charAt(0); +}; +"abc".firstCharacter(); // = "a" + +// This fact is often used in "polyfilling", which is implementing newer +// features of JavaScript in an older subset of JavaScript, so that they can be +// used in older environments such as outdated browsers. + +// For instance, we mentioned that Object.create isn't yet available in all +// implementations, but we can still use it with this polyfill: +if (Object.create === undefined){ // don't overwrite it if it exists + Object.create = function(proto){ + // make a temporary constructor with the right prototype + var Constructor = function(){}; + Constructor.prototype = proto; + // then use it to create a new, appropriately-prototyped object + return new Constructor(); + }; +} + +// ES6 Additions + +// The "let" keyword allows you to define variables in a lexical scope, +// as opposed to a function 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 a271fdb6..4d9962fe 100644 --- a/tests/results/3 +++ b/tests/results/3 @@ -16,6 +16,19 @@ ls -d */ # To display directories only, include hidden: ls -d .*/ */ + +# To display all files sorted by changed date, most recent first: +ls -ltc + +# To display files sorted by create time: +ls -lt + +# To display files in a single column: +ls -1 + +# To show ACLs (MacOS): +# see also `cheat chmod` for `/bin/chmod` options for ACLs +/bin/ls -le #[tldr:ls] # ls # List directory contents. diff --git a/tests/results/4 b/tests/results/4 index 692a2f66..02327463 100644 --- a/tests/results/4 +++ b/tests/results/4 @@ -1,76 +1,76 @@ - cheat.sheets:btrfs  -# Create a btrfs file system on /dev/sdb, /dev/sdc, and /dev/sdd -mkfs.btrfs /dev/sdb /dev/sdc /dev/sdd +#[cheat.sheets:btrfs] +# 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 dangerous: if your metadata is lost, your data is lost as well) -mkfs.btrfs -m single /dev/sdb +# btrfs with just one hard drive, metadata not redundant +# (this is dangerous: 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: -mkfs.btrfs -m raid0 -d raid1 /dev/sdb /dev/sdc /dev/sdd +# 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 redundant -mkfs.btrfs -d raid1 /dev/sdb /dev/sdc /dev/sdd +# both data and metadata to be redundant +mkfs.btrfs -d raid1 /dev/sdb /dev/sdc /dev/sdd -# To get a list of all btrfs file systems -btrfs filesystem show +# To get a list of all btrfs file systems +btrfs filesystem show -# detailed df for a filesystem (mounted in /mnt) -btrfs filesystem df /mnt +# detailed df for a filesystem (mounted in /mnt) +btrfs filesystem df /mnt -# resize btrfs online (-2g decreases, +2g increases) -btrfs filesystem resize -2g /mnt +# resize btrfs online (-2g decreases, +2g increases) +btrfs filesystem resize -2g /mnt -# use maximum space -btrfs filesystem resize max /mnt +# use maximum space +btrfs filesystem resize max /mnt -# add new device to a filesystem -btrfs device add /dev/sdf /mnt +# add new device to a filesystem +btrfs device add /dev/sdf /mnt -# remove devices from a filesystem -btrfs device delete missing /mnt +# remove devices from a filesystem +btrfs device delete missing /mnt -# create the subvolume /mnt/sv1 in the /mnt volume -btrfs subvolume create /mnt/sv1 +# create the subvolume /mnt/sv1 in the /mnt volume +btrfs subvolume create /mnt/sv1 -# list subvolumes -btrfs subvolume list /mnt +# list subvolumes +btrfs subvolume list /mnt -# mount subvolume without mounting the main filesystem -mount -o subvol=sv1 /dev/sdb /mnt +# mount subvolume without mounting the main filesystem +mount -o subvol=sv1 /dev/sdb /mnt -# delete subvolume -btrfs subvolume delete /mnt/sv1 +# delete subvolume +btrfs subvolume delete /mnt/sv1 -# taking snapshot of a subvolume -btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot +# taking snapshot of a subvolume +btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot -# taking snapshot of a file (copy file by reference) -cp --reflink /mnt/sv1/test1 /mnt/sv1/test3 +# taking snapshot of a file (copy file by reference) +cp --reflink /mnt/sv1/test1 /mnt/sv1/test3 -# convert ext3/ext4 to btrfs -btrfs-convert /dev/sdb1 +# convert ext3/ext4 to btrfs +btrfs-convert /dev/sdb1 -# convert btrfs to ext3/ext4 -btrfs-convert -r /dev/sdb1 +# convert btrfs to ext3/ext4 +btrfs-convert -r /dev/sdb1 - tldr:btrfs  -# btrfs -# A filesystem based on the copy-on-write (COW) principle for Linux. -# Some subcommands such as `btrfs device` have their own usage documentation. -# More information: . +#[tldr:btrfs] +# btrfs +# A filesystem based on the copy-on-write (COW) principle for Linux. +# Some subcommands such as `btrfs device` have their own usage documentation. +# More information: . -# Create subvolume: -sudo btrfs subvolume create path/to/subvolume +# Create subvolume: +sudo btrfs subvolume create path/to/subvolume -# List subvolumes: -sudo btrfs subvolume list path/to/mount_point +# List subvolumes: +sudo btrfs subvolume list path/to/mount_point -# Show space usage information: -sudo btrfs filesystem df path/to/mount_point +# Show space usage information: +sudo btrfs filesystem df path/to/mount_point -# Enable quota: -sudo btrfs quota enable path/to/subvolume +# Enable quota: +sudo btrfs quota enable path/to/subvolume -# Show quota: -sudo btrfs qgroup show path/to/subvolume +# Show quota: +sudo btrfs qgroup show path/to/subvolume diff --git a/tests/results/5 b/tests/results/5 index d3accee7..df0dc876 100644 --- a/tests/results/5 +++ b/tests/results/5 @@ -1,55 +1,56 @@ - cheat.sheets:btrfs  -# create the subvolume /mnt/sv1 in the /mnt volume -btrfs subvolume create /mnt/sv1 - -# list subvolumes -btrfs subvolume list /mnt - -# mount subvolume without mounting the main filesystem -mount -o subvol=sv1 /dev/sdb /mnt - -# delete subvolume -btrfs subvolume delete /mnt/sv1 - -# taking snapshot of a subvolume -btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot - - tldr:btrfs  -# Create subvolume: -sudo btrfs subvolume create path/to/subvolume - -# List subvolumes: -sudo btrfs subvolume list path/to/mount_point - -# Enable quota: -sudo btrfs quota enable path/to/subvolume - -# Show quota: -sudo btrfs qgroup show path/to/subvolume - - tldr:btrfs-filesystem  -# Defragment a directory recursively (does not cross subvolume boundaries): -sudo btrfs filesystem defragment -v -r path/to/directory - - tldr:btrfs-subvolume  -# btrfs subvolume -# Manage btrfs subvolumes and snapshots. -# More information: . - -# Create a new empty subvolume: -sudo btrfs subvolume create path/to/new_subvolume - -# List all subvolumes and snapshots in the specified filesystem: -sudo btrfs subvolume list path/to/btrfs_filesystem - -# Delete a subvolume: -sudo btrfs subvolume delete path/to/subvolume - -# Create a read-only snapshot of an existing subvolume: -sudo btrfs subvolume snapshot -r path/to/source_subvolume path/to/target - -# Create a read-write snapshot of an existing subvolume: -sudo btrfs subvolume snapshot path/to/source_subvolume path/to/target - -# Show detailed information about a subvolume: -sudo btrfs subvolume show path/to/subvolume +#[cheat.sheets:btrfs] +# create the subvolume /mnt/sv1 in the /mnt volume +btrfs subvolume create /mnt/sv1 + +# list subvolumes +btrfs subvolume list /mnt + +# mount subvolume without mounting the main filesystem +mount -o subvol=sv1 /dev/sdb /mnt + +# delete subvolume +btrfs subvolume delete /mnt/sv1 + +# taking snapshot of a subvolume +btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot +#[tldr:btrfs] +# Create subvolume: +sudo btrfs subvolume create path/to/subvolume + +# List subvolumes: +sudo btrfs subvolume list path/to/mount_point + +# Enable quota: +sudo btrfs quota enable path/to/subvolume + +# Show quota: +sudo btrfs qgroup show path/to/subvolume +#[tldr:btrfs-filesystem] +# Defragment a directory recursively (does not cross subvolume boundaries): +sudo btrfs filesystem defragment -v -r path/to/directory +#[tldr:btrfs-property] +# btrfs property +# Get, set, or list properties for a given btrfs filesystem object (files, directories, subvolumes, filesystems, or devices). +# More information: . +#[tldr:btrfs-subvolume] +# btrfs subvolume +# Manage btrfs subvolumes and snapshots. +# More information: . + +# Create a new empty subvolume: +sudo btrfs subvolume create path/to/new_subvolume + +# List all subvolumes and snapshots in the specified filesystem: +sudo btrfs subvolume list path/to/btrfs_filesystem + +# Delete a subvolume: +sudo btrfs subvolume delete path/to/subvolume + +# Create a read-only snapshot of an existing subvolume: +sudo btrfs subvolume snapshot -r path/to/source_subvolume path/to/target + +# Create a read-write snapshot of an existing subvolume: +sudo btrfs subvolume snapshot path/to/source_subvolume path/to/target + +# Show detailed information about a subvolume: +sudo btrfs subvolume show path/to/subvolume diff --git a/tests/results/6 b/tests/results/6 index d05344dc..807b498f 100644 --- a/tests/results/6 +++ b/tests/results/6 @@ -1,16 +1,16 @@ -## curl cht.sh +## curl cht.sh To access a cheat sheet you can simply issue a plain HTTP or HTTPS request specifying the topic name in the query URL: - curl cheat.sh/tar - curl https://cheat.sh/tar + curl cheat.sh/tar + curl https://cheat.sh/tar -You can use the full service name, cheat.sh, or the shorter variant, cht.sh. +You can use the full service name, cheat.sh, or the shorter variant, cht.sh. They are equivalent: - curl https://cht.sh/tar - curl https://cheat.sh/tar + curl https://cht.sh/tar + curl https://cheat.sh/tar The preferred access protocol is HTTPS, and you should use it always when possible. @@ -18,116 +18,116 @@ Cheat sheets in the root namespaces cover UNIX/Linux commands. Cheat sheets covering programming languages are located in subsections: - curl cht.sh/go/func + curl cht.sh/go/func -All cheat sheets in a subsection can be listed using a special query :list : +All cheat sheets in a subsection can be listed using a special query :list : - curl cht.sh/go/:list + curl cht.sh/go/:list -There are several other special queries. All of them are starting with a colon. -See /:help for the full list of the special queries. +There are several other special queries. All of them are starting with a colon. +See /:help for the full list of the special queries. -## Search +## Search If a cheat sheet is too large, you can cut the needed part out using an additional search parameter. In this case, only the paragraph that contains the search term will be displayed: - curl cht.sh/tar~extract + curl cht.sh/tar~extract If the name of the cheat sheet is omitted, and only the serch query is specified, all cheat sheets in the namespace are scanned, and the found occurrencies are displayed: - curl cht.sh/~extract + curl cht.sh/~extract -## Options +## Options cheat.sh queries as well as search queries have many options. -They can be specified as a part of the query string in the URL, after ?. +They can be specified as a part of the query string in the URL, after ?. Short single letter options could be written all jointly together, -and long options are separated with &. For example, to switch -syntax highlighting off the T switch is used: +and long options are separated with &. For example, to switch +syntax highlighting off the T switch is used: - curl cht.sh/tar?T + curl cht.sh/tar?T Full list of all available cheat.sh options as well as description of all modes -of operation can be found in /:help, +of operation can be found in /:help, - curl cht.sh/:help + curl cht.sh/:help -## cht.sh client +## cht.sh client -Though it's perfectly possible to access cheat.sh using curl (or any other +Though it's perfectly possible to access cheat.sh using curl (or any other HTTP client) alone, there is a special client, that has several advantages -comparing to plain curling: cht.sh. +comparing to plain curling: cht.sh. -To install the client in ~/bin: +To install the client in ~/bin: - curl https://cht.sh/:cht.sh > ~/bin/cht.sh - chmod +x ~/bin/cht.sh + curl https://cht.sh/:cht.sh > ~/bin/cht.sh + chmod +x ~/bin/cht.sh -Queries look the same, but you can separate words in the query with spaces, -instead of + as when using curl, what looks more natural: +Queries look the same, but you can separate words in the query with spaces, +instead of + as when using curl, what looks more natural: - cht.sh python zip lists + cht.sh python zip lists -## cht.sh shell +## cht.sh shell If you always issuing queries about the same programming language, it's can be more convenient to run the client in the shell mode and specify the queries context: - $ cht.sh --shell python - cht.sh/python> zip lists + $ cht.sh --shell python + cht.sh/python> zip lists Of course, you can start the shell without the context too: - $ cht.sh --shell - cht.sh> python zip lists - cht.sh> go http query - cht.sh> js iterate list + $ cht.sh --shell + cht.sh> python zip lists + cht.sh> go http query + cht.sh> js iterate list If you use predominantly one language but sometime issuing queries about other, -you may prepend the query with /: +you may prepend the query with /: - cht.sh/python> zip lists - cht.sh/python> /go http query - cht.sh/python> /js iterate list + cht.sh/python> zip lists + cht.sh/python> /go http query + cht.sh/python> /js iterate list -## :learn +## :learn If you are just start learning a new programming language, and you have no distinct queries for the moment, cheat.sh can be a good starting point too. As you know, it exports cheat sheets from the best cheat sheet repositories, and -one of them is Learn X in Y, a repository of concise documentation devoted +one of them is Learn X in Y, a repository of concise documentation devoted to learning programming languages from scratch (and not only them). If you want start learning a new programming language, do (use less -R because the output could be quite big): - curl cht.sh/elixir/:learn | less -R + curl cht.sh/elixir/:learn | less -R -Or simply :learn with cht.sh (you don't need less -R here, because -cht.sh starts pager if needed automatically): +Or simply :learn with cht.sh (you don't need less -R here, because +cht.sh starts pager if needed automatically): - cht.sh/elixir> :learn + cht.sh/elixir> :learn -## Programming languages questions +## Programming languages questions One of the most important features of cheat.sh is that you can ask it any questions about programming languages and instantly get answers on them. You can use both direct HTTP queries or the cht.sh client for that: - curl cht.sh/python/reverse+list + curl cht.sh/python/reverse+list - cht.sh/python> reverse list + cht.sh/python> reverse list In the latter case you don't need + to separate the words in the query, you can do it in a more natural way, with spaces. @@ -135,46 +135,46 @@ do it in a more natural way, with spaces. If context in the cht.sh shell is not specified, you have to write the programming language name as the first word in the query: - cht.sh> python reverse list + cht.sh> python reverse list But if you are using only one programming language and all queries are about it, it's better to change the current context and -## Comments +## Comments Text in the answers is syntactically formatted as comment in the correspondent programming language When using cht.sh, you can copy the result of the last query into the selection -buffer (you may also call it "clibpoard") using C (or c, with text): +buffer (you may also call it "clibpoard") using C (or c, with text): - cht.sh/python> reverse list - ... - cht.sh/python> C - 1 lines copied + cht.sh/python> reverse list + ... + cht.sh/python> C + 1 lines copied -## bash TAB-completion for cht.sh +## bash TAB-completion for cht.sh -One of the advantages of the cht.sh client comparing to plain curl is that you -can use TAB completion when writing its queries in bash -(other supported shells: zsh and fish). +One of the advantages of the cht.sh client comparing to plain curl is that you +can use TAB completion when writing its queries in bash +(other supported shells: zsh and fish). Install the TAB completion script for that. Assuming you use bash, you have to do: - mkdir -p ~/.bash.d/ - curl https://cht.sh/:bash_completion > ~/.bash.d/cht.sh - echo 'source ~/.bash.d/cht.sh' >> ~/.bashrc - source ~/.bash.d/cht.sh + mkdir -p ~/.bash.d/ + curl https://cht.sh/:bash_completion > ~/.bash.d/cht.sh + echo 'source ~/.bash.d/cht.sh' >> ~/.bashrc + source ~/.bash.d/cht.sh -## Editor +## Editor -You can access cheat.sh directly from editors: Vim and Emacs. +You can access cheat.sh directly from editors: Vim and Emacs. It's a very important feature! You should absolutely like it. -Imagine: +Imagine: instead of switching to your browser, googling, browsing Stack Overflow and eventually copying the code snippets you need and later pasting them into the editor, you can achieve the same instantly and without leaving @@ -183,21 +183,21 @@ the editor at all! Here is how it looks like: 1. In Vim, if you have a question while editing a program, you can just type -your question directly in the buffer and press KK. You will get -the answer to your question in pager. (with KB you'll get the answer -in a separate buffer). +your question directly in the buffer and press KK. You will get +the answer to your question in pager. (with KB you'll get the answer +in a separate buffer). 2. If you like the answer. You can manually paste it from the buffer or -the pager, or if you are lazy you can use KP to paste it under -your question (KR will replace your question). If you want the -answer without the comments, KC replays the last query +the pager, or if you are lazy you can use KP to paste it under +your question (KR will replace your question). If you want the +answer without the comments, KC replays the last query toggling them. -You have to install cheat.sh Vim/Emacs plugins for the editor support. -See /:vim or /:emacs with the detailed installation instructions. +You have to install cheat.sh Vim/Emacs plugins for the editor support. +See /:vim or /:emacs with the detailed installation instructions. -## Feature requests, feedback and contribution +## Feature requests, feedback and contribution If you want to submit a new community driver repository for cheat.sh please open a ticket on the project page on GitHub. @@ -206,11 +206,11 @@ If you want to modify an existing cheat sheet, please check the source of the cheat sheet (it is always displayed in the cheat sheet bottom line). If you want to add a new cheat sheet, add it here: -https://github.com/chubin/cheat.sheets +https://github.com/chubin/cheat.sheets If you want to suggest a new feature for cheat.sh, or if you've found a bug, please open a new issue on github: -https://github.com/chubin/cheat.sh +https://github.com/chubin/cheat.sh If you want to get the major project updates, follow @igor_chubin in Twitter -or this RSS feed: https://twitrss.me/twitter_user_to_rss/?user=igor_chubin +or this RSS feed: https://twitrss.me/twitter_user_to_rss/?user=igor_chubin diff --git a/tests/results/9 b/tests/results/9 index a8eca4f0..0bcd04a6 100644 --- a/tests/results/9 +++ b/tests/results/9 @@ -1,16 +1,16 @@ -# How do I copy a file in Python? -#  -# shutil (http://docs.python.org/3/library/shutil.html) has many methods -# you can use. One of which is: +# How do I copy a file in python? +# +# shutil (http://docs.python.org/2/library/shutil.html) has many methods +# you can use. One of which is: -from shutil import copyfile +from shutil import copyfile -copyfile(src, dst) +copyfile(src, dst) -# Copy the contents of the file named src to a file named dst. The -# destination location must be writable; otherwise, an IOError exception -# will be raised. If dst already exists, it will be replaced. Special -# files such as character or block devices and pipes cannot be copied -# with this function. src and dst are path names given as strings. -#  -# [Swati] [so/q/123198] [cc by-sa 3.0] +# Copy the contents of the file named src to a file named dst. The +# destination location must be writable; otherwise, an IOError exception +# will be raised. If dst already exists, it will be replaced. Special +# files such as character or block devices and pipes cannot be copied +# with this function. src and dst are path names given as strings. +# +# [Swati] [so/q/123198] [cc by-sa 3.0] diff --git a/tests/run-tests.sh b/tests/run-tests.sh index ea76fcfd..a808cbec 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -29,6 +29,7 @@ test_standalone="${CHEATSH_TEST_STANDALONE:-YES}" show_details="${CHEATSH_TEST_SHOW_DETAILS:-YES}" update_tests_results="${CHEATSH_UPDATE_TESTS_RESULTS:-NO}" CHTSH_URL="${CHTSH_URL:-http://localhost:8002}" +CHTSH_QUERY_OPTIONS="${CHTSH_QUERY_OPTIONS:-T}" TMP=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX) TMP2=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX) @@ -74,15 +75,15 @@ while read -r number test_line; do if [ "$test_standalone" = YES ]; then test_line="${test_line//cht.sh /}" - [[ $show_details == YES ]] && echo "${PYTHON} ../lib/standalone.py $test_line" - "${PYTHON}" ../lib/standalone.py "$test_line" > "$TMP" + [[ $show_details == YES ]] && echo "${PYTHON} ../lib/standalone.py $test_line \?$CHTSH_QUERY_OPTIONS" + "${PYTHON}" ../lib/standalone.py "$test_line \?$CHTSH_QUERY_OPTIONS" > "$TMP" elif [[ $test_line = "cht.sh "* ]]; then test_line="${test_line//cht.sh /}" - [[ $show_details == YES ]] && echo "bash $CHTSH_SCRIPT $test_line" - eval "bash $CHTSH_SCRIPT $test_line" > "$TMP" + [[ $show_details == YES ]] && echo "bash $CHTSH_SCRIPT $test_line \?$CHTSH_QUERY_OPTIONS" + eval "bash $CHTSH_SCRIPT $test_line \?$CHTSH_QUERY_OPTIONS" > "$TMP" else - [[ $show_details == YES ]] && echo "curl -s $CHTSH_URL/$test_line" - eval "curl -s $CHTSH_URL/$test_line" > "$TMP" + [[ $show_details == YES ]] && echo "curl -s $CHTSH_URL/$test_line?$CHTSH_QUERY_OPTIONS" + eval "curl -s $CHTSH_URL/$test_line?$CHTSH_QUERY_OPTIONS" > "$TMP" fi if ! diff -u3 results/"$number" "$TMP" > "$TMP2"; then From 1c10780e275afe0c47cc76cf685cf905e712cb81 Mon Sep 17 00:00:00 2001 From: poojankhanpara Date: Sat, 9 Jul 2022 11:25:36 -0700 Subject: [PATCH 2/2] removed the extra space and escaping from standalone test command --- tests/results/9 | 4 ++-- tests/run-tests.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/results/9 b/tests/results/9 index 0bcd04a6..cbe8793c 100644 --- a/tests/results/9 +++ b/tests/results/9 @@ -1,6 +1,6 @@ -# How do I copy a file in python? +# How do I copy a file in Python? # -# shutil (http://docs.python.org/2/library/shutil.html) has many methods +# shutil (http://docs.python.org/3/library/shutil.html) has many methods # you can use. One of which is: from shutil import copyfile diff --git a/tests/run-tests.sh b/tests/run-tests.sh index a808cbec..5934c498 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -75,8 +75,8 @@ while read -r number test_line; do if [ "$test_standalone" = YES ]; then test_line="${test_line//cht.sh /}" - [[ $show_details == YES ]] && echo "${PYTHON} ../lib/standalone.py $test_line \?$CHTSH_QUERY_OPTIONS" - "${PYTHON}" ../lib/standalone.py "$test_line \?$CHTSH_QUERY_OPTIONS" > "$TMP" + [[ $show_details == YES ]] && echo "${PYTHON} ../lib/standalone.py $test_line?$CHTSH_QUERY_OPTIONS" + "${PYTHON}" ../lib/standalone.py "$test_line?$CHTSH_QUERY_OPTIONS" > "$TMP" elif [[ $test_line = "cht.sh "* ]]; then test_line="${test_line//cht.sh /}" [[ $show_details == YES ]] && echo "bash $CHTSH_SCRIPT $test_line \?$CHTSH_QUERY_OPTIONS"