How to use combinators with zip iterable - spring-webflux

The zip that accepts iterable is turning my object to Object[] vs the merge. After the zip, I cannot perform other transformation because I lost my object type. Is this the same concept as the stream's reduce combiner? Just wondering how to properly use it. Thanks.
final List<Object[]> list = Flux
.zip(List.of(Mono.just("hello"), Mono.just("world")), objects -> objects)
.collectList().block();
final List<String> strings = Flux
.merge(List.of(Mono.just("hello"), Mono.just("world")))
.collectList().block();

It's an API limitation at present since the generic type of the Iterable's Publisher isn't captured, so that type information isn't available to you in the method. This means you'll unfortunately have to do something unsafe if you want to keep the type information here.
The most trivial change to your current code to get a List<String[]> would be the following:
final List<String[]> list = Flux
.zip(List.of(Mono.just("hello"), Mono.just("world")), objects -> Arrays.stream(objects).toArray(String[]::new))
.collectList().block();
...but of course, you do lose your type safety.
Depending on your use case (generally speaking, if you combinator can combine elements one at a time rather than all in one go), you may also be able to use Flux.zip() in a reducer:
List<Flux<String>> l = new ArrayList<>();
l.add(Flux.just("hello", "me"));
l.add(Flux.just("world", "hungry"));
final List<String> strings = Flux.fromIterable(l)
.reduce((a, b) -> Flux.zip(a, b, (x, y) -> x + ", " + y))
.flatMap(x -> x.collectList())
.block();
It's not equivalent, but may be a type-safe alternative depending on what you need.

Looks like the first argument to the zip function takes a Iterable<? extends Publisher<?>> the question marks mean it can take whatever object.
and its second argument Function<? super Object[],? extends O> is a function that the first argument is "something" that is an object in an array, and the second argument is "something" that extends a concrete type.
So sadly you will be getting a Object[] it's how it is written. You can cast your objects to the correct.
I have never used it before but i played around with it a bit.
final Flux<String> helloWorldString = Flux.zip(List.of(Mono.just("hello"), Mono.just(" "), Mono.just("world")), objects -> {
StringBuilder value = new StringBuilder();
for (var object : objects) {
value.append((String) object);
}
return value.toString();
});
As it is a combinator i think its purpose is to take any objects[] and build a concrete type out if it.

Related

Kotlin Interface method abstraction

I'm exploring the Substitution principal and from what I've understood about the principal is that a sub type of any super type should be passable into a function/class. Using this idea in a new section of code that I'm writing, I wanted to implement a abstract interface for a Filter like so
interface Filter {
fun filter(): Boolean
}
I would then imagine that this creates the contract for all classes that inherit this interface that they must implement the function filter and return a boolean output. Now my interpretation of this is that the input doesn't need to be specified. I would like it that way as I want a filter interface that guarantee the implementation of a filter method with a guarantee of a return type boolean. Does this concept even exists in Kotlin? I would then expect to implement this interface like so
class LocationFilter {
companion object : Filter {
override fun filter(coord1: Coordinate, coord2: Coordinate): Boolean {
TODO("Some business logic here")
}
}
}
But in reality this doesn't work. I could remove remove the filter method from the interface but that just defeats the point of the whole exercise. I have tried using varargs but again that's not resolving the issue as each override must implement varargs which is just not helpful. I know this may seem redundant, but is there a possibility to have the type of abstraction that I'm asking for? Or am I missing a point of an Interface?
Let's think about it a little. The main point of abstraction is that we can use Filter no matter what is the implementation. We don't need to know implementations, we only need to know interfaces. But how could we use Filter if we don't know what data has to be provided to filter? We would need to use LocationFilter directly which also defeats the point of creating an interface.
Your problem isn't really related to Kotlin, but to OOP in general. In most languages it is solved by generics/templates/parameterized types. It means that an interface/class is parameterized by another type. You use it in Kotlin like this:
interface Filter<in T> {
fun filter(value: T): Boolean
}
object LocationFilter : Filter<Coordinate> {
override fun filter(value: Coordinate): Boolean {
TODO()
}
}
fun acquireCoordinateFilter(): Filter<Coordinate> = LocationFilter
fun main() {
val coord: Coordinate = TODO()
val filter: Filter<Coordinate> = acquireCoordinateFilter()
val result = filter.filter(coord)
}
Filter is parameterized, meaning that we can have a filter for filtering strings (type is: Filter<String>), for filtering integers (Filter<Int>) or for filtering coordinates (Filter<Coordinate>). Then we can't use e.g. Filter<String> to filter integers.
Note that the code in main() does not use LocationFilter directly, it only knows how to acquire Filter<Coordinate>, but the specific implementation is abstracted from it.
Also note there is already a very similar interface in Java stdlib. It is called Predicate.
my interpretation of this is that the input doesn't need to be specified.
Where did you get that interpretation from?
You can see that it can't be correct, by looking at how the method would be called.  You should be able to write code that works for any instance of Filter — and that can only happen if the number and type of argument(s) is specified in the interface.  To use your example:
val f: Filter = someMethodReturningAFilterInstance()
val result = f.filter(coord1, coord2)
could only work if all implementations used two Coordinate parameters. If some used one String param, and others used nothing at all, then how would you call it safely?
There are a few workarounds you could use.
If every implementation takes the same number of parameters, then you could make the interface generic, with type parameter(s), e.g.:
interface Filter<T1, T2> {
fun filter(t1: T1, t2: T2): Boolean
}
Then it's up to the implementation to specify which types are needed.  However, the calling code either needs to know the types of the particular implementation, or needs to be generic itself, or the interface needs to provide type bounds with in variance.
Or if you need a variable number of parameters, you could bundle them up into a single object and pass that.  However, you'd probably need an interface for that type, in order to handle the different numbers and types of parameters, and/or make that type a type parameter on Filter — all of which smells pretty bad.
Ultimately, I suspect you need to think about how your interface is going to be used, and in particular how its method is going to be called.  If you're only ever going to call it when the caller knows the implementation type, then there's probably no point trying to specify that method in the interface (and maybe no point having the interface at all).  Or if you'll want to handle Filter instances without knowing their concrete type, then look at how you'll want to make those calls.
The whole this is wrong!
First, OOP is a declarative concept, but in your example the type Filter is just a procedure wrapped in an object. And this is completely wrong.
Why do you need this type Filter? I assume you need to get a collection filtered, so why not create a new object that accepts an existing collection and represents it filtered.
class Filtered<T>(private val origin: Iterable<T>) : Iterable<T> {
override fun iterator(): Iterator<T> {
TODO("Filter the original iterable and return it")
}
}
Then in your code, anywhere you can pass an Iterable and you want it to be filtered, you simply wrap this original iterable (any List, Array or Collection) with the class Filtered like so
acceptCollection(Filtered(listOf(1, 2, 3, 4)))
You can also pass a second argument into the Filtered and call it, for example, predicate, which is a lambda that accepts an element of the iterable and returns Boolean.
class Filtered<T>(private val origin: Iterable<T>, private val predicate: (T) -> Boolean) : Iterable<T> {
override fun iterator(): Iterator<T> {
TODO("Filter the original iterable and return it")
}
}
Then use it like:
val oddOnly = Filtered(
listOf(1, 2, 3, 4),
{ it % 2 == 1 }
)

in kotlin how to put function reference in an array

Having class member function like:
private fun getData1(uuid:String): IData? {
...
}
private fun getData2(uuid:String): IData? {
...
}
private fun getData3(uuid:String): IData? {
...
}
and would like to put in a function reference array:
var funArray = ArrayList<(uuid: String) -> IData?> (
this::getData1,
this::getData2,
this::getData3)
it does not compile:
None of the following functions can be called with the arguments
supplied:
public final fun <E> <init>(): kotlin.collections.ArrayList<(uuid: String) -> IData?> /* = java.util.ArrayList<(uuid: String) -> IData?> */ defined in kotlin.collections.ArrayList ...
if do:
var funArray: ArrayList<(uuid: String) -> IData?> = ArrayList<(uuid: String) -> IData?>(3)
funArray[0] = this::getData1 //<== crash at here
funArray[1] = this::getData2
funArray[2] = this::getData3
crash with exception
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
How to put function reference in an array?
The first attempt fails because ArrayList doesn't have a constructor taking (a variable argument list of) values.
You can get pretty much the same effect by replacing ArrayList with listOf() (or, if you need mutability, mutableListOf()), as that does take a vararg list:
var functions = listOf<(uuid: String) -> IData?>(
this::getData1,
this::getData2,
this::getData3)
That's perhaps the most natural solution.  (However, mutableListOf() is only guaranteed to return a MutableList implementation; it may not be an ArrayList.)
The second attempt fails because it's constructing an empty list.
(The ArrayList constructor it uses takes a parameter called initialCapacity; it ensures that the list could take at least 3 elements without needing to reallocate its arrays, but its initial size is zero.)
Perhaps the confusion is because although you say you ‘would like to put in a function reference array’, you're creating a List, not an Array.
(The ArrayList class is an implementation of the List interface which happens to use an array internally.  This follows the Java convention of naming implementation classes as <Implementation><Interface>.)
If you need to create an actual array, you could use arrayOf() in the first example:
var functions = arrayOf<(uuid: String) -> IData?>(
this::getData1,
this::getData2,
this::getData3)
Lists are probably used more widely than arrays in Kotlin, as they're more flexible.  (You can choose between many different implementations, with different characteristics.  They work better with generics; for example, you can create a List of a generic type.  You can make them immutable.  And of course if they're mutable, they can grow and shrink.)
But arrays have their place too, especially if performance is important, you need to interoperate with code that uses an array, and/or the size is fixed.

sortedBy() selector not sorting List

I have a sortedBy{} statement which intends to sort a List by the length of the String elements:
var animals: List<String> = listOf("tiger", "cat", "dragon", "elephant")
fun strLength(it: String) = it.length
animals.sortedBy { strLength(it) }
animals.forEach {println(it)}
However it only prints the initial order. Any idea why?
You have to assign the output of sortedBy.
animals = animals.sortedBy { strLength(it) }
Because, like many other functions in Kotlin, sortedBy doesn’t mutate the input & honour immutability. So it returns a new collection. So it mitigates side-effects. Kotlin encourages this immutable approach. However, there are mutable counterparts of these collections if required.
sortedBy does not sort the list, instead it returns a new list which has the elements sorted. If you don't want a new list, simply use sortBy.

Is Kotlin "pass-by-value" or "pass-by-reference"?

