Skip to content

Instantly share code, notes, and snippets.

@NIA
Last active December 15, 2015 11:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NIA/943180176c091442e3d6 to your computer and use it in GitHub Desktop.
Save NIA/943180176c091442e3d6 to your computer and use it in GitHub Desktop.
Scala Koans (Dec 2015)
[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