Object interaction through object-specific method - swift

I am trying to produce a function that involves a unique initiating object, a target object and a path object, in which the initiating and target objects are of the same class A, and the path object is of a different class B. The ideal output of this specific function should be input A1, A2 to B1; however, the result is input , to B1:
import UIKit
var interA = ""
var interB = ""
class A {
//Where any unique unit in A must interact with any other unique unit in A through a unique path B.
var name = "name"
}
class B {
var path = "path"
}
func action(user: A, medium: B, target: A) {
interA = user.name
interB = target.name
print(medium.path)
}
var A1 = A()
A1.name = "A1"
var A2 = A()
A2.name = "A2"
var B1 = B()
B1.path = "input \(interA), \(interB) to B1" //String simplification of multivariate function f(AI, AJ)
action(user: A1, medium: B1, target: A2) //Should show up as "input A1, A2 to B1"
Any solutions to the problem or more simplified methods of approach are appreciated. (Future inputs to this function should ideally include all the possible permutations of AI, AJ and BK for positive integers I, J and K.)

You are setting the path variable before action has a chance to update the user/target values. The replacement of the "\()" values happens once when the string is evaluated, not dynamically.

Related

How can I assign previously declared variables based on pattern matching?

Say I have some code of the sort:
var (nodes, d, p) = someFunction()
Then I have a few more instructions and I need to refresh the values of nodes, d and p. My current code is something like
val aux = someFunction(); nodes = aux._1; d = aux._2; p = aux._3
Which is obviously unnecessarily ugly. Ideally I'd want to do something like
(nodes, d, p) = someFunction()
Where the variables have been already declared before, but Scala doesn't allow me.
Any ideas on how to "solve" this?
You can write a helper function in the local context that takes the tuple that is returned from someFunction() and mutate needed variables.
Like this:
def someEnclosingFunctionOrCodeBlock = {
var nodes, d, p;
def mutateVars(tuple: (TypeNodes, TypeD, TypeP)): Unit = {
nodes = tuple._1
d = tuple._2
p = tuple._3
}
mutateVars(someFunction())
// ..
mutateVars(someFunction())
}
Additionally, you can fold it into 1 function that is something like callSomeFunctionAndMutateVars().
You can do it 2 ways - using the previous helper function
def callSomeFunctionAndMutateVars() = mutateVars(someFunction())
Or changing the previous helper function to
def callSomeFunctionAndMutateVars(): Unit = {
val tuple = someFunction()
nodes = tuple._1
d = tuple._2
p = tuple._3
}
PS: Honestly, you should consider changing it to immutable structures and an explicit composition of evaluations.

Scala Add elements to set only by checking specific fields of a case class

I have a case class
case class ApiCall(a: String, b: String, c: String, d: String, e: String, f: String)
I also have a mutable Set: private var apiCalls: mutable.Set[ApiCall] = mutable.Set[ApiCall]()
The problem is, I may get the following ApiCall elements:
ApiCall(a1, b1, c1, d1, e1, f1)
ApiCall(a1, b1, c1, d2, e2, f2)
I have to add elements to the set only if a unique combination of (a, b, c) of the case class ApiCall doesn't already exist. I cannot modify the case class itself because it is being used in multiple places.
Is it possible to add case class elements to the set only by looking at certain fields, and not all?
You might want to use Map instead of Set in your case:
val apiCalls = mutable.Map[(String, String, String), ApiCall]()
Also values are replaced for matching keys inside Map, you might need a separate method to update the API calls map:
def updateApiCalls(call: ApiCall): Unit = {
apiCalls.getOrElseUpdate((call.a, call.b, call.c), call)
()
}
I kind of solved it using a small workaround:
private var _apiCalls: mutable.Set[ApiCall] = mutable.Set[ApiCall]() is my Set of ApiCalls
I wrote a function which will add to set only if there's no 3 part key (a, b, c) already existing in the Set:
def addApiCall(e: X): Unit = {
val m = _x.find(m => m.a == e.a && m.b == e.b && m.c == e.c)
if (m.isEmpty)
_x += e
}
I'm not going to have too many elements in the Set either, so I found this approach easier to handle for me..

print string whenever variable get changed with scala macro

