Vavr User Guide refers to the following piece of code while discussing its named parameters feature:
Named Parameters
Vavr leverages lambdas to provide named parameters for matched values.
Number plusOne = Match(obj).of(
Case($(instanceOf(Integer.class)), i -> i + 1),
Case($(instanceOf(Double.class)), d -> d + 1),
Case($(), o -> { throw new NumberFormatException(); }) );
Could someone please elaborate on where the named parameters are in play here and how they are used? Thank you in advance.
I think what they mean is, without Vavr, you would have to cast the matched object to the matched type (e.g. in line 2, you would need to cast to Integer).
With Vavr, in the lambda, the parameter is the matched object in the correct type already, you didn't need to cast it.
int withoutVavr(Object obj) {
if (obj instanceof Integer) {
return ((Integer) obj) + 42;
} else if (obj instanceof String) {
return ((String) obj).concat("obj is just an Object until I cast it").length();
}
throw new NumberFormatException();
}
int withVavr(Object obj) {
return Match(obj).of(
Case($(instanceOf(Integer.class)), i -> i + 42),
Case($(instanceOf(String.class)),
blabla -> blabla.concat("blabla is a string, I did not need to cast it; also, I could rename it to blabla thanks to lambdas, without writing the tedious 'String blabla = (String) obj'").length()),
Case($(), o -> {
throw new NumberFormatException();
}));
}
Hope this clarifies/helps.
Related
I'm trying to use Mockito to return some default values in tests but I get a 404 on it
My test:
#Test
fun `Should return 200, when sending a valid push notification`() {
// Arrange
Mockito.`when`(subscriptionStore.getSubscription{ it.peerID == validSubscription.peerID})
.thenReturn(
validSubscription
)
// Act
val response = mockMvc.post("/push") {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(validPushMessage)
}
// Assert
response.andDo { print() }
.andExpect {
status { isOk() }
}
}
and here's the method on the interface I try to mock:
interface SubscriptionStore {
fun addSubscription(newSubscription: Subscription)
fun getSubscriptions(): Collection<Subscription>
fun getSubscription(predicate: (Subscription) -> Boolean): Subscription?
fun deleteSubscription(peerID: String)
fun updateSubscription(subscription: Subscription)
class DuplicateElementException(msg: String) : Exception(msg)
}
and here's the usage of the mocked method that doesn't return what I told it but gives me 404:
override fun push(pushMessage: PushMessage) {
val recipientSubscription = subscribeService.getSubscription(pushMessage.recipient)
?: throw NoSuchElementException("Recipient not found")
}
which calls this from my subscriptionStore
override fun getSubscription(PeerID: String): Subscription? = subscriptionStore.getSubscription { it.peerID == PeerID}
In Kotlin, 2 different lambdas with identical code are not considered equal:
val fun1: (Int) -> Boolean = {it > 5}
val fun2: (Int) -> Boolean = {it > 5}
println(fun1 == fun2) // false
This is why your stubbing fails - you pass different lambda in your test, and a different one in the actual code
To answer the original post: I would probably relax stubbing requirements on the predicate and use the ArgumentMatchers.any argument matcher
On top of that - selection of item by ID is typically exposed by DBs as a separate operation, as it is the fastest way to reach the element. Maybe it is worth adding to your API as well?
Given the following enum defined in an external api.
public enum Status {
COMPLETE,
RUNNING,
WAITING
}
I would like a way to add a int flag to each enum value. I know that I can extend the enum:
fun Status.flag(): Int {
when(this) {
RUNNING -> return 1;
WAITING -> return 2;
else -> return 0;
}
}
However I would like to define those int flag values as constants. Maybe a companion object, but I don't think I can extend an existing enum and add a companion object.
Any ideas?
Unless you are using a field that already exists in the original enum (like ordinal), you won't be able to do what you're asking without wrapping the external enum in your own enum.
Sure you could use ordinal, but a newer version of the external API may change the order of the items in the enum, so I wouldn't recommend it. But, if you REALLY want to, you could do something like this (again, this is NOT recommended):
val Status.flag: Int
get() = this.ordinal
But I'd definitely recommend wrapping it. That way you guarantee that the flag integers you define won't change.
enum class MyStatus(val status: Status, val flag: Int) {
COMPLETE(Status.COMPLETE, 0),
RUNNING(Status.RUNNING, 1),
WAITING(Status.WAITING, 2);
companion object {
private val STATUS_TO_MYSTATUS = values().associateBy { it.status }
fun fromStatus(status: Status): MyStatus {
return STATUS_TO_MYSTATUS[status] ?: throw Exception("No MyStatus found for status ${status.name}")
}
}
}
You can then convert Status to MyStatus by using MyStatus.fromStatus(...). Or you can add an extension function to Status to easily convert to MyStatus.
fun Status.toMyStatus() = MyStatus.fromStatus(this)
You can add extension properties/methods to the companion object of enum/class/etc. if one exists:
val Status.Companion.COMPLETE_INT = 0
val Status.Companion.RUNNING_INT = 1
but indeed you can't currently "create" the companion object if it doesn't. So just put the constants into your own non-companion object:
object StatusFlags {
const val COMPLETE_INT = 0
const val RUNNING_INT = 1
const val WAITING_INT = 2
}
fun Status.flag(): Int {
when(this) {
RUNNING -> return StatusFlags.RUNNING_INT
...
}
}
In my project I have a function like this:
fun doCoolStuff(arg1: Int = 0, arg2: String? = null) {
}
Which I want it to use it in following cases:
obj.doCoolStuff(101) // only first argument provided
obj.doCoolStuff("102") // only second argument provided
obj.doCoolStuff(103, "104") // both arguments provided
But not in this one:
obj.doCoolStuff() // illegal case, should not be able to call the function like this
How do I achieve this on the syntax level?
There is no syntax in Kotlin that would allow you to accomplish what you need. Use overloaded functions (I'd use two, one for each required argument):
fun doCoolStuff(arg1: Int, arg2: String? = null) { ... }
fun doCoolStuff(arg2: String?) { doCoolStuff(defaultIntValue(), arg2) }
This is not possible because you made both arguments optional. You could add a check in the method body or, what I'd prefer, provide proper overloads:
fun doCoolStuff(arg1: Int) {
doCoolStuff(arg1, null)
}
fun doCoolStuff(arg2: String?) {
doCoolStuff(0, arg2)
}
fun doCoolStuff(arg1: Int, arg2: String?) {}
Might be I don't understand but this works for me
fun doCoolStuff() {
throw IllegalArgumentException("Can't do this")
}
Just define the method with no parameters and throw exception.
You can declare doCoolStuff() with zero parameter and mark it as deprecated with DeprecationLevel.ERROR.
fun doCoolStuff(arg1: Int = 0, arg2: String? = null) {}
#Deprecated("Should be called with at least one parameter", level = DeprecationLevel.ERROR)
fun doCoolStuff() {}
Consider the following code:
class Test {
func func1(arg1: Int) -> Void {
println(arg1)
}
var funcArr: Array< (Int) -> Void > = [func1] // (!) 'Int' is not a subtype of 'Test'
}
I'm trying to store the method func1in an array, but as you can see, this doesn't seem to work because func1supposedly only takes an argument of type Test. I assume this has something to do with methods needing to be associated with an object.
For some more clarification, have a look at the following code where I let swift infer the type of the array:
class Test {
func func1(arg1: Int) -> Void {
println(arg1)
}
var funcArr = [func1]
}
Test().funcArr[0](Test()) // Compiles, but nothing gets printed.
Test().funcArr[0](1) // (!) Type 'Test' does not conform to protocol 'IntegerLiteralConvertible'
Test().func1(1) // Prints '1'
A possible workaround for this problem is moving func1outside of the class like so:
func func1(arg1: Int) -> Void {
println(arg1)
}
class Test {
var funcArr = [func1]
}
Test().funcArr[0](1) // Prints '1'
This works fine for this simple example, but is less than ideal when I actually need to operate on an Object of type Test in the function. I can of course add another parameter to the function to pass an instance of Testto the function, but this seems clunky.
Is there any way I can store methods in an array?
Ultimately, what I want to be able to do is testObject.funcArr[someInt](someParam) and have that function work as a method belonging to testObject. Any clever workarounds are of course also welcome.
Instance methods in swift are just curried functions, and the first argument is implicitly an instance of the class (i.e. self). And that's why these two are equivalent:
Test().func1(0)
Test.func1(Test())(0)
So when you try to put that function in the array, you're reveling its real nature: the method func1 on Test is actually this class method:
class func1(self_: Test)(arg1: Int)
So when you refer to simply func1 (without an "instance context") it has type Test -> Int -> Void, instead of the expected Int -> Void, and that's why you get the error
Int is not a subtype of Test
So the real issue is that when you store the methods in funcArr the instance is not known yet (or if you will, you're referring the function at a class level). You can work around this using a computed property:
var funcArr: [Int -> Void] { return [func1] } // use a computed property
Or another valuable option could be simply to acknowledge the real type of func1 and explicitly passing the instance. E.g.
...
var funcArr = [func1]
...
let test = Test()
let func1 = test.funcArr[0]
func1(test)(0) // prints 0
update
Freely inspired by this other Q/A (Make self weak in methods in Swift) I came up with a similar solution that stores the method references.
func weakRef<T: AnyObject, A, B>(weakSelf: T, method: T -> A -> B) -> A -> B {
return { [unowned weakSelf] in { a in method(weakSelf)(a) } }()
}
class Test {
var methodRefs: [Int -> Void] = []
init() {
methodRefs.append(weakRef(self, Test.func1))
}
func func1(arg1: Int) {
println(arg1)
}
}
In order to store a method, you should remember that the method is invoked on a class instance. What's actually stored in the array is a curried function:
(Test) -> (Int) -> Void
The first function takes a class instance and returns another function, the actual (Int) -> Void method, which is then invoked on that instance.
To make it more explicit, the array type is:
var funcArr: [(Test) -> (Int) -> Void] = [Test.func1]
Then you can invoke the method with code like this:
var test = Test()
var method = test.funcArr[0]
method(test)(1)
Suggested reading: Curried Functions
In Swift you can define an enum and give it a property via an associated value, e.g.:
protocol SizeEnum {
var length : Double? { get } // Length should be >= 0 - has to be an Optional for errors
}
enum SizesEnum : SizeEnum {
case Short(length : Double) // 0 <= length <= maxShort
case Long(length : Double) // length > maxShort
private static let maxShort = 1.0
var length : Double? {
get {
switch self {
case let .Short(length):
if length >= 0 && length <= SizesEnum.maxShort { // Need to error check every access
return length
}
case let .Long(length):
if length > SizesEnum.maxShort { // Need to error check every access
return length
}
}
return nil // There was an error
}
}
}
SizesEnum.Short(length: 0.5).length // [Some 0.5]
SizesEnum.Short(length: 2).length // nil
SizesEnum.Long(length: 2).length // [Some 2.0]
SizesEnum.Long(length: -1).length // nil
However this is not ideal because:
The error checking for the length parameter can only be done on access, you cannot intercept the init
The length parameter is surprisingly long winded
An alternative, which seems better to me, is to use a static factory, e.g.:
protocol SizeStruct {
var length : Double { get } // Length should be >= 0 - is *not* an Optional
}
struct SizesStruct : SizeStruct {
static func Short(length : Double) -> SizeStruct? {
if length >= 0 && length <= maxShort { // Check at creation only
return SizesStruct(length)
}
return nil
}
static func Long(length : Double) -> SizeStruct? {
if length > maxShort { // Check at creation only
return SizesStruct(length)
}
return nil
}
let length : Double
private static let maxShort = 1.0
private init(_ length : Double) {
self.length = length
}
}
SizesStruct.Short(0.5)?.length // [Some 0.5]
SizesStruct.Short(2)?.length // nil
SizesStruct.Long(2)?.length // [Some 2.0]
SizesStruct.Long(-1)?.length // nil
Given that the static factory solution is neater, when would I actually use an enum with values? Am I missing something? Is there a killer use case?
In response to drewag
For Optional other languages, e.g. Java and Scala, you use factories, the Java version is described here: http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html the factory is the of method.
In Swift you would do something like:
class Opt { // Note only Some stores the value, not None
//class let None = Opt() - class variables not supported in beta 4!
class Some<T> : Opt {
let value : T
init(_ value : T) {
self.value = value
}
}
private init() {} // Stop any other ways of making an Opt
}
Opt.Some(1).value // 1
This is probably the optimal example for enum since no error checking is required, but even so the factory version is competitive. The Optional example is so straightforward you don't even need a factory, you just create the Somes directly. Note how None doesn't use any storage.
The Barcode example shows how much better the factory technique is; in practice not all collections of 4 Ints are a valid UPCA and not all Strings are a valid QR Code, therefore you need error checking which is painful with enums. Here is the factory version:
class Barcode { // Note seperate storage for each case
class UPCABarcode : Barcode {
let type : Int, l : Int, r : Int, check : Int
private init(type : Int, l : Int, r : Int, check : Int) {
(self.type, self.l, self.r, self.check) = (type, l, r, check)
}
}
class func UPCA(#type : Int, l : Int, r : Int, check : Int) -> UPCABarcode? {
if ok(type: type, l: l, r: r, check: check) {
return UPCABarcode(type: type, l: l, r: r, check: check)
}
return nil
}
class func QRCode(#s : String) -> Barcode? { // Have not expanded this case; use same pattern as UPCA
return Barcode()
}
private init() {} // Prevent any other types of Barcode
class func ok(#type : Int, l : Int, r : Int, check : Int) -> Bool {
return true // In practice has to check supported type, range of L and R, and if check digit is correct
}
}
Barcode.UPCA(type: 0, l: 1, r: 2, check: 3)
If you use the enum version of Barcode then every time you use a Barcode you have to check its validity because there is nothing to stop invalid barcodes. Whereas the factory version does the checking at creation. Note how Barcode has no storage and UPCA has custom storage. I didn't code QRCode because it uses the same design pattern as UPCA.
My impression is that the enum version looks great in tutorials but soon becomes painful in practice because of error handling.
I believe the biggest killer use case is Optional. It is built into the language, but an optional is simply an enum:
enum Optional<T> {
case None
case Some(T)
}
In this case, a member variable like value would not make sense because in the None case, there is literally no value.
Also, right out of the Swift tour:
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
With a struct, there would be a lot of wasted member variables and a confusing interface to model this kind of data.
I don't believe it makes sense to use an associated value for an enum if the same type is used for every case. In that case a member variable is cleaner. The focus of associated values is to more accurately model certain types of data. The most useful cases are ones where different instances of a type can have different data associated with them. This could potentially be done with subclasses but then one would need to downcast to access more specific variables and the declarations would be much more verbose. Enums are a concise way to represent this type of data.
Another example could be web requests:
struct NetRequest {
enum Method {
case GET
case POST(String)
}
var URL: String
var method: Method
}
var getRequest = NetRequest(URL: "http://drewag.me", method: .GET)
var postRequest = NetRequest(URL: "http://drewag.me", method: .POST("{\"username\": \"drewag\"}"))
When I think of "enum" I don't think of "factory" at all. Normally factories are for larger more complex class structures. Enums are supposed to be very small pieces of data with little logic.