Scala - runtime String template - java

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.

Related

How to write this java builder with generics to scala?

I'm trying to write this java code in scala, but I am getting a compile error.
Document<String, String> doc = Document.<String, String>builder().id("newDocId").score(1d).build();
I am trying:
val doc = Document.<String, String>builder().id("newDocId").score(1d).build();
How do I convert this java generic usage?
I also tried Document[String, String] but I get an error sayingDocument is not a value.
Try this:
val doc = Document.builder[String, String]().id("newDocId").score(1d).build()
Scala uses square brackets for generics (and semicolons are optional). Also, the type parameters go to the method, not the object.

is it possible to have a mixed variable in Java like in PHP?

For example in PHP:
<?php
$my_var = 1;
$my_var = [ "1" ]; // no problem
In Java, I tried to make a Class with a mixed argument:
class MyClass {
public String my_var;
}
MyClass c = new MyClass();
c.my_var = "ok";
c.my_var = 1; // error during compilation time
The reason I am asking that is because I am using jersey with json and I try to make a Feedback Class.
One argument in my Feedback class is the data to send back to the front-end in an Ajax manner. Sometimes data is a normal string:
`{ "data" : "hello world" }`
Sometimes it can be an array
`{ "data" : [ "hello", "world" ] }` or `{ "data" : [ { "id": 1 }, { "id": 2 }, ... ] }`
I am a real noobies when it comes to the Java language and libraries. The only solution I can think of now is to override the toString method for the objects involved in the Json encoding but "toString"'ing a List will give me something like that,
`{ "data" : "[ ...]" }` which is incorrect.
you can do this:
Object c = new Object();
c = new String("hi"); //valid
c = new Integer(1); //valid
And then to check what type of variable it is you can use instanceof
You can also make it an array or a list, and if you want to use toString on it generically to print out any object, you can make your own list class with an overridden toString method that prints it nicely, and use that class in your object
using objects with nice toString methods means that you won't have to use instanceof if all you want to do is get a string representation of the object
Java is a statically typed language; and "dynamics" are limited to things such as assigning sub class values to a super class variable, like:
Object o = "a string";
o = new Double(42.0);
So it looks like o can be both, String and Integer. But as said; that is because Object is a super type of both those classes.
This for example:
String s = "meow";
s = 42;
leads to a compiler error. What would work again would be s = Integer.toString(42) for example.
Similarly, you could do:
Object o = new int[5];
because in Java any reference type (including arrays) is a sub class of Object.
And just to be precise: the Java people think this is an advantage. Because it allows more checking at compile time - catching many errors that require you to write/run unit tests in those dynamic languages where a duck can meow like a cat and still be barking dog in the end.
Coming back to your question: from a Java point of view, an array is not the same as a string. And therefore you would not a low such a JSON representation. In other words: I would first try to change the JSON format.
If that is not possible, I would look into customized JSON de/serialization code - in order to have the framework decide which case is given and do the appropriate thing. Just as inspiration, you can have a look how this can be done with gson.
Currently you can't do that in Java yet, so you'd have to make an indirect workaround, but there are plans to implement typeless objects/variables in Java version 10 (currently at 8, almost moved to 9)
Think oops way,
Have an Interface like FeedBackResponse , Have different implementation classes for each of the cases, make them implement FeedBackResponse.
Each class will have different attributes.
Serialize the object using json library.
Ex,
FeedBackResponse response = getResponse("Some Service");
return jsonLib.serialize(response);
Factory
private FeedBackResponse getResponse(String attr){
// based on attr create ur object here.
}

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.

Create a string with the result of an expression and the expression that originated the value. Is it possible?

Like
String r = SomeThing.toExecString("new Object().toString()");
And when executed the value of r would be:
"new Object().toString() = java.lang.Object#c5e3974"
Is this even possible at all? Would it need a bunch of reflection? A built in compiler maybe?
ScriptEngine engine = new ScriptEngineManager().getEngineByName("beanshell");
Object result = engine.eval("new Object().toString();");
System.out.println(result);
You may get close to what you want using BeanShell. I ran the above code with Java 6 with BeanShell 2.0b4 and the JSR 223-based bsh-engine.jar engine on the classpath.
There is a great post here:
Generating Static Proxy Classes - http://www.javaspecialists.eu/archive/Issue180.html
Part one is enough for what you asked, I think
Don't know if you really wanted this. But your problem would be solved with this method:
String toExecString( String code ) {
return String.format(
"\"%s\" = %s#%x",
code,
code.getClass().getName(),
code.hashCode()
);
}

Categories

Resources