If I have defined a variable b val b:B. Is it possible to print the value of b each time b is assigned to a new value. Like the code below:
case class B(name:String) {
}
var b = B("123")
b = B("xxx")
println(s"b is changed to $b")
b = B("xxJJx")
println(s"b is changed to $b")
I hope the code println(s"b is changed to $b") be hidden in some sort of macro when I create B or b, like:
var b = macro_wrap(B("123"))
With plain var, you cannot do it.
The closest you can get is to create a getter-setter pair which will look like a var from outside:
object Stuff {
private var b0 = B("123")
def b: B = b0
def b_=(newb: B): Unit = {
b0 = newb
println(s"b is changed to $newb")
}
}
Then:
Stuff.b = B("xxx")
Will print the new value.
Note that the setter is a method named b_= which is treated somewhat specially by Scala compiler - an assignment Stuff.b = B("xxx") is automatically translated into Stuff.b_=(B("xxx")). This works only if setter is accompanied by a getter.

scala constructor-local variables again

I am porting my java code to scala, and have a constructor that does quite some stuff:
open hibernate session to load data
do loading (now the session is kept open! I need lazy loading further on)
perform some operations on loaded data and put in containers
tie containers with their consumers
..blah blah
close session
The constructor produces quite a number (~20) of object members, that are final (val in scala). Their creation is not independent, also note that session. Obviously I don't want the session and other temporary stuff to become constructed instance members. How do I do that in scala?
Similar questions have been already asked before:
Constructor-local variables in Scala
Scala local variable inside primary constructor
Answers given in previous topics suggest either returning a tuple of ~20 fields from initialization method, or creating a private constructor that takes those ~20 values as parameters from companion object apply method. Either seems pig ugly to me.
So far the most sensible approach seems to declare those fields as vars, not vals, and reassign them in some initialization method, which also kinda smells.
I have a technically correct solution, but it might not be what you wanted, because it introduces a lot of verbocity
trait Example {
val a1 : Int
val a2 : Int
val a3 : Int
val a4 : Int
val a5 : Int
val a6 : Int
}
object Example {
def apply(seed : Int) : Example = {
val x1 = seed + 1
val x2 = x1 * 2
val x3 = x2 / 3
val x4 = x3 + x1
val x5 = x4 * x2
val x6 = x5 - x4
new Example {
override val a1 = x1
override val a2 = x2
override val a3 = x3
override val a4 = x4
override val a5 = x5
override val a6 = x6
}
}
}
So there is no constructor neither initializing method that takes many of variables, but they are passed via trait extending
Another (complex) way would be something like this:
import Person.getParams
class Person private (t: (Int, String, String)) {
val a = t._1
val b = t._2
val c = t._3
def this(filename: String) {
this(getParams(filename))
}
}
object Person {
def getParams(filename: String): (Int, String, String) {
// do some logic with filename which results in the relevant tuple
// return the tuple
}
}
Of course this is limited to 22 parameters so if you need more you would need an actual class...

initialise a var in scala

I have a class where I like to initialize my var by reading a configfile, which produces intermediate objects/vals, which I would like to group and hide in a method.
Here is the bare minimum of the problem - I call the ctor with a param i, in reality a File to parse, and the init-method generates the String s, in reality more complicated than here, with a lot of intermediate objects being created:
class Foo (val i: Int) {
var s : String;
def init () {
s = "" + i
}
init ()
}
This will produce the error: class Foo needs to be abstract, since variable s is not defined. In this example it is easy to solve by setting the String to "": var s = "";, but in reality the object is more complex than String, without an apropriate Null-implementation.
I know, I can use an Option, which works for more complicated things than String too:
var s : Option [String] = None
def init () {
s = Some ("" + i)
}
or I can dispense with my methodcall. Using an Option will force me to write Some over and over again, without much benefit, since there is no need for a None else than to initialize it that way I thought I could.
Is there another way to achieve my goal?
var s : Whatever = _ will initialize s to the default value for Whatever (null for reference types, 0 for numbers, false for bools etc.)
Instead of creating separate methods for initialization, you should perform the initialization using the following way :
class Foo(val i: Int) {
var s: String = {
var s0 = " "
s0 += i
// do some more stuff with s0
s0
}
var dashedDate = {
val dashed = new SimpleDateFormat("yy-MM-dd")
dashed.format(updated)
}
// Initializing more than one field:
var (x, y, z) = {
var x0, y0, z0 = 0
// some calculations
(x0, y0, z0)
}
}
Honestly, why are you using var? Why not just do:
val rootObject = readFile(filename)
This would make the most sense to me.