builder syntax for collections in Kotlin - collections

I'm booting up on Kotlin and looking to configure an Array of Labels in the pattern of a builder syntax. I came up with the Kotlin standard library function (apply) combined with a helper function on collections (forEach). Is it correct to refer to this as builder pattern? What that means to me is that the declaration, assignment and the configuration are done in one line/step. I appreciate any thoughts about how to write this in a still more compact and clear "Kotlin-ish" way, or is this the preferred Kotlin syntax more or less. BTW, there are a lot of ways to get this wrong (use let instead of apply does not return the receiver).
val labels = arrayOf(Label("A"),Label("B"),Label("C"),Label("D")).apply {
this.forEach { it.prefWidth = 50.0 }
}

What I'd suggest is avoiding repeating the word Label in your idiom:
val labels = arrayOf("A", "B", "C", "D")
.map { Label(it).apply { prefWidth = 50.0 } }
.toTypedArray()
This creates a bit more transient objects, but it reduces the noise and makes it easier to see the thing that varies between your labels.

Instead of the explicit forEach, you can use a map with an inner apply, which was already correctly chosen in the original post:
arrayOf(Label("A"), Label("B"), Label("C"), Label("D"))
.map { it.apply { prefWidth = 50.0 } }
Using apply in these cases is perfectly valid and even defined as an idiom here (Builder-style usage of methods that return Unit).
The shown code looks more readable to me although it creates a copy of the array inside map. In memory/performance critical situations, you might not want to pay this price and go with your already suggested solution instead.
As an other alternative, which might be useful if such actions are often needed in your code base, a simple extension function will help:
inline fun <T> Array<T>.applyEach(action: T.() -> Unit) = apply { forEach { it.action() } }
//usage
val labels = arrayOf(Label("A"), Label("B"), Label("C"), Label("D")).applyEach { prefWidth = 50.0 }

Functions inside Standard.kt are indeed confusing, but you're using apply() correctly: it's best applied when initializing a variable. You can totally refer to this as the Builder pattern, since it provides a clean solution for constructing an instance of a class.

Related

Writing a Kotlin util function which provides self-reference in initializer

I'm trying to generalize my hack from an answer to another question.
It should provide a way to reference a value which is not constructed yet inside its initializer (of course, not directly, but in lambdas and object expressions).
What I have at the moment:
class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
}
fun <T> selfReference(initializer: SelfReference<T>.() -> T): T {
return SelfReference(initializer).self
}
It works, see this example:
class Holder(var x: Int = 0,
val action: () -> Unit)
val h: Holder = selfReference { Holder(0) { self.x++ } }
h.action()
h.action()
println(h.x) //2
But at this point the way in which initializer references the constructed value is self property.
And my question is: is there a way to rewrite SelfReference so that initializer is passed an argument (or a receiver) instead of using self property? This question can be reformulated to: is there a way to pass a lazily evaluated receiver/argument to a function or achieve this semantics some way?
What are the other ways to improve the code?
UPD: One possible way is to pass a function that returns self, thus it would be used as it() inside the initializer. Still looking for other ones.
The best I have managed to produce while still being completely generic is this:
class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
operator fun invoke(): T = self
}
Adding the invoke operator lets you use it in the following way:
val h: Holder = selfReference { Holder(0) { this().x++ } }
This is the closest I got to make it look like something you would "normally" write.
Sadly I think it is not possible to get completely rid of a explicit access to the element. Since to do that you would need a lambda parameter of type T.() -> T but then you wouldn't be able to call that parameter without an instance of Tand being T a generic there is no clean and safe way to acquire this instance.
But maybe I'm wrong and this helps you think of a solution to the problem
is there a way to rewrite SelfReference so that initializer is passed an argument (or a receiver) instead of using self property? This question can be reformulated to: is there a way to pass a lazily evaluated receiver/argument to a function or achieve this semantics some way?
I'm not sure I completely understand your use case but this may be what you're looking for:
fun initHolder(x: Int = 0, holderAction: Holder.() -> Unit) : Holder {
var h: Holder? = null
h = Holder(x) { h!!.holderAction() }
return h
}
val h: Holder = initHolder(0) { x++ }
h.action()
h.action()
println(h.x) // 2
This works because holderAction is a lambda with a receiver (Holder.() -> Unit) giving the lambda access to the receiver's members.
This is a general solution since you may not be able to change the signature of the respective Holder constructor. It may be worth noting this solution does not require the class to be open, otherwise a similar approach could be done with a subclass using a secondary constructor.
I prefer this solution to creating a SelfReference class when there are only a few number of classes that need the change.
You may want to check for null instead of using !! in order to throw a helpful error. If Holder calls action in it's constructor or init block, you'll get a null pointer exception.
I'm pretty sure you can achieve the same results in a more readable and clear way using something like this:
fun <T> selfReferenced(initializer: () -> T) = initializer.invoke()
operator fun<T> T.getValue(any: Any?, property: KProperty<*>) = this
and later use
val valueName: ValueType by selfReferenced{
//here you can create and use the valueName object
}
Using as example your quoted question https://stackoverflow.com/a/35050722/2196460 you can do this:
val textToSpeech:TextToSpeech by selfReferenced {
TextToSpeech(
App.instance,
TextToSpeech.OnInitListener { status ->
if (status == TextToSpeech.SUCCESS) {
textToSpeech.setLanguage(Locale.UK)
}
})
}
Inside the selfReferenced block you can use the outer object with no restrictions. The only thing you should take care of, is declaring the type explicitly to avoid recursive type checking issues.

