Skip to content
This repository was archived by the owner on Aug 17, 2019. It is now read-only.

Commit 937f27d

Browse files
committed
Some API experimentation.
Tests do not pass
1 parent d8fb144 commit 937f27d

File tree

3 files changed

+127
-87
lines changed

3 files changed

+127
-87
lines changed

Diff for: src/main/scala/com/ckkloverdos/maybe/Maybe.scala

+99-67
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2011 Christos KK Loverdos
2+
* Copyright 2011-2012 Christos KK Loverdos
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,59 +33,81 @@ sealed abstract class Maybe[+A] {
3333
def isNoVal: Boolean
3434
def isFailed: Boolean
3535

36-
def getOr[B >: A](b: => B): B
36+
def getOr[B >: A](b: B): B
3737

38-
def ||[B >: A](f: => Maybe[B]): Maybe[B]
38+
def ||[B >: A](f: Maybe[B]): Maybe[B]
3939

40-
def map[B](f: A => B): Maybe[B]
40+
def map[B](f: A B): Maybe[B]
4141

42-
def flatMap[B](f: A => Maybe[B]): Maybe[B]
42+
def flatMap[B](f: A Maybe[B]): Maybe[B]
4343

4444
/**
4545
* Map or return the provided default value.
4646
*/
47-
def defMap[B](default: => B)(f: A => B): B = map(f) getOr default
47+
def defMap[B](default: B)(f: A B): B = map(f) getOr default
4848

4949
/**
5050
* Use this value of type `A` to provide another one of type `B` and then
5151
* do some cleanup on the original value of type `A`.
5252
*
5353
* Use case: Get a DB cursor, perform calculations based on that and then close the cursor.
5454
*/
55-
def finallyMap[B](_finally: A => Unit)(f: A => B): Maybe[B]
55+
def finallyMap[B](_finally: A Unit)(f: A B): Maybe[B]
5656

57-
def finallyFlatMap[B](_finally: A => Unit)(f: A => Maybe[B]): Maybe[B]
57+
def finallyFlatMap[B](_finally: A Unit)(f: A Maybe[B]): Maybe[B]
5858

5959
@inline
60-
final def >>[B](f: A => Maybe[B]): Maybe[B] = this flatMap f
61-
62-
def filter(f: A => Boolean): Maybe[A]
63-
64-
def foreach(f: A => Unit): Unit
65-
66-
def fold[T](onJust: (A) => T)(onNoVal: => T)(onFailed: (Failed) => T): T
67-
60+
final def >>[B](f: A Maybe[B]): Maybe[B] = this flatMap f
61+
62+
def filter(f: A Boolean): Maybe[A]
63+
64+
def foreach(f: A Unit): Unit
65+
66+
def fold[T](onJust: (A) T)(onNoVal: T)(onFailed: (Failed) T): T
67+
68+
// @inline
69+
// final def foldOption[B](onJust: (A) ⇒ B)(onNoVal: ⇒ B): Maybe[B] = this match {
70+
// case Just(a) ⇒
71+
// this.map(onJust)
72+
// case NoVal ⇒
73+
// Maybe(onNoVal)
74+
// case failed @ Failed(_) ⇒
75+
// failed
76+
// }
77+
//
78+
// @inline
79+
// def foldEither[B](onJust: (A) ⇒ B)(onFailed: ⇒ (Failed) => B): Maybe[B] = this match {
80+
// case Just(a) ⇒
81+
// this.map(onJust)
82+
// case NoVal ⇒
83+
// NoVal
84+
// case failed @ Failed(_) ⇒
85+
// Maybe(onFailed(failed))
86+
// }
87+
6888
@inline
69-
final def foldUnit(onJust: => Any)(onNoVal: => Any)(onFailed: => Any): Unit =
70-
fold(a => onJust)(onNoVal)(f => onFailed)
89+
final def foldUnit(onJust: Any)(onNoVal: Any)(onFailed: Any): Unit =
90+
fold(a onJust)(onNoVal)(f onFailed)
7191

7292
@inline
73-
final def foldJust[T](onJust: (A) => T)(onOther: => T): T =
74-
fold(onJust)(onOther)(f => onOther)
93+
final def foldJust[T](onJust: (A) T)(onOther: T): T =
94+
fold(onJust)(onOther)(f onOther)
7595

7696
@inline
77-
final def forJust[B >: A](f: Just[A] => Maybe[B]): Maybe[B] =
97+
final def forJust[B >: A](f: Just[A] Maybe[B]): Maybe[B] =
7898
if(isJust) f(this.asInstanceOf[Just[A]]) else this
7999

80100
@inline
81-
final def forNoVal[B >: A](f: => Maybe[B]): Maybe[B] =
101+
final def forNoVal[B >: A](f: Maybe[B]): Maybe[B] =
82102
if(isNoVal) f else this
83103

84104
@inline
85-
final def forFailed[B >: A](f: Failed => Maybe[B]): Maybe[B] =
105+
final def forFailed[B >: A](f: Failed Maybe[B]): Maybe[B] =
86106
if(isFailed) f(this.asInstanceOf[Failed]) else this
87107

88-
def castTo[B: Manifest]: MaybeOption[B]
108+
def safeCastTo[B: Manifest]: MaybeOption[B]
109+
110+
def castTo[B: Manifest]: Maybe[B]
89111

90112
/**
91113
* Flattens two successive maybes to one.
@@ -99,9 +121,9 @@ sealed abstract class Maybe[+A] {
99121
sealed trait MaybeOption[+A] extends Maybe[A]
100122

101123
object MaybeOption {
102-
def apply[A](x: => A): MaybeOption[A] = Maybe(x) match {
103-
case j@Just(_) => j
104-
case _ => NoVal
124+
def apply[A](x: A): MaybeOption[A] = Maybe(x) match {
125+
case j@Just(_) j
126+
case _ NoVal
105127
}
106128
}
107129

@@ -111,12 +133,12 @@ object MaybeOption {
111133
sealed trait MaybeEither[+A] extends Maybe[A]
112134

113135
object MaybeEither {
114-
def apply[A](x: => A): MaybeEither[A] = Maybe(x) match {
115-
case j@Just(_) =>
136+
def apply[A](x: A): MaybeEither[A] = Maybe(x) match {
137+
case j@Just(_)
116138
j
117-
case f@Failed(_) =>
139+
case f@Failed(_)
118140
f
119-
case NoVal =>
141+
case NoVal
120142
Failed(new Exception("Got NoVal for a MaybeFailed"))
121143
}
122144
}
@@ -131,20 +153,20 @@ object Maybe {
131153
* This is a polymorphic constructor for Maybes.
132154
* Use it if you are not sure what to expect from `x`.
133155
*/
134-
def apply[A](x: => A): Maybe[A] = {
156+
def apply[A](x: A): Maybe[A] = {
135157
try {
136158
val value = x
137159
value match {
138-
case null => NoVal
139-
case _ => Just(value)
160+
case null NoVal
161+
case _ Just(value)
140162
}
141163
} catch {
142-
case e: Throwable => Failed(e)
164+
case e: Throwable Failed(e)
143165
}
144166
}
145167
}
146168

147-
final case class Just[@specialized +A](get: A) extends MaybeOption[A] with MaybeEither[A] {
169+
final case class Just[+A](get: A) extends MaybeOption[A] with MaybeEither[A] {
148170
def toIterator = Iterator(get)
149171
def toTraversable = Traversable(get)
150172
def toOption = Some(get)
@@ -154,31 +176,37 @@ final case class Just[@specialized +A](get: A) extends MaybeOption[A] with Maybe
154176
def isFailed = false
155177
def isNoVal = false
156178

157-
def getOr[B >: A](b: => B) = get
179+
def getOr[B >: A](b: B) = get
158180

159181

160-
def finallyMap[B](_finally: A => Unit)(f: A => B): Maybe[B] = {
182+
def finallyMap[B](_finally: A Unit)(f: A B): Maybe[B] = {
161183
try this.map(f)
162184
finally { safeUnit(_finally(get)) }
163185
}
164186

165-
def finallyFlatMap[B](_finally: A => Unit)(f: A => Maybe[B]): Maybe[B] = {
187+
def finallyFlatMap[B](_finally: A Unit)(f: A Maybe[B]): Maybe[B] = {
166188
try this.flatMap(f)
167189
finally { safeUnit(_finally(get)) }
168190
}
169191

170-
def fold[T](onJust: (A) => T)(onOnVal: => T)(onFailed: (Failed) => T) = onJust(get)
192+
def fold[T](onJust: (A) T)(onOnVal: T)(onFailed: (Failed) T) = onJust(get)
193+
194+
def ||[B >: A](f: Maybe[B]) = this
171195

172-
def ||[B >: A](f: => Maybe[B]) = this
196+
def map[B](f: (A) B)= Maybe(f(get))
197+
def flatMap[B](f: (A) Maybe[B]) = f(get)
198+
def filter(f: (A) Boolean): Maybe[A] = if(f(get)) this else NoVal
199+
def foreach(f: A Unit) = f(get)
173200

174-
def map[B](f: (A) => B)= Maybe(f(get))
175-
def flatMap[B](f: (A) => Maybe[B]) = f(get)
176-
def filter(f: (A) => Boolean): Maybe[A] = if(f(get)) this else NoVal
177-
def foreach(f: A => Unit) = f(get)
201+
def safeCastTo[B: Manifest] = get match {
202+
case null NoVal // normally null should not even be here but we are being cautious
203+
case value if(manifest[B].erasure.isInstance(value)) this.asInstanceOf[MaybeOption[B]] else NoVal
204+
}
178205

179206
def castTo[B: Manifest] = get match {
180-
case null => NoVal // normally null should not even be here but we are being cautious
181-
case value => if(manifest[B].erasure.isInstance(value)) this.asInstanceOf[MaybeOption[B]] else NoVal
207+
case null NoVal
208+
case value if(manifest[B].erasure.isInstance(value)) this.asInstanceOf[Maybe[B]]
209+
case value Failed(new ClassCastException("%s -> %s".format(get.asInstanceOf[AnyRef].getClass.getName, manifest[B])))
182210
}
183211

184212
def flatten1[U](implicit ev: A <:< Maybe[U]): Maybe[U] = ev(get)
@@ -197,22 +225,24 @@ case object NoVal extends MaybeOption[Nothing] {
197225
def isNoVal = true
198226
def isFailed = false
199227

200-
def getOr[B >: Nothing](b: => B) = b
228+
def getOr[B >: Nothing](b: B) = b
201229

202-
def fold[T](onJust: (Nothing) => T)(onNoVal: => T)(onFailed: (Failed)=> T) = onNoVal
230+
def fold[T](onJust: (Nothing) T)(onNoVal: T)(onFailed: (Failed) T) = onNoVal
203231

204-
def ||[B >: Nothing](f: => Maybe[B]) = f
232+
def ||[B >: Nothing](f: Maybe[B]) = f
205233

206-
def map[B](f: (Nothing) => B)= NoVal
207-
def flatMap[B](f: (Nothing) => Maybe[B]) = NoVal
208-
def filter(f: (Nothing) => Boolean) = NoVal
209-
def foreach(f: Nothing => Unit) = {}
234+
def map[B](f: (Nothing) B)= NoVal
235+
def flatMap[B](f: (Nothing) Maybe[B]) = NoVal
236+
def filter(f: (Nothing) Boolean) = NoVal
237+
def foreach(f: Nothing Unit) = {}
210238

211-
def finallyMap[B](_finally: (Nothing) => Unit)(f: (Nothing) => B) = this
239+
def finallyMap[B](_finally: (Nothing) Unit)(f: (Nothing) B) = this
212240

213-
def finallyFlatMap[B](_finally: (Nothing) => Unit)(f: (Nothing) => Maybe[B]) = this
241+
def finallyFlatMap[B](_finally: (Nothing) Unit)(f: (Nothing) Maybe[B]) = this
214242

215-
def castTo[B: Manifest]: MaybeOption[B] = NoVal
243+
def safeCastTo[B: Manifest]: MaybeOption[B] = this
244+
245+
def castTo[B: Manifest] = this
216246

217247
def flatten1[U](implicit ev: <:<[Nothing, Maybe[U]]) = this
218248

@@ -235,22 +265,24 @@ final case class Failed(cause: Throwable) extends MaybeEither[Nothing] {
235265
def toList = Maybe.MaybeEmptyList
236266
def toSet = Maybe.MaybeEmptySet
237267

238-
def getOr[B >: Nothing](b: => B) = b
268+
def getOr[B >: Nothing](b: B) = b
269+
270+
def fold[T](onJust: (Nothing) T)(onNoVal: T)(onFailed: (Failed) T) = onFailed(this)
239271

240-
def fold[T](onJust: (Nothing) => T)(onNoVal: => T)(onFailed: (Failed)=> T) = onFailed(this)
272+
def ||[B >: Nothing](f: Maybe[B]) = f
241273

242-
def ||[B >: Nothing](f: => Maybe[B]) = f
274+
def map[B](f: (Nothing) B) = this
275+
def flatMap[B](f: (Nothing) Maybe[B]) = this
276+
def filter(f: (Nothing) Boolean) = this
277+
def foreach(f: Nothing Unit) = {}
243278

244-
def map[B](f: (Nothing) => B) = this
245-
def flatMap[B](f: (Nothing) => Maybe[B]) = this
246-
def filter(f: (Nothing) => Boolean) = this
247-
def foreach(f: Nothing => Unit) = {}
279+
def finallyMap[B](_finally: (Nothing) Unit)(f: (Nothing) B) = this
248280

249-
def finallyMap[B](_finally: (Nothing) => Unit)(f: (Nothing) => B) = this
281+
def finallyFlatMap[B](_finally: (Nothing) Unit)(f: (Nothing) Maybe[B]) = this
250282

251-
def finallyFlatMap[B](_finally: (Nothing) => Unit)(f: (Nothing) => Maybe[B]) = this
283+
def safeCastTo[B: Manifest]: MaybeOption[B] = NoVal
252284

253-
def castTo[B: Manifest]: MaybeOption[B] = NoVal
285+
def castTo[B: Manifest] = this
254286

255287
def flatten1[U](implicit ev: <:<[Nothing, Maybe[U]]) = this
256288

Diff for: src/main/scala/com/ckkloverdos/package.scala

-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@ package object maybe {
3838
catch { case _ }
3939
}
4040

41-
final class RichMaybe[A](a: => A) {
42-
def maybe: Maybe[A] = Maybe(a)
43-
}
44-
45-
implicit def anyToRichMaybe[A](a: => A): RichMaybe[A] = new RichMaybe[A](a)
46-
4741
implicit def optionToMaybe[T](x: Option[T]): MaybeOption[T] = x match {
4842
case Some(c) => Just(c)
4943
case None => NoVal

Diff for: src/test/scala/com/ckkloverdos/maybe/MaybeTest.scala

+28-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2011 Christos KK Loverdos
2+
* Copyright 2011-2012 Christos KK Loverdos
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.ckkloverdos.maybe
1818

1919
import org.junit.Assert
2020
import org.junit.Test
21-
import java.io.File
2221

2322
/**
2423
*
@@ -95,42 +94,57 @@ class MaybeTest {
9594

9695
@Test
9796
def testCastNullToNoVal: Unit = {
98-
Assert.assertEquals(NoVal, Just(null).castTo[Int])
97+
Assert.assertEquals(NoVal, Just(null).safeCastTo[Int])
9998
}
10099

101100
@Test
102-
def testCastTo: Unit = {
101+
def testSafeCastTo: Unit = {
103102
val help = "Help"
104103
val aJust: Maybe[_] = Just(help)
105-
Assert.assertTrue(aJust.castTo[CharSequence].isJust)
104+
Assert.assertTrue(aJust.safeCastTo[CharSequence].isJust)
106105
}
107106

108107
@Test
109-
def testCastTo2: Unit = {
108+
def testSafeCastTo2: Unit = {
110109
val help = "Help"
111110
val aJust: Maybe[_] = Just(help)
112-
Assert.assertFalse(aJust.castTo[Int].isJust)
111+
Assert.assertFalse(aJust.safeCastTo[Int].isJust)
112+
}
113+
114+
@Test
115+
def testCastTo: Unit = {
116+
println("Just(1).castTo[Int] = %s".format(Just(1).castTo[Int]))
117+
Assert.assertTrue(Just(1).castTo[Int].isJust)
118+
}
119+
120+
@Test
121+
def testCastTo2: Unit = {
122+
println("Just(1).castTo[String] = %s".format(Just(1).castTo[String]))
123+
Assert.assertTrue(Just(1).castTo[String].isFailed)
113124
}
114125

115126
@Test
116127
def testFinallyMap: Unit = {
117-
var _flag = false
128+
var _flag1 = false
129+
var _flag2 = false
118130
class TesterCursor {
119-
var closed = false
120131

121-
def doit() = 1
132+
def doit() = {
133+
_flag1 = true
134+
}
122135

123136
def close() = {
124-
closed = true
125-
_flag = true
137+
_flag2 = true
126138
}
127139
}
128140

129141
class Tester {
130142
def newCursor = new TesterCursor
131143
}
132144

133-
val tester = new Tester
134-
tester.maybe.map(_.newCursor).finallyMap(_.close())(_.doit())
145+
Maybe(new Tester).map(_.newCursor).finallyMap(_.close())(_.doit())
146+
147+
Assert.assertEquals(true, _flag1)
148+
Assert.assertEquals(true, _flag2)
135149
}
136150
}

0 commit comments

Comments
 (0)