I am creating a population of agents using around 40 mapped parameters. These parameters are just used in the initialisation of the population. However, the problem is that when creating a new agent these many parameters will be required in the arguments without an actual need for them. Just to give you an idea how ugly it looks like.
add_households(int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, boolean)
Therefore, I was wondering if there is a way to remove/hide these parameters after no longer needed. It would be great to be looking like this :
add_households(int, boolean)
If not possible, the other solutions that I will be looking for are:
Maybe there is something similar to parameters mapping for variables. (as variables will not show as arguments.
Moving the whole population after being initialised to a new Agent class with the wanted parameters only. (The main thing here is to keep the created connections with other agent classes)
I appreciate any other suggestions for this problem.
Thank you in advance;
A Possible Solution
Amy's suggestion is elegant in my opinion. However, it did not work exactly as suggested. When typing: objHousehold.initRuntimeParamters( set_age(5), set_p_HH_willing_to_change(true));
It throws an error stating:
The method set_age(int) is undefined for the type Main.
The method set_p_HH_willing_to_change(boolen) is undefined for the type Main.
However, with a littel change I managed to access the wanted parameters only by typing:
Household objHousehold = add_households();
households(objHousehold.getIndex()).set_age(5);
households(objHousehold.getIndex()).set_p_HH_willing_to_change(true);
You could always do add_households(), which would take the default parameters. You could then call a function to set only the 2 you are interested in.
Household objHousehold = add_households();
objHousehold.initRuntimeParamters( int, boolean );
within initRuntimeParameters, use set_parameterName( value ) to set the parameter value.
Related
Let's say I have a case class X(id: Int, name: String, age: Int) and some function (in my case, withUniqueGeneratedKeys in doobie) that returns X. If I have already defined X I am good.
But in my case the core data structure is something like:
case class XData(name: String, age: Int)
case class MaterializedX(id: Int, element: XData)
And of course I could write a line like case class X(id: Int, name: String, age: Int) to create X but it would be duplication of logic - whenever something about XData changes, I'd have to change the code for X as well. Intuitively, it feels like there should be a way to derive X from XData and MaterializedX. This transformation might mean some code, but it would save me lots of future work because I have many item types beyond X.
How could this be done? Happy to hear other approaches.
I am using Scala 3.1.2 in case this matters. Thank you!
Edit: Changed title per helpful comment, to make this question easier to understand.
I think you should be more clear about the question, I mean what title says is almost completely different from your question description (and what you might be actually looking for). Anyway, in my assumptions, what you need is probably a custom Read[MaterializedX] and Write[MaterializedX], as follows:
implicit val pointMaterializedX: Read[MaterializedX] =
Read[(Int, String, Int)]
.map {
case (id, name, age) => MaterializedX(id, XData(name, age))
}
implicit val pointWrite: Write[MaterializedX] =
Write[(Int, String, Int)]
.contramap { materializedX =>
(materializedX.id, materializedX.element.name, materializedX.element.age)
}
More documentations here
This works out of the box with doobie. Nested case classes get flattened into one row. The following code compiles without defining any custom decoders.
case class XData(name: String, age: Int)
case class MaterializedX(id: Int, element: XData)
implicitly[doobie.Read[MaterializedX]]
implicitly[doobie.Write[MaterializedX]]
For instance when I go to tab complete after file.c for matching .cpp, I get things like the following. I have built with -g -ggdb -03
fileName.calloc fileName.calloc#got.plt
fileName.calloc#plt fileName.ceil
fileName.ceil#got.plt fileName.ceil#plt
fileName.clock_gettime fileName.clock_gettime#got.plt
fileName.clock_gettime#plt fileName.close
fileName.close#got.plt fileName.close#plt
fileName.coeff_ab(double*, double*, double, double, double, double, double)
fileName.coerceAngle0to2PI(double*) fileName.coerceAngle0to2PI(float*)
...
I'm using certain external library that has a method which is overloaded several times with different arguments, something like:
insertInto(index: Int, int: Int)
insertInto(index: Int, lng: Long)
insertInto(index: Int, dbl: Double)
insertInto(index: Int, str: String)
And a certain case class I'm using whose data I want to pass onto said methods, say:
case class C(str: String, lng: Long, dbl: Double, int: Int /* more values */)
val c = C("asd", 1, 1.1, 1)
Right now I'm using the library method like:
insertInto(1, c.int)
insertInto(2, c.lng)
insertInto(3, c.dbl)
insertInto(4, c.str)
//more insertions...
But since I'm always using the index of the value in the case classes I figured that maybe I could could save up on some lines of code (around 10) with something like the following:
c.productIterator.zipWithIndex.toList.foreach {
case (idx, value) => insertInto(idx, value)
}
But this doesn't work because I'd be iterating a List[Any] and therefore the compiler complains that I'm not passing the correct argument type to insertInto since Any is not String, Int, Long, Double, etc..
What would be the correct way of handling this? Thanks in advance
case class A[T](t:T)(implicit tag: ClassManifest[T]){
val newTag = tag
override def toString= t+" "+tag.toString
}
case class C(xs:List[Any])
val c=C(List(A("a"),A[Long](1), A[Double](1.1), A[Int](1)))
c.xs.foreach(println)
Try this. I am using Scala 2.9.3. In newer versions, you can use TypeTag and ClassTag. Check here
So now you have the class type information. You can devise some mechanism to map class type value as string to .class instance and then use asinstanceof to cast it.
I would like a function to consume tuple of 7 but compiler won't let me with the shown message. I failed to find a proper way how to do it. Is it even possible without explicitely typing all the type parameters like Tuple7[String,String...,String] and is it even a good idea to use Scala like this ?
def store(record:Tuple7): Unit = {
}
Error:(25, 20) class Tuple7 takes type parameters
def store(record: Tuple7): Unit = {
^
As stated by Luis you have to define what Type goes on which position for every position in the Tuple.
I`d like to add some approaches to express the same behaviour in different ways:
Tuple Syntax
For that you have two choices, what syntax to use to do so:
Tuple3[String, Int, Double]
(String, Int, Double)
Approach using Case Classes for better readability
Long tuples are hard to handle, especially when types are repeated. Scala offers a different approach for handling this. Instead of a Tuple7 you can use a case class with seven fields. The gain in this approach would be that you now can attach speaking names to each field and also the typing of each position makes more sense if a name is attached to it.
And the chance of putting values in wrong positions is reduced
(String, Int, String, Int)
// vs
case class(name: String, age: Int, taxNumber: String, numberOfChildren: Int)
using Seq with pattern matching
If your intention was to have a sequence of data seq in combination with pattern matching could also be a nice fit:
List("name", 24, "", 5 ) match {
case name:String :: age:Int ::_ :: _ :: Nil => doSomething(name, age)
}
This only works nice in a quite reduced scope. Normally you would lose a lot of type information as the List is of type Any.
You could do the following :
def store(record: (String, String, String, String, String, String, String)):Unit = {
}
which is the equivalent of :
def store(record: Tuple7[String, String, String, String, String, String, String]):Unit = {
}
You can read more about it in Programming in Scala, 2nd Edition, chapter "Next Steps in Scala", sub-chapter "Step 9. use Tuples".
This code works fine:
In the controller:
Ok(views.html.payment(message,test,x_card_num,x_exp_date,exp_year,exp_month,x_card_code,x_first_name,x_last_name,x_address,x_city,x_state,x_zip,save_account,product_array,x_amount,products_json,auth_net_customer_profile_id,auth_net_payment_profile_id,customer_id))
In the view:
#(message: String, test: String, x_card_num: String, x_exp_date: String,exp_year: String, exp_month: String, x_card_code: String, x_first_name: String, x_last_name: String, x_address: String, x_city: String, x_state: String, x_zip: String, save_account: String, product_array: Map[String,Map[String,Any]], x_amount: String, products_json: String, auth_net_customer_profile_id: String,auth_net_payment_profile_id: String,customer_id: String)
But when I try to add one more variable to the controller and view like this:
Ok(views.html.payment(message,test,x_card_num,x_exp_date,exp_year,exp_month,x_card_code,x_first_name,x_last_name,x_address,x_city,x_state,x_zip,save_account,product_array,x_amount,products_json,auth_net_customer_profile_id,auth_net_payment_profile_id,customer_id,saved_payments_xml))
#(message: String, test: String, x_card_num: String, x_exp_date: String,exp_year: String, exp_month: String, x_card_code: String, x_first_name: String, x_last_name: String, x_address: String, x_city: String, x_state: String, x_zip: String, save_account: String, product_array: Map[String,Map[String,Any]], x_amount: String, products_json: String, auth_net_customer_profile_id: String,auth_net_payment_profile_id: String,customer_id: String, saved_payments_xml: String)
It gives me this error:
missing parameter type
What am I doing wrong?
There's a limit to the number of parameters you can pass to a template. You've exceeded it when you add another parameter.
It's an undocumented and fairly arbitrary limit which is the result of how the code generation from a template works. It is arguably a bug, but not one that I would fix since nobody needs this many parameters, and having this many makes code much less readable.
Your best resolution here is to refactor, for example by creating some case classes to represent Card and Address in your model, and pass those in instead.