Kotlin extension with parameters - java

On an Android project with both Kotlin and java, I want to use the Kotlin functions substringBeforeLast(delimiter) and substringAfterLast(delimiter) in some java files.
So i thought of using extensions. I did the following which works,
fun String.getStringAfterLast(): String{
return this.substringAfterLast(".")
}
however i was thinking of passing the delimiter as a parameter, but it gives me an error when trying to use in java "remove 2nd argument..."
fun String.getStringBeforeLast(delimiter: String): String{
return this.substringBeforeLast(delimiter)
}
Is the approach correct ? Can it be done ?

Your approach to this problem is correct and it should work. For example, with this Kotlin code:
fun String.getStringBeforeLast(delimiter: String): String{
return this.substringBeforeLast(delimiter)
}
You should be able to invoke the function from Java like this:
ExtensionKt.getStringBeforeLast(str, ",");
If it didn't work then I guess there had to be some small mistake, like for example: you added delimiter param to getStringBeforeLast() function, but mistakenely tried to invoke getStringAfterLast() function from Java.
Also, you can always invoke functions of Kotlin stdlib directly from Java. Just note that substringBeforeLast()/substringAfterLast() actually receive one additional, optional parameter and you need to provide it from Java, making the code a little more verbose:
StringsKt.substringBeforeLast(str, ",", str);

Related

Java java.util.function.Consumer when argument needs to be transformed

I would like to create a lambda replacement for this current code:
Map<String,Consumer> executionMap = new HashMap<>();
executionMap.put("operation1", str -> this.getEntity().setBooleanCondition(Boolean.parseBoolean(str))
For cases where I don't need to do transform the argument I have this:
executionMap.put("operation2", this.getEntity()::setAStringValue);
I am annoyed because I can figure out how to make the boolean case as elegant.
Additional example of being annoyed:
executionMap.put("operation3", str -> {
this.getEntity().setAStringValueA(str);
this.getEntity().setAStringValueB(str);
});
For this second case I tried :
executionMap.put("operation3",
this.getEntity()::setAStringValueA.andThen(this.getEntity()::setAStringValueB);
But this got a compilation error.
I feel like the answer(s) are obvious but I am not seeing the path.
Your operation3 is pretty straightforward.
executionMap
.put("operation3", ((Consumer<String>)this.getEntity()::setAStringValueA)
.andThen(this.getEntity()::setAStringValueB));

Scala - runtime String template

I want to do exactly what java's String Template does, but in scala. This library however does not work with case classes:
case class Obj(str:String)
val st = new ST("xx $obj.str$ xx",'$','$')
st.add("obj",Obj("replacement"))
st.render() //returns "xx xx"
ST tries to find property "str" with reflection, but it just does not work with scala.
How can I achieve it without ST?
Try to create your class like this:
case class Obj(#BeanProperty str: String)
Here is the scala doc: http://www.scala-lang.org/api/current/#scala.beans.BeanProperty
Also you can take a look at the project Scalasti which is a interface for StringTemplate: http://software.clapper.org/scalasti/
It's built into the language (in an extendable way). Just
val obj = Obj("replacement")
s"xx ${obj.str} xx"
You can have any Scala expression inside ${...}.
See http://docs.scala-lang.org/overviews/core/string-interpolation.html (or just search for "Scala string interpolation") for more.

Call Scala generic method from Java

How can I call the following Scala method from Java?
def mult[A,B: ClassTag,C: ClassTag](rdd1:RDD[A], rdd2:RDD[B])(implicit multiplier: Multiplier[A,B,C]): RDD[C] =
rdd1.zip(rdd2).map(p => multiplier.multiply(p._1, p._2))
Is it possible? Eclipse isn't giving me any help from its autocomplete.
Ugh. Must you? The B and C ClassTags are added to the list of implicit parameters (before the explicit ones), so you can add appropriate ones generated with the scala.reflect.ClassTag object. But it's going to be ugly.
Something like (untested):
mult(rdd1, rdd2, scala.reflect.ClassTag.apply(B.class), scala.reflect.ClassTag.apply(C.class), myMult);

Play framework: is there a way to avoid strange form helper syntax?

I am trying to build a form with Play Framework 2, the usual syntax is:
#helper.form(action = routes.Application.submit, 'id -> "myForm") {
}
Note that the single quotation mark is before id is opened and never closed.
Is there another syntax that I can use to do the same thing?
The 'id is a Symbol.
You could use the Symbol("sym") syntax if you don't like this one, but it is not standard.
scala> 'symbol == Symbol("symbol")
res0: Boolean = true
You could work around it with an implicit conversion. This will require using a scala source file, though (seems like you're using java, but you can mix them).
app/libs/SymbolImplicits.scala
package example.libs
object SymbolImplicits {
implicit def string2Symbol[A](s: (String, A)): (Symbol, A) = (Symbol(s._1), s._2)
}
Then in your view you would #import example.libs.SymbolImplicits._, so you can then do:
#helper.form(action = routes.Application.submit, "id" -> "myForm") {
}
"id" -> "myForm" is then implicitly converted to 'id -> "myForm".
To avoid using that import in every view, you could also add this line to build.sbt (or in Build.scala project properties) instead:
TwirlKeys.templateImports += "example.libs.SymbolImplicits._"
No, that's required syntax for Scala's Symbol as pointed in other answer, anyway except that it looks weird for it's perfectly valid and there's no reason to fight with it.

Java Play 2 - Function as a parameter in scala

I have problems to write reusable code in scala.
If i have something like
#helper.form(action = routes.Guides.addComment(category,title)) {
Is there a way to replace it with a variable?
pseudo code
#(func : Function)
#helper.form(action = func) {
Edit:
Oh.... now it's kinda obvious. The function itself should return a string , so I guess i can just say something like this
#(func :String)
..
.
return ok (form.render(routes.Guides.test()))
Testing it now
May I suggest an alternative? Use Call directly.
#(route: Call)
#helper.form(action = route) {
...
}
In Scala, you could even pass only a part of the route and fill the rest from the controller (very useful when you're using pagination).
figured it out.
with
routes.Guides.test().url
you get the url and then you can use it as a parameter
for example
#guidesComment((routes.Guides.addComment(ug.category,ug.title)).url)
guidesComment looks like this
#(func: String)
Then use it like this
<form action="#func" method="POST">

Categories

Resources