Java: Using .stream to transform ArrayList<MyObj> to TreeMap<String, ArrayList<MyObj>>

This is a Java 8 lower-intermediate question:
I have the following code in Java 6:
List <ViewWrapperContentElementTypeProperty> vwPropertyList = getFromDao();
TreeMap <Long, ArrayList<ViewWrapperContentElementTypeProperty>> mappedProperties = new TreeMap<Long, ArrayList<ViewWrapperContentElementTypeProperty>> ();
for (ViewWrapperContentElementTypeProperty vwCetP:vwPropertyList)
{
if(null==mappedProperties.get(vwCetP.getContentElementTypeId()))
{
ArrayList<ViewWrapperContentElementTypeProperty> list = new ArrayList<ViewWrapperContentElementTypeProperty>());
list.add(vwCetP);
mappedProperties.put(vwCetP.getContentElementTypeId(), list);
}
else
{
mappedProperties.get(vwCetP.getContentElementTypeId()).add(vwCetP);
}
}
Can I use vwPropertyList.stream().map() to implement this more efficiently?
It seems like you are looking for a grouping by operation. Fortunately, the Collectors class provide a way to do this:
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toCollection;
...
TreeMap<Long, ArrayList<ViewWrapperContentElementTypeProperty>> mappedProperties =
vwPropertyList.stream()
.collect(groupingBy(ViewWrapperContentElementTypeProperty::getContentElementTypeId,
TreeMap::new,
toCollection(ArrayList::new)));
I used the overloaded version of groupingBy where you can provide a specific map implementation (if you really need a TreeMap).
Also the toList() collector returns a List (which is an ArrayList but it's an implementation details). Since you apparently need to specify a concrete implementation as you want ArrayLists as values, you can do it with toCollection(ArrayList::new).
With regard to using Streams and lambda expressions, of course... This should look like the following:
Map<Long, List<ViewWrapperContentElementTypeProperty>> mappedProperties =
vwPropertyList.stream()
.collect(Collectors.groupingBy(ViewWrapperContentElementTypeProperty::getContentElementTypeId));
Please note that using Stream API methods like above forces using interfaces (Map, List), which is a good practice anyway.
When it comes to performance, it should be roughly the same as using a traditional loop.

Collection intermediate operations library in Java7

I Like the idea of intermediate operations of Java8, Where all operations will applied once when a terminal operation is reached.
I am asking is there library that I can use with Java 7 that allow me to achieve such behaviour.
Note:
I am using commons-collections4 for collection operations, like forAllDo, So it is possible to use it for such case? (intermediate vs terminal operations)
Guava
As your [Guava] tag suggests, most Guava collection operations are lazy - they are applied only once needed. For example:
List<String> strings = Lists.newArrayList("1", "2", "3");
List<Integer> integers = Lists.transform(strings, new Function<String, Integer>() {
#Override
public Integer apply(String input) {
System.out.println(input);
return Integer.valueOf(input);
}
});
This code seems to convert a List<String> to a List<Integer> while also writing the strings to the output. But if you actually run it, it doesn't do anything. Let's add some more code:
for (Integer i : integers) {
// nothing to do
}
Now it writes the inputs out!
That's because the Lists.transform() method doesn't actually do the transforming, but returns a specially crafted class which only computes the values when they are needed.
Bonus proof that it all works nicely: If we removed the empty loop and replaced it with e.g. just integers.get(1);, it would actually only output the number 2.
If you'd like to chain multiple methods together, there is always FluentIterable. That basically allows you to code in the Java 8 Stream-like style.
Goldman Sachs Collections
While Guava usually does the right thing by default and works with JDK classes, sometimes you need something more complex. That's where Goldman Sachs collections come in. GS collections give you far more flexibility and power by having a complete drop-in collections framework with everything you might dream of. Laziness is not theer by default, but can be easily achieved:
FastList<String> strings = FastList.newListWith("1", "2", "3");
LazyIterable<Integer> integers = strings.asLazy().collect(new Function<String, Integer>() {
#Override
public Integer valueOf(String string) {
System.out.println(string);
return Integer.valueOf(string);
}
});
Again, doesn't do anything. But:
for (Integer i : integers) {
// nothing to do
}
suddenly outputs everything.

Using Recursive References in Go

I want to contain all my commands in a map and map from the command to a function doing the job (just a standard dispatch table). I started with the following code:
package main
import "fmt"
func hello() {
fmt.Print("Hello World!")
}
func list() {
for key, _ := range whatever {
fmt.Print(key)
}
}
var whatever = map[string](func()) {
"hello": hello,
"list": list,
}
However, it fails to compile because there is a recursive reference between the function and the structure. Trying to forward-declare the function fails with an error about re-definition when it is defined, and the map is at top-level. How do you define structures like this and initialize them on top level without having to use an init() function.
I see no good explanation in the language definition.
The forward-reference that exists is for "external" functions and it does not compile when I try to forward-declare the function.
I find no way to forward-declare the variable either.
Update: I'm looking for a solution that do not require you to populate the variable explicitly when you start the program nor in an init() function. Not sure if that is possible at all, but it works in all comparable languages I know of.
Update 2: FigmentEngine suggested an approach that I gave as answer below. It can handle recursive types and also allow static initialization of the map of all commands.
As you might already have found, the Go specifications states (my emphasis):
if the initializer of A depends on B, A will be set after B. Dependency analysis does not depend on the actual values of the items being initialized, only on their appearance in the source. A depends on B if the value of A contains a mention of B, contains a value whose initializer mentions B, or mentions a function that mentions B, recursively. It is an error if such dependencies form a cycle.
So, no, it is not possible to do what you are trying to do. Issue 1817 mentions this problem, and Russ Cox does say that the approach in Go might occasionally be over-restrictive. But it is clear and well defined, and workarounds are available.
So, the way to go around it is still by using init(). Sorry.
Based on the suggestion by FigmentEngine above, it is actually possible to create a statically initialized array of commands. You have, however, to pre-declare a type that you pass to the functions. I give the re-written example below, since it is likely to be useful to others.
Let's call the new type Context. It can contain a circular reference as below.
type Context struct {
commands map[string]func(Context)
}
Once that is done, it is possible to declare the array on top level like this:
var context = Context {
commands: map[string]func(Context) {
"hello": hello,
"list": list,
},
}
Note that it is perfectly OK to refer to functions defined later in the file, so we can now introduce the functions:
func hello(ctx Context) {
fmt.Print("Hello World!")
}
func list(ctx Context) {
for key, _ := range ctx.commands {
fmt.Print(key)
}
}
With that done, we can create a main function that will call each of the functions in the declared context:
func main() {
for key, fn := range context.commands {
fmt.Printf("Calling %q\n", key)
fn(context)
}
}
Just populate the map inside a function before using list(). Like that.
Sry I did not see that you wrote "without init()": that is not possible.

Flex How To Call A Function With A Variable Number Of Parameters?

Let's Say I Have This Class:
package{
import flash.display.Sprite;
public class Main extends Sprite{
public function Main(){
trace(getAverage(1,2,3));
trace(getAverage(1,2,3,4));
trace(getAverage(1,2,3,4,5));
}
public function getAverage (...numbers) {
var total = 0;
for (var i = 0; i < numbers.length; i++) {
total += numbers [i];
}
return total / numbers.length;
}
}
}
How do I accomplish the "opposite" of this? Namely, how could I now CALL 'getAverage' with a dynamic number of paraemters?
For instance, if I wanted to do something LIKE:
var r:int=Math.random()*6;
var a:Array=new Array();
for (i:int=0;i<r;i++) {
a[i]=Math.random()*22;
}
// Now I have 'r' Number Of Parameters Stored In 'a'
// How Do I Call getAverage, with all the values in 'a'??
// getAverage(a) isn't right, is it?
// I'm looking for something similar to getAverage(a[0],a[1],a[...]);
var av:Number=getAverage(???);
What I want to know, is if I have a function that takes a variable number of arguments, that's great, but how can I CALL IT with a variable number of arguments, when that number isn't known at runtime? Possibly it's impossible... I'm just not sure, since 'callLater' seems to be able to take an array and generate a dynamic number of parameters from it somehow...
NOTE: Answers consisting solely of "Why Do You Want To Do This?", will be downvoted.
P.S. This IS NOT about calculating Averages! I REALIZE There Are Way Simpler Ways Of Doing All Of This! (I could just write getAverage to accept a single array as its only parameter) The Above is just an EXAMPLE to Illustrate my Question. HOW TO PASS A DYNAMIC NUMBER OF PARAMETERS TO A FUNCTION?
Is this what you're looking for?
var av:Number = getAverage.apply(null, a);
Dave is correct. You can use the apply method of a function to pass in an Array of arguments.
Here is a better explanation of how it works and what the arguments of apply are:
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/Function.html
Also note that you can use the call method to do the same thing but using ...args (comma-delimited list) instead, but apply would be more suitable to your situation.
The problem with your question is that the arguments object is already an Array and using (...args) already provides you with a dynamic way to pass any number of arguments you require. Sorry about the previous answer, wasn't thinking straight...
You can create an array or an object with those parameters and pass that object to that function. That's just normal.
Flash has a rather strong introspection capabilities. So, instead of passing a number of objects, you just pass a single dynamic object with any number of attributes you need:
var ob:Object={arg1:"value1", arg2:8};
var arg:String="arg4";
ob["arg3"]=8;
ob[arg]=18;
trace (ob.hasOwnProperty("arg1"));
trace (ob.arg3);
trace (ob.arg4);
That should cover just about any use case you might need. The downside is that this allows for some rather clever and hard to trace bugs. :-)

Resources