Erlang and the records - erlang

What is wrong in this code?
I was expected "titi" in person.name but I still have "toto"!
More explicitly, how to modify a record in a function?
init1()->
S=#person{name="toto"}, %record creation and field setting
fct(S),
io:format("~s~n",[S#person.name]).
fct(R)->
R#person{name="titi"}. %record updating

You need to get a result of fct():
init1()->
S=#person{name="toto"}, %record creation and field setting
S2 = fct(S), % Get updated record
io:format("~s~n",[S2#person.name]).
fct(R)->
R#person{name="titi"}. %record updating

Bertaud, I think you are getting ahead of yourself a bit. You really need to understand the basics of immutability before you write any more code. (i.e. "variables" do not vary : you can only assign a value to them once.) I suggest you read the free online guide "Learn You Some Erlang For Great Good", at http://learnyousomeerlang.com/. The section that covers the basics of variables is http://learnyousomeerlang.com/starting-out-for-real#invariable-variables.

It is impossible to stress too much that all data in Erlang is immutable. So to do something like in your original question you need to modify it like #hdima did. The record is not updated but rewritten. In the same way there is no global data in Erlang, all data belongs to a process. This is even true of ETS tables as they basically behave like a process, albeit a built-in one without explicit communication.
So if you use the process dictionary or an ETS table the data itself can never be updated, only the dictionary/table. This means that to modify some data in the dictionary/table you basically have to:
"Read" the data
Update the data making new data
"Write" the new back into the dictionary/table
Without writing the new data back into the dictionary/table it will be lost, as your new data was.

Within fct(), you're not mutating the record, but you're returning a new value for the record, which needs to be used further. If you're calling fct(S), without handling the return value, then you'll lose that new value ("titi").

Related

What are ways to store complex dynamic objects locally (iOS, swift)?

I have iOS app that takes data from the server as json and then serializes them into objects of different types. Types can be complicated, can contain subtypes, can inherit, so there is no any limitations. Another thing that makes everything even more complicated is some of types are stored as AnyObject? and only in run time they are being serialized into real types accordingly to the specific rules. Something like that:
class A {
var typeName: String?
var b: AnyObject?
}
Then when it's serialized it can be done something like that:
if let someClass = NSClassFromString(typeName) as? SomeGenericType.Type{
b = someClass.init()
}
Also querying should be done on all the data. Currently I'm trying to store all of them locally, then load into memory and query there from the code. I'm using User defaults, but they have some limitations, also I needed to provide custom coding to make it work, and each time when I add a new field it turned out that I missed something in coding and nothing works. So it's pain.
Ideally I would just do some magic command and all the objects are sent to local storage no matter how complicated they are. The same to extract them from this storage. Also, user change data so I can't just store primary Json. And I don't want to covert objects back to Jason as for it's pain too.
Any suggestions?
If you want to use sqlite then You can store whole object in one row! I means you can create table with 2 columns one is id and second is your dataobject(it's data type should be blob). Then convert your whole object into data. Then store in sqlite table and retrieve it as data then convert it to object when want to use. By this way your object will remains in same format as you asked
Firebase while meant for online synching and storage can also cache everything locally in case you are offline and perform query's against the local cache. It uses JSON.
CouchDB also has a mobile version for iOS.
Both of those are over kill if your dataset is small; you can just store it as a text file and read the JSON back in. See performance characteristics here. The graph is for a 7MB file so if you are significantly less than that your load time may be minimal.
NSKeyedArchiver.archivedData(withRootObject:) is great for storing custom objects as Data objects. The only thing you need to do to be able to use this is to make your custom objects conform to NSCoding. A great example can be found here:
Save custom objects into NSUserDefaults
Once you have the Data version of the object, it can easily be stored in UserDefaults, as a property in CoreData, or even in the app's keychain entries. Depending on your use case, sensitivity of data, and how much data you intend to store, you might want to use any number of storage methods. NSKeyedArchiver.archivedData(withRootObject:) allows you to pretty much use any of them.

Fix uneccessary copy of NSManagedObject

I'm sorry the title may mislead you, since I'm not so good at English. Let me describe my problem as below (You may skip to the TL;DR version at the bottom of this question).
In Coredata, I design a Product entity. In app, I download products from a server. It return JSON string, I defragment it then save to CoreData.
After sometimes has passed, I search a product from that server again, having some interaction with server. Now, I call the online product XProduct. This product may not exist in CoreData, and I also don't want to save it to CoreData since it may not belong to this system (it come from other warehouse, not my current warehouse).
Assume this XProduct has the same properties as Product, but not belong to CoreData, the developer from before has designed another Object, the XProduct, and copy everything (the code) from Product. Wow. The another difference between these two is, XProduct has some method to interact with server, like: - (void)updateStock:(NSInteger)qty;
Now, I want to upgrade the Product properties, I'll have to update the XProduct also. And I have to use these two separately, like:
id product = anArrayContainsProducts[indexPath.row];
if ([product isKindOfClass:[XProduct class]] {
// Some stuff with the xproduct
}
else {
// Probably the same display to the cell.
}
TL;DR
Basically, I want to create a scenario like this:
Get data from server.
Check existed in CoreData.
2 == true => add to array (also may update some data from server).
2 == false => create object (contains same structure as NSManagedObject from JSON dictionary => add to array.
The object created in step 4 will never exist in CoreData.
Questions
How can I create an NSManagedObject without having it add to NSMangedObjectContext and make sure the app would run fine?
If 1 is not encouragement, please suggest me a better approach to this. I really don't like to duplicate so many codes like that.
Update
I was thinking about inheritance (XProduct : Product) but it still make XProduct the subclass of NSManagedObject, so I don't think that is a good approach.
There are a couple of possibilities that might work.
One is just to create the managed objects but not insert them into a context. When you create a managed object, the context argument is allowed to be nil. For example, calling insertNewObjectForEntityForName(_:inManagedObjectContext:) with no context. That gives you an instance of the managed object that's not going to be saved. They have the same lifetime as any other object.
Another is to use a second Core Data stack for these objects, with an in-memory persistent store. If you use NSInMemoryStoreType when adding the persistent store (instead of NSSQLiteStoreType), you get a complete, working Core Data stack. Except that when you save changes, they only get saved in memory. It's not really persistent, since it disappears when the app exits, but aside from that it's exactly the same as any other Core Data stack.
I'd probably use the second approach, especially if these objects have any relationships, but either should work.

DB4O update depth issues

I'm having some problems storing a change to a complex object. I've done a lot of digging and can't figure this out for the life of me.
From debugging, I can clearly see that the object is correct before storing, but when I retrieve the stored data, it's empty(say the increase of a stat). Specifically here is the breakdown below
StatSheet has ArrayList of Players
Player has ArrayList of Stats
ArrayList of StatSheets -> ArrayList of Players -> ArrayList of Stats
The ArrayList of Stat objects doesn't store after a change is made, no matter what I do. The arraylist of players seems to update fine which confuses me. I have tried changing the update depth to 2, 3, 4, 5, and beyond. I have also tried specifically setting cascadeOnUpdate to true. Can someone please help, I've been at this for days.
It's been a while that I looked at db4o and you didn't give a lot of details about your environment or code but maybe you can look at these solutions:
Do you use web environment? So look at this first answer:
A few questions about working with db4o
Do you use 'commit' when you store your objects? Because after storing and updating process you should commit the changes.
The array list of objects is store but db4o don't know what to do with the inner objects. The ArrayList isn't 'Activatable', so you can't retrieve yours objects.
You must put activationPurpose on every getter/setter of your stored object to enable the activation of object.
As you can't do this on native java objects, DB4O provide you some objects that have been tagged with activationPurpose on there getter/setter : like :
com.db4o.collections.ActivatableArrayList
So every java collection that should be store must be replace with it db4o equivalent (com.db4o.collections.*).

Best alternative for 'long term' storing model-view-controller data in Objective-C/ios

I am planning on creating my app in a 'Model-View-Controller'(MVC)-style, and in the end, for me at least, this means that all data is stored in the controller-class. Let's say I have a class Player, and the player has several objects of class Weapons or Equipment or whatever. The initialization of Controller* stores the player(s), so if I can store/save only the Controller-object over time, even if the app or the device restarts, that would be nice. I did this in Java one, I put in Serialization = 100L;(or something like it) in the top of the file of every object that would be included when saving the Controller-object, and it worked perfectly. Is this possible in ios/cocoa-touch/objective-c?
I have read and used Core Data (not very much), but that is just a database-table, sql?, which would have me extract every piece of information of every object?
For instance, if the object Player* has a member NSString *name;, I would have to save the actual string in Core Data, instead of saving the object of the player? Like, varchar.
If there is any way to store an entire custom object on the device for further use, I would very much like to know what it's called, and where I can read about it/tutorials.
Read up on the NSCoding protocol. You can make your object complient to it, then serialized it and save it to a file. Later you can restore it to the same state by using a decoder. For sure some other posts that cover this topic on SO.

Core Data Object for ID Only Found Once

I've got a huge xml File which needs to be parsed.
For different Tags inside the xml, e.g Football Soccer Data, I create NSManagedObjects e.g. SoccerPlayer and so forth.
I also need to use these objects a few times within the parsing method and so I created an Object which finds me the right object for the id I provide.
This works fine for the first game inside the xml but won't work for any one after that.
Could be the problem that I have to delete a few objects as I parse through the xml?
For my XML Parsing Framework, I use TouchXML.
Has anyone else experienced this behaviour before?
I agree with the comment that some code would help -- it's hard to understand exactly what the problem is. Nevertheless, I'll point out that the documentation for NSManagedObject's -objectID says:
Important: If the receiver has not yet been saved, the object ID is a
temporary value that will change when
the object is saved.
So, if you're creating an object, storing it's objectID, saving the context, and then trying to find the object with the objectID that you stored, you're probably going to fail because the temporary objectID was replaced with a permanent one when the context was saved.

Resources