I would like to make the following work:
def foo(x:Int = 1) = {
object obj {
val x = foo.this.x
}
}
But I don't know how to reference x from within the object. Can this be done without renaming x in one of the two spots?
Renaming the variables may not be easy when, for example, foo is a widely used API function with x as a named variable, while obj extends a 3rd party trait that has x as an abstract member.
No, this is not possible. There is no way to identify the outer block of the function definition.
For your syntax to work foo would have to be an object with a member x. i.e. this works:
class foo{
val x = 1
object obj {
val x = foo.this.x
}
}
foo also could be a singleton object extending FunctionX, which gives you something very similar to a method. But it is probably easier to just rename one of the values.
It is not possible in Scala.
You write the code, so the easiest option will be to rename one of the xs and problem solved.
However, if from some reason you really need it - you can do a trick and create an object that will behave like your method
object Foo {
self =>
val x = 1
def apply() = {
object obj {
val x1 = self.x
val x2 = Foo.x
// x1 == x2, just 2 different ways of doing this
}
}
}
Because the apply method is implemented you can use it as you would use a function Foo()
Why not just introduce a new variable that has the same value as foo's argument x, but is not shadowed?
def foo(x: Int): Unit = {
val foo_x = x
object obj {
val x = 13
def doStuff: Unit = printf("%d %d\n", x, foo_x);
}
obj.doStuff
}
foo(42)
Related
I don´t know why it doesn´t work..
I cant use if or when functions in class or in the "playerPosition" function..
class Player(val name:String, val nachname: String, val nr:Int) {
var position = mutableListOf<Int>(0,1,2,3)
var playerPosi = Int
fun playerPosition(){
if(playerPosi < 3 ){
}
}
}
And the next question is, how can I use a function from a class in the main func.?
Maybe like this
class Player(val name:String, val nachname: String, val nr:Int, var playerPosi : Int) {
var position = mutableListOf<Int>(0,1,2,3)
fun playerPosition(){
if(playerPosi > 3 ){
println("Diese Position gibt es nicht")
}
}
}
MAIN FUNCTION
fun main(){
val team2 = mutableListOf<Player>()
team2.add(Player("Berkan", "Kutlu", 10,4))
val spieler = Player("Wesley","Sneijder",10,4)
playerPosition()
println("${team2.first().playerPosi}")
}
notice
Im trying to set the max Int from playerPosi to 3. Because of Offense, Middfield and Defense and Keeper
If Ive the numbers from 0 to 3 I will try to identify 0 as Keeper 1 as Defense and so on.
Thanks for you patience with me :D
First question
The problem here is not the if keyword, it's because the property playerPosi is wrong.
Instead of writing :
var playerPosi = Int
you need to write :
var playerPosi: Int
Why ?
In kotlin, you have two way to declare a variable / property :
var : mutable variable / property, you can change it's value
val : read-only variable (check Tenfour04 response)
After the var / val keyword you give it a name
And after that you have three choices :
Directly give a value and kotlin will infer the type
var playerPosi = 1
Give it a type and initialize it latter
var playerPosi: Int
Give it a type and initialize it
var playerPosi: Int = 1
Second Question
If you want to call a method of an object (here it's Player), you need to :
Instantiate it
Get the reference
Call the method from the reference
So, if we take your sample :
val team2 = mutableListOf<Player>()
team2.add(Player("Berkan", "Kutlu", 10,4))
val spieler = Player("Wesley","Sneijder",10,4) // Instantiate + take the reference on spieler variable.
speiler.playerPosition() // here you call the playerPosition method with the speiler variable
println("${team2.first().playerPosi}")
Try changing from var playerPosi = Int to var playerPosi: Int, with : instead of =. If you want to define the data type, you should use :; = is used to assign value.
To use the function on object you have previously created, you should first specify the object you want the function to be called into, then a dot, and then the function's name. Like this:
fun main(){
val spieler = Player("Wesley","Sneijder",10,4)
spieler.playerPosition()
}
In the first case: var playerPosi = Int is wrong syntax. Declaration should be var playerPosi: Int.
In the second case: if player is object of class Player, the you can do player.playerPosi.
main() function seems to be written for variant #2, where playerPosi is also constructor parameter.
There is normal extension function
fun <T> List<T>.test() { }
fun String.test(){ }
and i can declare a variable with extension function type
val obj1 = fun String.(){ }
but can not declare a variable with generic extension function type
val obj2 = fun <T> List<T>.() {} //error
P.S. I don't want to use List<Any>, it is different from generic.
Can someone tell me how to solve it? Thanks!!
Extension functions are kind of a red herring. Values can't have polymorphic types at all, not just in Kotlin, but in Java, Scala, etc.
Depending on why you want it, one approach would be a generic function returning an extension function:
fun <T> obj2Generic() = fun List<T>.() {}
val obj2ForInt = obj2Generic<Int>()
val obj2ForString = obj2Generic<String>()
You cannot do it, same as you cannot assign regular (non-extension) generic function to a variable or instantiate a generic class without specifying the type parameter. Try to put yourself in the compiler's shoes: what would be the type of such variable? It would be generic as well, so it is only possible in another generic context.
fun <T> List<T>.test(){ }
val v1 = List::test // No
val v2 = List<String>::test // OK
fun <T> other() {
val v3 = List<T>::test // OK
val v4 = fun List<T>.() { } // OK
}
I want to assign a member function of a class instance as a first class function to a variable:
class A(val id:Int){ def f(u:Int)=id+u }
val a= new A(0)
val h=a.f // fails: interpreted as a.f(with missing parameter u)
val h1 = (u:Int)=>a.f(u) // OK and does what we want
We can get the desired effect by assigning an appropriate anonymous function.
Is this the only way?
I searched but could find no reference at all.
Use a placeholder to indicate it is partially applied:
scala> class A(val id:Int){ def f(u:Int)=id+u }
defined class A
scala> val a = new A(0)
a: A = A#46a7a4cc
scala> val h = a.f _
h: Int => Int = <function1>
scala> h(2)
res0: Int = 2
EDIT
Trying the code out in the REPL prints
scala> val h = a.f
<console>:9: error: missing arguments for method f in class A;
follow this method with `_' if you want to treat it as a partially applied function
val h = a.f
^
I am using shapeless 2.1.0 -scala 2.11, jdk 1.7: I have a trait
trait Input[T]{
def location:String
}
object location extends Poly1 {
implicit def caseInput[T] = at[Input[T]](l => l.location)
}
val list = new Input[String] {def location:String="/tmp"} :: HNil
list.map(location)
This returns correctly in my console
shapeless2.::[String,shapeless2.HNil] = /tmp :: HNil
However when I have the exact same logic in a function -where the HList is returned to me from another function call and I map function on it I get a compile time error
:could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[location.type,shapeless.::[Input[String]{...},shapeless.HNil]]
I suspect I am probably missing some implicits. I have checked the shapeless tests and documentation -hopefully I didn't miss anything too obvious.
I can create a complete example to recreate the issue if it's not something obvious -thanks for reading.
Best,
Amit
Updated: With an example
trait Input[T]{
def location:String
def value:T
}
trait location extends Poly1 {
implicit def caseList[T] = at[Input[T]](l => l.location)
}
object testfun extends location {
implicit val atString = at[Input[String]](_.location)
implicit val atInt = at[Input[Int]](_.location)
implicit val atLong = at[Input[Long]](_.location)
}
def inputs:HList={
val str = new Input[String]{
override def location: String = "/tmp/string"
override def value: String = "here it is"
}
val ints = new Input[Int]{
override def location: String = "/tmp/1"
override def value: Int = 1
}
val longs = new Input[Long]{
override def location: String = "/tmp/1l"
override def value: Long = 1l
}
str::ints::longs::HNil
}
>>>println(inputs.map(testfun))
could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[HListTest.testfun.type,shapeless.HList]
If I were to remove the return type of the def inputs, I don't get any errors.
It turned out that the gist that I have posted works fine -it was an issue with Intellij
gist.github.com/kumaramit01/80ca29b46d2c07e55b0b
Intellij kept on indicating syntax error when I had return type defined as
Input[String] :: Input[Int] :: Input[Long] :: HNil
Amit
How can i deserialize json array using lift-json to scala vector?
For example:
case class Foo(bar: Vector[Bar])
trait Bar {
def value: Int
}
case class Bar1(value: Int) extends Bar
case class Bar2(value: Int) extends Bar
import net.liftweb.json.{ShortTypeHints, Serialization, DefaultFormats}
implicit val formats = new DefaultFormats {
override val typeHintFieldName = "type"
override val typeHints = ShortTypeHints(List(classOf[Foo],classOf[Bar1],classOf[Bar2]))
}
println(Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1)))))
The result is:
{
"type":"Foo",
"bar":[{
"type":"Bar1",
"value":1
},{
"type":"Bar2",
"value":5
},{
"type":"Bar1",
"value":1
}]
}
Good. But when i try to deserialize this string
println(Serialization.read[Foo](Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1))))))
i get an exception:
net.liftweb.json.MappingException: Parsed JSON values do not match
with class constructor args=List(Bar1(1), Bar2(5), Bar1(1)) arg
types=scala.collection.immutable.$colon$colon constructor=public
test.Foo(scala.collection.immutable.Vector)
It's means that json array associated with scala list, not vector type that defined in class Foo. I know that there is way to create custom serializer by extending net.liftweb.json.Serializer and include it to formats value. But how can i restore type of objects that stores in Vector. I wanna get result of deserializing like this:
Foo(Vector(Bar1(1), Bar2(5), Bar1(1)))
I've often been annoyed by the List-centricness of Lift, and have found myself needing to do similar things in the past. The following is the approach I've used, adapted a bit for your example:
trait Bar { def value: Int }
case class Bar1(value: Int) extends Bar
case class Bar2(value: Int) extends Bar
case class Foo(bar: Vector[Bar])
import net.liftweb.json._
implicit val formats = new DefaultFormats { outer =>
override val typeHintFieldName = "type"
override val typeHints =
ShortTypeHints(classOf[Bar1] :: classOf[Bar2] :: Nil) +
new ShortTypeHints(classOf[Foo] :: Nil) {
val FooName = this.hintFor(classOf[Foo])
override def deserialize = {
case (FooName, foo) => foo \ "bar" match {
case JArray(bars) => Foo(
bars.map(_.extract[Bar](outer, manifest[Bar]))(collection.breakOut)
)
case _ => throw new RuntimeException("Not really a Foo.")
}
}
}
}
Kind of ugly, and could probably be cleaned up a bit, but it works.
You could add an implicit conversion:
implicit def listToVect(list:List[Bar]):Vector[Bar] = list.map(identity)(breakOut)
after that, Serialization.read[Foo] works as expected.