Last active
December 15, 2015 11:17
-
-
Save NIA/943180176c091442e3d6 to your computer and use it in GitHub Desktop.
Scala Koans (Dec 2015)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[info] Koans: (http://scalakoans.webfactional.com) | |
[info] AboutAsserts: | |
[info] - asserts can take a boolean argument | |
[info] - asserts can include a message | |
[info] - true and false values can be compared with should matchers | |
[info] - booleans in asserts can test equality | |
[info] - sometimes we expect you to fill in the values | |
[info] AboutValAndVar: | |
[info] - Vars are variables, and may be reassigned | |
[info] - vals are values, and may not be reassigned, analogous to final in Java | |
[info] - All vals and var types are inferred by default, but you can add the type explicitly | |
[info] - If you want to include a space in your variable or value use backticks | |
[info] - Any strange characters that you wish to use in a variable or value can be used after an underscore | |
[info] - Backticks can also be used to spite your co-workers and send them into a spiral of confusion and agony! | |
[info] - A lazy val is assignment that will not evaluated until it is called. Note there is no lazy var | |
[info] AboutLiteralBooleans: | |
[info] - Boolean literals are either true or false, using the true or false keyword | |
[info] AboutLiteralNumbers: | |
[info] - Integer Literals are 32-bit and can be created from decimal, hexadecimal | |
[info] - Long Literals are 64 bit, are specified by appending an L or l at the end; | |
[info] l is rarely used since it looks like a 1 | |
[info] - Float and Double Literals are IEEE 754 for specific, | |
[info] Float are 32-bit length, Doubles are 64-bit. | |
[info] Floats can be coerced using a f or F suffix, and | |
[info] Doubles can be coerced using a d or D suffix. | |
[info] Exponent are specified using e or E. | |
[info] AboutLiteralStrings: | |
[info] - Character Literals are quoted with single quotes | |
[info] - Character Literals can use hexadecimal Unicode | |
[info] - Character Literals can use octal as well | |
[info] - Character Literals can use escape sequences | |
[info] - One-Line String Literals are surrounded by quotation marks. | |
[info] - String Literals can contain escape sequences. | |
[info] - Multiline String literals | |
[info] are surrounded | |
[info] by three quotation marks | |
[info] - Use stripMargin to prettify multi-line strings | |
[info] AboutMethods: | |
[info] - A method's last statement will be what is returned | |
[info] There is no need for the keyword `return`. | |
[info] When a method includes a `=` after the method declaration that | |
[info] will infer the return type | |
[info] - If you want to include the return type explicitly, | |
[info] no one will stop you | |
[info] - If a method returns two different types and no explicit | |
[info] return type is defined, | |
[info] the type of the method will likely be inferred as the | |
[info] common super parent of the two types being returned | |
[info] - If a method does not of have equal it is considered `Unit` which is analogous to `void` in Java | |
[info] - If you want to have an = on the method, while still explicitly returning Unit you can make the return type `Unit`, | |
[info] this also analogous to `void | |
[info] - Once you have an =, it is understood that there will be a return type and can be inferred | |
[info] - Of course if you wish to be explicit about the return type, you can attach it at the end of the method | |
[info] - When performing recursion, the | |
[info] return type on the method is mandatory! | |
[info] - If you want to ensure a method is not only recursive but _tail recursive_, | |
[info] you can get help from the scala compiler to ensure that it is indeed a | |
[info] tail recursive call by | |
[info] including scala.annotation.tailrec on the method. When methods are properly tail recursive. The | |
[info] Scala compiler will optimize the code from stack recursion into a loop at compile time | |
[info] - In scala, methods can be placed inside in methods! This comes useful for | |
[info] recursion where accumulator helper methods can be placed inside the outer | |
[info] method, or you just want to place one method in another for design reasons | |
[info] - Remember you can have strange characters in values and variables as long as they're | |
[info] after an underscore, well you can do the same in methods | |
[info] - If you also remember you can add reserved words or words with space to any value or variable? | |
[info] Same applies for methods. Although please note that this is uncommon unless you really are into | |
[info] internal DSLs | |
[info] - Convention (not required for the compiler) states that if you a call a method that | |
[info] returns a Unit, invoke that method with empty parenthesis, other leave the parenthesis out | |
[info] - Methods with colons are right-associative, that means the object that a method is on will be on | |
[info] the _right_ and the method parameter will be on the _left_ | |
[info] AboutClasses: | |
[info] - val parameters in class definition define getter | |
[info] - var parameters in class definition define getter and setter | |
[info] - fields defined internally are private to class | |
[info] AboutUniformAccessPrinciple: | |
[info] - Can access age as parameterless method | |
[info] - Can access age as property | |
[info] - Cannot add parameter to Method invocation | |
[info] - What happens when I update current year using property | |
[info] - What happens when I update current year using method | |
[info] AboutConstructors: | |
[info] - Primary constructor specified with a parameter requires that parameter to be passed in | |
[info] - Class with no class parameters is called with no arguments | |
[info] AboutParentClasses: | |
[info] - Class hierarchy is linear, a class can only extend from one parent class | |
[info] - A class that extends from another is polymorphic | |
[info] - An abstract class, as in Java, cannot be instantiated and only inherited | |
[info] - A class can be placed inside an abstract class just like in java | |
[info] AboutOptions: | |
[info] - Option can have one of two values - Some or None | |
[info] - Represent null with None because null is a bad idea | |
[info] - Provide a default value for None | |
[info] - checking whether option has value | |
[info] - Option can also be used with pattern matching | |
[info] AboutObjects: | |
[info] - An object is a singleton. One object -- that's it. This object is a replacement of static in Java, | |
[info] and is called upon much in the same way | |
[info] - Here is proof an object is a singleton, and not a static method in a class | |
[info] - An object that has the same name as class is called a companion object, | |
[info] it is used to contain factories for the class that it complements | |
[info] - A companion object stores shared variables and values for every instantiated class to share. | |
[info] (See SecretAgent class and companion object above). | |
[info] - A companion object can also see private values and variables of the instantiated objects | |
[info] AboutApply: | |
[info] - The apply method is a magical method in Scala, it is a method that doesn't require you | |
[info] to leave out the entire method name! | |
[info] - The apply method can also be used in singleton objects as well, in fact, it is the most common way | |
[info] to create a factory method in an object | |
[info] AboutTuples: | |
[info] - Tuples can be created easily | |
[info] - Tuple items may be accessed individually | |
[info] - Tuples may be of mixed type | |
[info] - Tuples items can be swapped on a Tuple 2 | |
[info] AboutHigherOrderFunctions: | |
[info] - Meet lambda. Anonymous function | |
[info] - An anonymous function can also take on a different look by taking out the brackets | |
[info] - Meet closure. Closure is any function that closes over the environment | |
[info] - We can take that closure and throw into a method and it will still hold the environment | |
[info] - function returning another function | |
[info] - function returning another function using an anonymous function | |
[info] - isInstanceOf is the same as instanceof in java, but in this case the parameter types can be | |
[info] 'blanked out' using existential types with is a single underline, since parameter type are unknown | |
[info] at runtime. | |
[info] - function taking another function as parameter. Helps in composing functions. | |
[info] Hint: a map method applies the function to each element of a list | |
[info] - Currying is a technique to transform function with multiple parameters to function with one parameter | |
[info] - Currying allows you to create specialized version of generalized function | |
[info] AboutEmptyValues: | |
[info] - None equals None | |
[info] - None should be identical to None | |
[info] - None can be converted to a String | |
[info] - An empty list can be represented by another nothing value: Nil | |
[info] - None can be converted to an empty list | |
[info] - None is considered empty | |
[info] - None can be cast Any, AnyRef or AnyVal | |
[info] - None cannot be cast to all types of objects | |
[info] - None can be used with Option instead of null references | |
[info] - Some is the opposite of None for Option types | |
[info] - Option.getOrElse can be used to provide a default in the case of None | |
[info] AboutLists: | |
[info] - Eq tests identity (same object) | |
[info] - == tests equality (same content) | |
[info] - Nil lists are identical, even of different types | |
[info] - Lists are easily created | |
[info] - Lists can be accessed via head and tail | |
[info] - Lists can accessed by position | |
[info] - Lists are immutable | |
[info] - Lists have many useful methods | |
[info] - Functions over lists can use _ as shorthand | |
[info] - Functions over lists can use () instead of {} | |
[info] - Lists can be 'reduced' with a mathematical operation | |
[info] - Foldleft is like reduce, but with an explicit starting value | |
[info] - You can create a list from a range | |
[info] - Lists reuse their tails | |
[info] AboutMaps: | |
[info] - Maps can be created easily | |
[info] - Maps contain distinct pairings | |
[info] - Maps insertion with duplicate key updates previous entry with subsequent value | |
[info] - Map keys may be of mixed type | |
[info] - Mixed type values can be added to a map | |
[info] - Maps may be accessed | |
[info] - Map elements can be removed easily | |
[info] - Accessing a map by key results in an exception if key is not found | |
[info] - Map elements can be removed in multiple | |
[info] - Map elements can be removed with a tuple | |
[info] - Attempted removal of nonexistent elements from a map is handled gracefully | |
[info] - Map equivalency is independent of order | |
[info] AboutSets: | |
[info] - Sets can be created easily | |
[info] - Sets contain distinct values | |
[info] - Sets can be added to easily | |
[info] - Sets may be of mixed type | |
[info] - Sets can be checked for member existence | |
[info] - Set elements can be removed easily | |
[info] - Set elements can be removed in multiple | |
[info] - Set elements can be removed with a tuple | |
[info] - Attempted removal of nonexistent elements from a set is handled gracefully | |
[info] - Sets can be iterated easily | |
[info] - Two sets can be intersected easily | |
[info] - Two sets can be joined as their union easily | |
[info] - A set is either a subset of another set or it isn't | |
[info] - The difference between two sets can be obtained easily | |
[info] - Set equivalency is independent of order | |
[info] AboutFormatting: | |
[info] - String can be placed in format | |
[info] - Character Literals can be an a single character | |
[info] - Character Literals can be an escape sequence, including octal or hexidecimal | |
[info] - Formatting can also include numbers | |
[info] - Formatting can be used for any number of items, like a string and a number | |
[info] AboutStringInterpolation: | |
[info] - String can be placed in not only in a format method call | |
[info] but inside a string if you precede the string with an s | |
[info] you can then refer to any value or variable within scope | |
[info] This is called string interpolation. | |
[info] - String interpolation can include expressions which can | |
[info] include numbers and strings | |
[info] - If your numbers need special formatting, you can use an | |
[info] `f` prefix before the string instead of an `s`. Once an `f` | |
[info] is placed in front of the string you can apply any printf format rule | |
[info] using a % and the format rule after the variable reference. | |
[info] AboutPatternMatching: | |
[info] - Pattern matching returns something | |
[info] - Pattern matching can return complex somethings | |
[info] - Pattern matching can match complex expressions | |
[info] - Pattern matching can wildcard parts of expressions | |
[info] - Pattern matching can substitute parts of expressions | |
[info] - Pattern matching can done on regular expression groups | |
[info] - A backquote can be used to refer to a stable variable in scope to create a case statement. | |
[info] This prevents what is called \'Variable Shadowing\' | |
[info] - A backquote can be used to refer to a method parameter as a stable variable to create a case statement. | |
[info] - To pattern match against a List, the list can be broken out into parts, | |
[info] in this case the head (x) and the tail(xs). Since the case doesn't terminate in Nil, | |
[info] xs is interpreted as the rest of the list | |
[info] - To obtain the second you can expand on the pattern. Where x is the first element, y | |
[info] is the second element, and xs is the rest. | |
[info] - Same koan as above, but we are pattern matching of a list with only one item! | |
[info] - To pattern match against List, you can also establish a pattern match | |
[info] if you know the exact number of elements in a List | |
[info] AboutCaseClasses: | |
[info] - Case classes have an automatic equals method that works | |
[info] - Case classes have an automatic hashcode method that works | |
[info] - Case classes have a convenient way they can be created | |
[info] - Case classes have a convenient toString method defined | |
[info] - Case classes have automatic properties | |
[info] - Case classes can have mutable properties | |
[info] - Safer alternatives exist for altering case classes | |
[info] - Case classes have default and named parameters | |
[info] - Case classes can be disassembled to their constituent parts as a tuple | |
[info] AboutRange: | |
[info] - Range are not inclusive at end of range | |
[info] - Range can specify a step for an increment | |
[info] - Range does not include the last item, even in a step increment | |
[info] - Range can specify to include the last value | |
[info] AboutPartiallyAppliedFunctions: | |
[info] - A partially applied function is a function that you do not apply any or all the | |
[info] arguments, creating another function. This partially applied function | |
[info] doesn't apply any arguments | |
[info] - Partially applied functions can replace any number of arguments | |
[info] AboutPartialFunctions: | |
[info] - A partial function is a trait that when | |
[info] implemented can be used as building blocks to determine | |
[info] a solution. The trait PartialFunction requires that the | |
[info] the method isDefinedAt and apply be implemented. | |
[info] - Case statements are a quick way to create partial functions. When you create a case | |
[info] statement, the apply and isDefinedAt is created for you. | |
[info] - The result of partial functions can have an \'andThen\' function added to the end | |
[info] of the chain | |
[info] - The result of partial functions can have an \'andThen\' function added to the end | |
[info] of the chain used to continue onto another chain of logic | |
[info] AboutImplicits: | |
[info] - Implicits wrap around existing classes to provide extra functionality | |
[info] This is similar to \'monkey patching\' in Ruby, and Meta-Programming in Groovy. | |
[info] Creating a method isOdd for Int, which doesn't exist | |
[info] - Implicits rules can be imported into your scope with an import | |
[info] - Implicits can be used to automatically convert one type to another | |
[info] - Implicits can be used declare a value to be provided as a default as | |
[info] long as an implicit value is set with in the scope. These are | |
[info] called implicit function parameters | |
[info] - Implicit Function Parameters can contain a list of implicits | |
[info] - Default arguments though are preferred to Implicit Function Parameters | |
[info] AboutTraits: | |
[info] - A class uses the extends keyword to mixin a trait if it is the only relationship the class inherits | |
[info] - A class can only 'extend' from one class or trait, any subsequent extension should use the keyword 'with' | |
[info] - Traits are polymorphic. Any type can be referred to by another type if related by extension | |
[info] - Traits can have concrete implementations that can be mixed into concrete classes with it's own state | |
[info] - Traits can also be mixed during instantiation after the fact! | |
[info] This is useful if you only want to mixin per instance and not per class | |
[info] - Traits are stackable and can change the behavior of methods that the traits are stacked upon | |
[info] - Just like other traits, stackable traits can be mixed after the fact | |
[info] - More traits can be stacked one atop another, make sure that all overrides | |
[info] are labelled, abstract override. The order of the mixins are important. | |
[info] Traits on the right take effect first. | |
[info] - Same koans as before except that we swapped the order of the traits | |
[info] - Using three traits to enhance the IntQueue: Doubling, Incrementing, and Filtering! | |
[info] - Traits are instantiated before a the mixed-in class instantiation | |
[info] - Traits are instantiated before a classes instantiation from left to right | |
[info] - Instantiations are tracked internally and will not allow a duplicate instantiation. Note T1 extends T2, and C1 also extends T2, but T2 is only instantiated once. | |
[info] - The diamond of death (http://en.wikipedia.org/wiki/Diamond_problem) is avoided since instantiations are tracked and will not allow multiple instantiations | |
[info] AboutForExpressions: | |
[info] - For loops can be simple | |
[info] - For loops can contain additional logic | |
[info] - For expressions can nest, with later generators varying more rapidly than earlier ones | |
[info] AboutInfixPrefixAndPostfixOperators: | |
[info] - Simple: Infix Operators are available if an object | |
[info] has a method that takes one parameter. | |
[info] - Infix Operators do NOT work if an object | |
[info] has a method that takes two parameters. | |
[info] - Postfix operators work if an object | |
[info] has a method that takes no parameters. | |
[info] - Prefix operators work if an object | |
[info] has a method name that starts with unary_ . | |
[info] - Here we create our own prefix operator for our own class. | |
[info] The only identifiers that can be used as prefix operators | |
[info] are +, -, !, and ~ | |
[info] AboutInfixTypes: | |
[info] - We can make a type infix, meaning that the type can be displayed in complement | |
[info] between two types in order to make a readable delaration | |
[info] - Of course we can make this a bit more elegant by creating an infix operator | |
[info] method to use with our infix type | |
[info] AboutMutableMaps: | |
[info] - Mutable maps can be created easily | |
[info] - Mutable maps can have elements removed | |
[info] - Mutable maps can have tuples of elements removed | |
[info] - Mutable maps can have tuples of elements added | |
[info] - Mutable maps can have Lists of elements added | |
[info] - Mutable maps can have Lists of elements removed | |
[info] - Mutable maps can be cleared | |
[info] AboutMutableSets: | |
[info] - Mutable sets can be created easily | |
[info] - Mutable sets can have elements removed | |
[info] - Mutable sets can have tuples of elements removed | |
[info] - Mutable sets can have tuples of elements added | |
[info] - Mutable sets can have Lists of elements added | |
[info] - Mutable sets can have Lists of elements removed | |
[info] - Mutable sets can be cleared | |
[info] AboutSequencesAndArrays: | |
[info] - A list can be converted to an array | |
[info] - Any sequence can be converted to a list | |
[info] - You can create a sequence from a for comprehension | |
[info] - You can create a sequence from a for comprehension with a condition | |
[info] - You can filter any sequence based on a predicate | |
[info] - You can also filter Arrays in the same way | |
[info] - You can map values in a sequence through a function | |
[info] AboutIterables: | |
[info] - Iterable is a trait that has the ability to return an iterator of itself. | |
[info] Some known iterators are Sets, Lists, Vectors, Stacks, and Streams. Iterator has two | |
[info] important methods: `hasNext`, which answers whether the iterator has another element | |
[info] available. `next` which will return the next element in the iterator. | |
[info] - `grouped` will return an fixed sized Iterable chucks of an Iterable | |
[info] - `sliding` will return an Iterable that shows a sliding window of an Iterable. | |
[info] - `sliding` can take the size of the window as well the size of the step during each | |
[info] iteration | |
[info] - `takeRight` is the opposite of 'take' in Traversable. It retrieves the last elements | |
[info] of an Iterable. | |
[info] - `dropRight` will drop the number of elements from the right. | |
[info] - `zip` will stitch two iterables into an iterable of pairs of corresponding elements | |
[info] from both iterables. e.g. Iterable(x1, x2, x3) zip Iterable(y1, y2, y3) will | |
[info] return ((x1,y1), (x2, y2), (x3, y3)) | |
[info] - if two Iterables aren't the same size, then `zip` will only zip what can only be paired. | |
[info] e.g. Iterable(x1, x2, x3) zip Iterable(y1, y2) will | |
[info] return ((x1,y1), (x2, y2)) | |
[info] - if two Iterables aren't the same size, then `zipAll` can provide fillers for what it couldn't | |
[info] find a complement for. e.g. Iterable(x1, x2, x3) zipAll (Iterable(y1, y2), x, y) will | |
[info] return ((x1,y1), (x2, y2, y)) | |
[info] - `zipWithIndex` will zip an Iterable with it's integer index | |
[info] - `sameElements` will return true if the two iterables have the same number of elements | |
[info] AboutTraversables: | |
[info] - Using Option to avoid if checks for null | |
[info] - Using in for comprehension | |
[info] AboutInteroperability: | |
[info] - You can interop with a java class and it's use of collections by importing | |
[info] scala.collection.JavaConversions and letting scala implicitly convert | |
[info] from a Scala collection type | |
[info] into a Java collection type. See AboutImplicits Koan Suite for more details | |
[info] and see src/test/java for the | |
[info] SomeJavaClass file. This koan | |
[info] converts a scala List of String to java List of raw type. | |
[info] - This koan converts a scala List of Boat (our own class) to java List of unknown <?> type. | |
[info] AboutLazySequences: | |
[info] - Creating a lazy collection form a strict collection | |
[info] - Strict collection always processes its elements but lazy collection does it on demand | |
[info] - Lazy collection sometimes avoid processing errors | |
[info] - Lazy collections could also be infinite | |
[info] - Always remember tail of a lazy collection is never computed unless required | |
[info] AboutPathDependentTypes: | |
[info] - When a class is instantiated inside of another object, it belongs to the object. This is a path | |
[info] dependent type. Once established, it cannot be placed inside of another object | |
[info] AboutRecursion: | |
[info] - Methods can be embedded in other methods, this is particularly useful as helper methods for recursion. | |
[info] Also in Scala, any recursive method must have a return type. | |
[info] - As a precaution, the helpful @tailrec annotation will throw a compile time if a method is not tail recursive, | |
[info] meaning that the last call and only call of the method is the recursive method. Scala optimizes recursive calls | |
[info] to a loop from a stack | |
[info] - As properly tail recursive method will use an accumulator method so that the only call of a recursive method is the last one. | |
[info] just like the first koan above. | |
[info] AboutStructuralTypes: | |
[info] - Structural typing is the ability to allow to the best of Scala's ability, duck typing. | |
[info] Duck Typing is where the method signatures and properties become valid semantics, not inheritence. | |
[info] Duck Typing comes from the term "If it walk like duck, and talks like a duck, ... | |
[info] - Structural typing can also be used to assign values and variables | |
[info] - Use a semicolon (;) to add more methods for the structural type | |
[info] - You can use type aliasing if the structural type gets to be too much typing | |
[info] Passed: Total 355, Failed 0, Errors 0, Passed 355 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment