KT-3192 Drop kotlin.nullable package

#KT-3192 Fixed
This commit is contained in:
Maxim Shafirov
2013-02-04 17:29:56 +04:00
parent e1b7126ae3
commit 9f546f938d
6 changed files with 14 additions and 348 deletions
@@ -10,5 +10,4 @@ fun firstFun() {
// RUNTIME: 1
// TIME: 1
// EXIST: toLinkedList@toLinkedList()~for jet.Iterable<T> in kotlin
// EXIST: toLinkedList@toLinkedList()~for T? in kotlin.nullable
// NUMBER: 2
// NUMBER: 1
+8 -7
View File
@@ -1,8 +1,9 @@
package kotlin
import kotlin.nullable.hashCodeOrDefault
import java.io.Serializable
private fun Any?.safeHashCode() : Int = if (this == null) 0 else this.hashCode()
// TODO: make it a data class
public class Pair<out A, out B> (
public val first: A,
@@ -14,8 +15,8 @@ public class Pair<out A, out B> (
override fun toString(): String = "($first, $second)"
override fun hashCode(): Int {
var result = first.hashCodeOrDefault(0)
result = 31 * result + second.hashCodeOrDefault(0)
var result = first.safeHashCode()
result = 31 * result + second.safeHashCode()
return result;
}
@@ -40,9 +41,9 @@ public class Triple<A, B, C> (
override fun toString(): String = "($first, $second, $third)"
override fun hashCode(): Int {
var result = first.hashCodeOrDefault(0)
result = 31 * result + second.hashCodeOrDefault(0)
result = 31 * result + third.hashCodeOrDefault(0)
var result = first.safeHashCode()
result = 31 * result + second.safeHashCode()
result = 31 * result + third.safeHashCode()
return result;
}
@@ -55,4 +56,4 @@ public class Triple<A, B, C> (
second == t.second &&
third == t.third;
}
}
}
@@ -1,184 +0,0 @@
package kotlin.nullable
import java.util.*
/** Returns true if the element is not null and matches the given predicate */
public inline fun <T: Any> T?.any(predicate: (T)-> Boolean): Boolean {
return this != null && predicate(this)
}
/** Returns true if the element is not null and matches the given predicate */
public inline fun <T: Any> T?.all(predicate: (T)-> Boolean): Boolean {
return this != null && predicate(this)
}
/** Returns the 1 if the element is not null else 0 */
public inline fun <T: Any> T?.count(predicate: (T)-> Boolean): Int {
return if (this != null) 1 else 0
}
/** Returns the first item which matches the predicate if this element is not null else null */
public inline fun <T: Any> T?.find(predicate: (T)-> Boolean): T? {
return if (this != null && predicate(this)) this else null
}
/** Returns a new List containing all elements in this collection which match the given predicate */
public inline fun <T: Any> T?.filter(predicate: (T)-> Boolean): T? = find(predicate)
/** Filters all elements in this collection which match the given predicate into the given result collection */
public inline fun <T: Any, C: MutableCollection<in T>> T?.filterTo(result: C, predicate: (T)-> Boolean): C {
if (this != null && predicate(this))
result.add(this)
return result
}
/** Returns a List containing all the non null elements in this collection */
public inline fun <T: Any> T?.filterNotNull(): Collection<T> = filterNotNullTo(java.util.ArrayList<T>())
/** Filters all the null elements in this collection winto the given result collection */
public inline fun <T: Any, C: MutableCollection<in T>> T?.filterNotNullTo(result: C): C {
if (this != null) {
result.add(this)
}
return result
}
/** Returns a new collection containing all elements in this collection which do not match the given predicate */
public inline fun <T: Any> T?.filterNot(predicate: (T)-> Boolean): Collection<T> = filterNotTo(ArrayList<T>(), predicate)
/** Returns a new collection containing all elements in this collection which do not match the given predicate */
public inline fun <T: Any, C: MutableCollection<in T>> T?.filterNotTo(result: C, predicate: (T)-> Boolean): C {
if (this != null && !predicate(this)) {
result.add(this)
}
return result
}
/**
* Returns the result of transforming each item in the collection to a one or more values which
* are concatenated together into a single collection
*/
public inline fun <T: Any, R> T?.flatMap(transform: (T)-> MutableCollection<R>): Collection<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns the result of transforming each item in the collection to a one or more values which
* are concatenated together into a single collection
*/
public inline fun <T: Any, R> T?.flatMapTo(result: MutableCollection<R>, transform: (T)-> MutableCollection<R>): Collection<R> {
if (this != null) {
val coll = transform(this)
for (r in coll) {
result.add(r)
}
}
return result
}
/** Performs the given operation on each element inside the collection */
public inline fun <T: Any> T?.forEach(operation: (element: T) -> Unit) {
if (this != null) {
operation(this)
}
}
/**
* Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values
*
* For example to sum together all numeric values in a collection of numbers it would be
* {code}val total = numbers.fold(0){(a, b) -> a + b}{code}
*/
public inline fun <T: Any> T?.fold(initial: T, operation: (it: T, it2: T) -> T): T {
return if (this != null) {
operation(initial, this)
} else {
initial
}
}
/**
* Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values
*/
public inline fun <T: Any> T?.foldRight(initial: T, operation: (it: T, it2: T) -> T): T {
// maximum size is 1 so reverse is not needed
return fold(initial, {x, y -> operation(y, x)})
}
/**
* Iterates through the collection performing the transformation on each element and using the result
* as the key in a map to group elements by the result
*/
public inline fun <T: Any, K> T?.groupBy(result: MutableMap<K, MutableList<T>> = HashMap<K, MutableList<T>>(), toKey: (T)-> K): Map<K, MutableList<T>> {
if (this != null) {
val key = toKey(this)
val list = result.getOrPut(key){ ArrayList<T>() }
list.add(this)
}
return result
}
/** Creates a String from the nullable or item with the given prefix and postfix if supplied */
public inline fun <T: Any> T?.makeString(separator: String = ", ", prefix: String = "", postfix: String = ""): String {
val buffer = StringBuilder(prefix)
if (this != null) {
buffer.append(this)
}
buffer.append(postfix)
return buffer.toString()
}
/** Returns the nullable result of transforming this with the given transformation function */
public inline fun <T: Any, R> T?.map(transform : (T) -> R) : R? {
return if (this != null) {
transform(this)
} else {
null
}
}
/** Transforms each element of this collection with the given function then adds the results to the given collection */
public inline fun <T: Any, R, C: MutableCollection<in R>> T?.mapTo(result: C, transform : (T) -> R) : C {
if (this != null) {
result.add(transform(this))
}
return result
}
/** Returns itself since it can't be reversed as it can contain at most one item */
public inline fun <T: Any> T?.reverse(): T? {
return this
}
/** Copies the collection into the given collection */
public inline fun <T: Any, C: MutableCollection<T>> T?.toCollection(result: C): C {
if (this != null)
result.add(this)
return result
}
/** Converts the collection into a LinkedList */
public inline fun <T: Any> T?.toLinkedList(): LinkedList<T> = this.toCollection(LinkedList<T>())
/** Converts the collection into a List */
public inline fun <T: Any> T?.toList(): List<T> = this.toCollection(ArrayList<T>())
/** Converts the collection into a Set */
public inline fun <T: Any> T?.toSet(): Set<T> = this.toCollection(HashSet<T>())
/** Converts the collection into a SortedSet */
public inline fun <T: Any> T?.toSortedSet(): SortedSet<T> = this.toCollection(TreeSet<T>())
/**
TODO figure out necessary variance/generics ninja stuff... :)
public inline fun <in T> T?.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List<T> {
val answer = this.toList()
answer.sort(transform)
return answer
}
*/
/** Returns a hash code on an existing object, or default value otherwise */
public inline fun Any?.hashCodeOrDefault(default: Int): Int = if (this == null) default else this.hashCode()
+5 -5
View File
@@ -8,18 +8,18 @@ class PairTest {
val p = Pair(1, "a")
test fun pairFirstAndSecond() {
assertTrue(p.first == 1)
assertTrue(p.second == "a")
assertEquals(1, p.first)
assertEquals("a", p.second)
}
test fun pairMultiAssignment() {
val (a, b) = p
assertTrue(a == 1)
assertTrue(b == "a")
assertEquals(1, a)
assertEquals("a", b)
}
test fun pairToString() {
assertTrue(p.toString() == "(1, a)")
assertEquals("(1, a)", p.toString())
}
test fun pairEquals() {
@@ -1,147 +0,0 @@
package language.scala
import kotlin.nullable.*
import junit.framework.TestCase
import kotlin.test.assertEquals
class Request(val value: String?) {
fun getParameter(name: String): String? {
return value
}
}
/**
* This test case shows how we can use T?, the Kotlin nullable type instead of Option[T] in Scala
*
* Its worth saying that nullable types have 2 huge benefits over Option:
*
* * Already works with any Java or JVM based API which can return nulls
* * No extra object construction to wrap non-null values
*
* Examples taken from the [Scala API docs for Option](http://www.scala-lang.org/api/current/scala/Option.html)
*
* Composition of nullable types is currently implemented with the optional kotlin.nullable package
*/
class OptionTest: TestCase() {
fun testPatternMatching() {
fun foo(request: Request): String {
/* Scala:
val nameMaybe = request.getParameter("name")
nameMaybe match {
case Some(name) => {
name.trim.toUppercase
}
case None => {
"No name value"
}
}
*/
// Kotlin version:
val name = request.getParameter("name")
return when (name) {
is String -> {
name.trim().toUpperCase()
}
else -> {
"No name value"
}
}
}
assertEquals("No name value", foo(Request(null)))
assertEquals("BAR", foo(Request("BAR")))
assertEquals("BAR", foo(Request(" bar ")))
println("foo(null) = ${foo(Request(null))}")
println("foo(\" bar \") = ${foo(Request(" bar "))}")
}
fun testPatternMatchingUsingIf() {
fun foo(request: Request): String {
/* Scala:
val nameMaybe = request.getParameter("name")
nameMaybe match {
case Some(name) => {
name.trim.toUppercase
}
case None => {
"No name value"
}
}
*/
// Kotlin version
val name = request.getParameter("name")
return if (name != null) {
name.trim().toUpperCase()
} else {
"No name value"
}
}
assertEquals("No name value", foo(Request(null)))
assertEquals("BAR", foo(Request("BAR")))
assertEquals("BAR", foo(Request(" bar ")))
println("foo(Request(null)) = ${foo(Request(null))}")
println("foo(Request(\" bar \")) = ${foo(Request(" bar "))}")
}
fun testFunctionComposition() {
fun foo(request: Request): String {
/* Scala:
val name:Option[String] = request.getParameter("name")
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper.getOrElse(""))
*/
val name = request.getParameter("name")
val upper = name.map{ it.trim() }.filter{ it.length != 0 }.map{ it.toUpperCase() }
return upper ?: ""
}
assertEquals("", foo(Request(null)))
assertEquals("", foo(Request(" ")))
assertEquals("BAR", foo(Request(" bar ")))
}
fun testCompositionWithFor() {
fun foo(request: Request): String {
/* Scala:
val upper = for {
name <- request.getParameter("name")
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper.getOrElse(""))
*/
// Kotlin version
// not as clean as we've no way to compose if statements so have
// to cheat and use returns
val name = request.getParameter("name")
if (name != null) {
val trimmed = name.trim()
if (trimmed.length() != 0) {
return trimmed.toUpperCase()
}
}
return ""
}
assertEquals("", foo(Request(null)))
assertEquals("", foo(Request("")))
assertEquals("BAR", foo(Request(" bar ")))
}
}
@@ -1,3 +0,0 @@
This package compares and contrasts some Scala coding patterns with how things work in Kotlin.
Its more intended to help show folks familiar with doing things the Scala way, how the code would look in Kotlin.