I'm completely new to Lift. My goal is to make a small application which will let me enter data about scientific articles (studies) into a database.
I haven't gotten around to making a database yet, still playing with getting an entry form to work. So I decided that I will hold a few studies in memory, in a list of a companion object to the Study class. I also created an accumulator variable to dispense unique IDs, as long as I don't have a DBMS managing the IDs.
As a smoke test, I visited the page showing the list of studies (seeded with two studies in code), then visited the form page, entered a new study, and navigated again to the list of studies. I was surprised to see that my new study has the ID of 1 instead of 3, so at some point, my accumulator variable must have been reset. But the ListBuffer collecting studies was not reset, because it showed all three studies. Adding more studies results in the counter incrementing by 1 every time.
The literature I have found on Lift (the two free books on Liftweb, as well as Gilberto Garcia's Lift Application Development Cookbook) are incomplete and are more like a collection of mini-tutorials, they don't explain how Lift works.
So what is the actual lifecycle of my Study object, and why did one mutable variable get reset after re-opening the page but not another?
package org.rumtscho.litsuche
package study
import scala.collection.mutable.ListBuffer
class Study private[study](
val id: Int,
val handmadeAuthorRef: String,
val humanReadableDescription: String )
{
}
object Study {
val seedStudies = List(
new Study(dispenseNextFreeId, "Brooks1975", "Tells us that throwing more programmers at a project makes it run late, not early"),
new Study(dispenseNextFreeId, "Dijkstra1968", "Recognizes that we need structured code")
)
private var studiesList = seedStudies.to[ListBuffer]
private var currentId = 0
private def dispenseNextFreeId: Int = {
currentId = currentId + 1
return currentId
}
def allStudies = studiesList.toList
def addStudy(reference: String, description: String): Unit = {
studiesList += new Study(dispenseNextFreeId, reference, description)
}
}
Here is the representation of the three studies:
update My understanding of what is happening (could be wrong, of course):
I open the page showing the list of studies. This calls allStudies. studiesList is initialized to contain Brooks1975 and Dijkstra1968. During the construction of the studies, currentId is initialized to 0 and then incremented to 2.
I open the entry form and add a third study. addStudy retrieves allStudies from memory, without initializing it again. It initializes currentId to 0. I end up with a third study with the ID 1.
I display all studies, then return to the entry form page. This time, addStudy retrieves both allStudies and currentId from memory. I get a fourth study with the ID of 2.
The comments have pointed out that this is probably Scala-specific and not related to Lift. But still, I don't understand why currentId is initialized two times (in steps 1 and 2), and not either once (as soon as the object itself is created) or every time it is read. I would have expected the first behavior, but even reinitializing every time seems more logical than randomly reinitializing one time only.
Go into the scala REPL, enter paste mode (:paste) command, and put in the following:
def increment {
currentId = currentId + 1
}
increment
increment
var currentId = 0
then try
var currentId = 0
def increment {
currentId = currentId + 1
}
increment
increment
In the first example, currentId ends up with value 0. In the second, it ends up with value 2. Why does this happen? I'm not an expert on Scala declaration, but it seems that this is the same problem you are running in to.
It seems that the solution is as #jcern suggests. In general, I'd say put all your declarations at the top of your classes or objects, and always declare before using a variable, and not the other way around.
Related
I'm trying to produce a runtime table. Below class and codes are simplified version of my final purpose.
class AppModel {
int appID;
String appName;
AppModel({this.appID, this.appName});
}
I'm calculating, fetching some another data and trying to fill the following object like this:
// _newApps value is between 1-30 mostly but not limited
List<AppModel> theList = [];
for (int i = 0; i < _newApps; i++) {
AppModel _newRecord = AppModel();
_newRecord.appID = _getNewAppID();
_newRecord.appName = _getNewAppName();
theList.add(_newRecord);
}
So the question is the code creates a new AppModel instance for only adding the element to the list for every iteration inside the for loop. According to my program logic, this event can be repeated 100-150 times sometimes.
Is it normal or is there any more memory efficient way to do so?
Thank you in advance.
I would like to point out (a better approach) that instead of for Loop you could have used the map method on the Apps List you have. And instead of creating a object every time in the Loop create a constructor for returning the object instance using the required details.
Hope you find it useful.
Encountering a problem whereby I am specifying Private Constants at the start of a scala step definiton file which relies on a List Buffer element to be populated, however when compiling I get a 'IndexOutOfBoundsException' because the list is empty initially and only gets populated later in a for loop.
For Example I have the following 2 constants:
private val ConstantVal1= globalExampleList(2)
private val ConstantVal2= globalExampleList(3)
globalExampleList is populated further down in the file using a for loop:
for (i <- 1 to numberOfW) {
globalExampleList += x.xy }
This List Buffer adds as many values as required to a global mutable ListBuffer.
Is there a better way to declare these constants? I've tried to declare them after the for loop but then other methods are not able to access these. I have around 4 different methods within the same file which use these values and instead of accessing it via index each time i thought it would be better to declare them as a constant to keep it neat and efficient for whenever they require changing.
Thanks
You can create list buffer of necessary size with default value and populate it later:
val globalExampleList: ListBuffer[Int] = ListBuffer.fill(numberOfW)(0)
for (i <- 0 until numberOfW) {
globalExampleList(i) = x.xy
}
But ConstantVal1, ConstantVal2 will still have original default value. So you can make them vars and re-assign them after you populate the buffer.
Your code seems to have a lot of mutations and side effects.
You have 2 ways to go.
First you can use lazy modifier
private lazy val ConstantVal1= globalExampleList(2)
private lazy val ConstantVal2= globalExampleList(3)
Or you can write the two lines after the for loop.
val globalExampleList = XXXX
for (i <- 1 to numberOfW) { globalExampleList += x.xy }
private val ConstantVal1= globalExampleList(2)
private val ConstantVal2= globalExampleList(3)
Below is some really rudimentary sample code to illustrate the question.
case class randomizer(seed: Long){
def getRandom(): Double = {
//Other stuff
val rand = new util.Random(seed)
rand.nextDouble()
}
}
This will reliably return the same first value always. Every time getRandom is called.
However,
case class randomizer(seed: Long){
val rand = new util.Random(seed)
def getRandom(): Double = {
//Other stuff
rand.nextDouble()
}
}
This will return a different random value every time.
I suspect this is because by re-initializing rand every single time (as in the first one) we end up getting the first number for that seed. Since the seed guarantees that we will get the same "set" of random numbers each time this is expected behavior. By moving the generator outside of the function it will exist as long as the class does, and as a result continue generating numbers in that "set". Is this the correct way to think about this?
It's not a "set" so much as a "stream", but yes, that's it.
I have a class that needs to write to a file to interface with some legacy C++ application.
Since it will be instantiated several times in a concurrent manner,
it is a good idea to give the file an unique name.
I could use System.currentTimemili or hashcode, but there exists the possibility of collisions.
Another solution is to put a var field inside a companion object.
As an example, the code below shows one such class with the last solution, but I am not sure it is the best way to do it (at least it seems thread-safe):
case class Test(id:Int, data: Seq[Double]) {
//several methods writing files...
}
object Test {
var counter = 0
def new_Test(data: Seq[Double]) = {
counter += 1
new Test(counter, data)
}
}
Did you try this :
def uuid = java.util.UUID.randomUUID.toString
See UUID javadoc, and also How unique is UUID? for a discussion of uniqueness guarantee.
it is a good idea to give the file an unique name
Since all you want is a file, not id, the best solution is to create a file with unique name, not a class with unique id.
You could use File.createTempFile:
val uniqFile = File.createTempFile("myFile", ".txt", "/home/user/my_dir")
Vladimir Matveev mentioned that there is a better solution in Java 7 and later - Paths.createTempFile:
val uniqPath = Paths.createTempFile(Paths.get("/home/user/my_dir"), "myFile", ".txt"),
I have a procedure that continuously updates a value. I want to be able to periodically query the operation for the current value. In my particular example, every update can be considered an improvement and the procedure will eventually converge on a final, best answer, but I want/need access to the intermediate results. The speed with which the loop executes and the time it takes to converge matters.
As an example, consider this loop:
var current = 0
while(current < 100){
current = current + 1
}
I want to be able to get value of current on any loop iteration.
A solution with an Actor would be:
class UpdatingActor extends Actor{
var current : Int = 0
def receive = {
case Update => {
current = current + 1
if (current < 100) self ! Update
}
case Query => sender ! current
}
}
You could get rid of the var using become or FSM, but this example is more clear IMO.
Alternatively, one actor could run the operation and send updated results on every loop iteration to another actor, whose sole responsibility is updating the value and responding to queries about it. I don't know much about "agents" in Akka, but this seems like a potential use case for one.
What are better/alternative ways of doing this using Scala? I don't need to use actors; that was just one solution that came to mind.
Your actor-based solution is ok.
Sending the intermediate result after each change to a "result provider" actor would be a good idea as well if the calculation blocks the actor for a long time and you want to make sure that you can always get the intermediate result. Another alternative would be to make the actual calculator actor a child of the actor that collects the best result. That way the thing acts as a single actor from the outside, and you have the actor that has state (the current best result) separated from the actor that does the computation, which might fail.
An agent would be a solution somewhat between the very low level #volatile/AtomicInteger approach and an Actor. An agent is something that can only be modified by running a transform on it (and there is a queue for transforms), but which has a current state that can always be accessed. It is not location transparent though. so stay with the actor approach if you need that.
Here is how you would solve this with an agent. You have one thread which does a long-running calculation (simulated by Thread.sleep) and another thread that just prints out the best current result in regular intervals (also simulated by Thread.sleep).
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent._
import akka.agent.Agent
object Main extends App {
val agent = Agent(0)
def computation() : Unit = {
for(i<-0 until 100) {
agent.send { current =>
Thread.sleep(1000) // to simulate a long-running computation
current + 1
}
}
}
def watch() : Unit = {
while(true) {
println("Current value is " + agent.get)
Thread.sleep(1000)
}
}
global.execute(new Runnable {
def run() = computation
})
watch()
}
But all in all I think an actor-based solution would be superior. For example you could do the calculation on a different machine than the result tracking.
The scope of the question is a little wide, but I'll try :)
First, your example is perfectly fine, I don't see the point of getting rid of the var. This is what actors are for: protect mutable state.
Second, based on what you describe you don't need an actor at all.
class UpdatingActor {
private var current = 0
def startCrazyJob() {
while(current < 100){
current = current + 1
}
}
def soWhatsGoingOn: Int = current
}
You just need one thread to call startCrazyJob and a second one that will periodically call soWhatsGoingOn.
IMHO, the actor approach is better, but it's up to you to decide if it's worth importing the akka library just for this use case.