As I know Java is pass-by-value from this post. I am from Java background I wonder what Kotlin is using for passing values in between. Like in Extensions or Methods etc.
Every time I hear about the "pass-by-value" vs "pass-by-reference" Java debate I always think the same. The answer I give: "Java passes a copy (pass-by-value) of the reference (pass-by-reference)". So everyone is happy. I would say Kotlin does the same as it is JVM based language.
UPDATE
OK, so it's been a while since this answer and I think some clarification should be included. As #robert-liberatore is mentioning in the comments, the behaviour I'm describing is true for objects. Whenever your methods expect any object, you can assume that the JVM internally will make a copy of the reference to the object and pass it to your method. That's why having code like
void doSomething(List<Integer> x) {
x = new ArrayList<Integer>()
}
List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3
behaves like it does. You're copying the reference to the list, so "reassigning it" will take no effect in the real object. But since you're referring to the same object, modifying its inner content will affect the outer object.
This is something you may miss when defining your attributes as final in order to achieve immutability. You won't be able to reassign them, but there's nothing preventing you from changing its content
Of course, this is true for objects where you have a reference. In case of primitives, which are not a reference to an object containing something but "something" themselves, the thing is different. Java will still make a copy of the whole value (as it does with the whole reference) and pass it to the method. But primitives are just values, you can't "modify its inner values". So any change inside a method will not have effect in the outer values
Now, talking about Kotlin
In Kotlin you "don't have" primitive values. But you "do have" primitive classes. Internally, the compiler will try to use JVM primitive values where needed but you can assume that you always work with the boxed version of the JVM primitives. Because of that, when possible the compiler will just make a copy of the primitive value and, in other scenarios, it will copy the reference to the object. Or with code
fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2
fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1
I'd say that Kotlin scenario is a bit safer than Java because it forces its arguments to be final. So you can modify its inner content but not reassign it
fun doSomething(x: MutableList<Int>) {
x.add(2) // this works, you can modify the inner state
x = mutableListOf(1, 2) // this doesn't work, you can't reassign an argument
}
It uses the same principles like Java. It is always pass-by-value, you can imagine that a copy is passed. For primitive types, e.g. Int this is obvious, the value of such an argument will be passed into a function and the outer variable will not be modified. Please note that parameters in Kotlin cannot be reassigned since they act like vals:
fun takeInt(a: Int) {
a = 5
}
This code will not compile because a cannot be reassigned.
For objects it's a bit more difficult but it's also call-by-value. If you call a function with an object, a copy of its reference is passed into that function:
data class SomeObj(var x: Int = 0)
fun takeObject(o: SomeObj) {
o.x = 1
}
fun main(args: Array<String>) {
val obj = SomeObj()
takeObject(obj)
println("obj after call: $obj") // SomeObj(x=1)
}
You can use a reference passed into a function to change the actual object.
The semantics is identical to Java.
In Java, when you have an instance of an object, and you pass it to a method, that method can change the state of that object, and when the method is done, the changes would have been applied to the object at the call site.
The same applies in Kotlin.
For primitives value is passed, and for non-primitives a reference to the object is passed. I'll explain with an example:
The code:
fun main() {
var a = 5
var b = a
a = 6
println("b = $b")
}
prints: b = 5
Kotlin passes the value of a to b, because a is a primitive. So changing a afterwards won't impact b.
The code:
fun main() {
var a = Dog(5)
var b = a
a.value = 6
println("b = ${b.value}")
}
class Dog (var value: Int)
prints b = 6, because this time a is not a primitive and so the reference to the object (Dog) was passed to b and not its value. Therefore changing a would affect all objects that point to it.
In Java primitive types like int, float, double, boolean are passed to a method by value, if you modify them inside the receiver method they doesn't change into the calling method. But if the property/variable type isn't a primitive, like arrays of primitives or other classes when they are changed inside the method that receive them as parameter they also change in the caller method.
But with Kotlin nothing seems to be primitive, so I think all is passed by reference.
This might be a little bit confusing.
The correct answer, IMHO, is that everything passes by reference, but no assignment is possible so it will be similar to passing by value in C++.
Note that function parameters are constant, i.e., they cannot be assigned.
Remember that in Kotlin there are no primitive types. Everything is an object.
When you write:
var x: Int = 3
x += 10
You actually create an object of type Int, assign it the value 3, and get a reference, or pointer, named x.
When you write
x += 10
You reassign a new Int object, with the value 13, to x. The older object becomes a garbage (and garbage-collected).
Of course, the compiler optimizes it, and creates no objects in the heap in this particular case, but conceptually it is as explained.
So what is the meaning of passing by reference function parameters?
Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin.
If the object (passed to the function) has a method which changes its internal state, it will affect the original object.
No such method exists for Int, String, etc. They are immutable objects.
No copy is ever generated when passing objects to functions.
Bear in mind, am quite new to Kotlin. In my opinion, primitives are passed-by-value, but objects are passed-by-reference.
A primitive passed to a class works by default, but if you pass an object from a list, for example, and that object changes, the class object changes too. Because, in fact, it is the same object.
Additionally, if objects gets removed from the list, the class object IS STILL A REFERENCE. So it can still change due to references in other places.
Example below explaines. You can run it here.
fun main() {
val listObjects = mutableListOf(ClassB(), ClassB(), ClassB())
val listPrimitives = mutableListOf(111, 222, 333)
val test = ClassA()
test.ownedObject = listObjects[0]
test.ownedPrimitive = listPrimitives[0]
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listObjects[0].isEnabled = true
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listPrimitives[0] = 999
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
}
class ClassA {
var ownedObject: ClassB = ClassB()
var ownedPrimitive: Int = 0
}
class ClassB {
var isEnabled = false
}
Since Kotlin is a new language for JVM, like Java it is pass-by-value. The confusing part is with object, at first it looks like that it is passed-by-reference but the actuality is that the reference/pointer itself is pass-by-value (a copy of a reference is passed to a method) hence when a method receives a reference to an object, the method can manipulate the original object.

Scala class inheritance

Tagged as homework.
I'm having trouble in the object oriented world while trying to implement a class.
I'm implenting various functions to take action on lists, that I'm using to mock a set.
I'm not too worried about my logic on how to find union, for example, but really just the structure.
For eg:
abstract class parentSet[T] protected () {
def union(other:parentSet[T]):parentSet[T]
}
Now I want a new class extending parentSet:
class childSet[T] private (l: List[T]) extends parentSet[T] {
def this() = this(List())
private val elems = l
val toList = List[T] => new List(l)
def union(other:parentSet[T]):childSet[T] = {
for (i <- this.toList) {
if (other contains i) {}
else {l :: i}
}
return l
}
}
Upon compiling, I receive errors such that type childSet isn't found in def union, nor is type T to keep it parametric. Also, I assume my toList isn't correct as it complains that it isn't a member of the object; to name a few.
Where in my syntax am I wrong?
EDIT
Now I've got that figured out:
def U(other:parentSet[T]):childSet[T] = {
var w = other.toList
for (i <- this.toList) {
if (!(other contains i)) {w = i::w}
}
return new childSet(w)
}
Now, I'm trying to do the same operations with map, and this is what I'm working on/with:
def U(other:parentSet[T]):MapSet[T] = {
var a = Map[T,Unit]
for (i <- this.toList) {
if (!(other contains i)) {a = a + (i->())}
}
return new MapSet(elems + (a->()))
}
I still want to use toList to make it easily traversable, but I'm still getting type errors while messing with maps..
This code has a few problems:
It seems that you are not realizing that List[T] is an immutable type, meaning you cannot change its value once created. So if you have a List[T] and you call the :: method to prepend a value, the function returns a new list and leaves your existing one unchanged. Scala has mutable collections such as ListBuffer which may behave more like you expect. So when you return l, you're actually returning the original list.
Also, you have the order wrong in using ::. It should go i :: l, since :: is a right-binding function (because it ends with a :).
Lastly, in your union method you are doing (other contains i). Maybe it's just the Scala syntax that's confusing you, but this is the same as doing (other.contains(i)) and clearly contains is not a defined method of parentSet. It is a method on the List[T] type, but you're not calling contains on a list.
You tagged this as homework so I'm not going to fix your code, but I think you should
Look at some examples of correct Scala code involving lists, try here for starters
Play around in the Scala REPL and try creating and working with some lists, so you get a feel for how immutable collections work.
To answer your direct question, even though childSet is inheriting parentSet the original method specify parentSet as the return type and not childSet. You can either only use parentSet as the type OR you could specify the return type to be anything that inherits parentSet.