where to put code that operates on an array of structs? - arrays

If I have a struct and some code that processes arrays of this struct, where would be the place to put this code?
struct Thing {
var id : String
let type : ThingType
}
things:[Thing]?
I have code to retrieve values from a server which returns an array of 100 Thing. Where should the code go?
I've currently defined it as a static function of the Struct but would like to follow a convention, if there is one.

A function that retrieves Thing instances from a server most certainly should not be a member of Thing.
It's best to make a new protocol that declares the function, like so:
protocol ThingProvider {
func fetchThings() -> [Thing]
}
and a conforming type:
class DataBaseThingProvider: ThingProvider {
init() {
// open database connection
}
deinit() {
// close database connection
}
func fetchThings() -> [Thing] {
// fetch Things from database
}
}
This way, you can change the provider you use (Firebase, Parse, SQLite, CoreData, JSON, CSV, whatever.) by just swapping out the concrete provider class you use, and all other code can stay the same.
It also makes your code much more testable, because you can easily construct a mock provider, which decouples your tests from your production backend.
class MockThingProvider: ThingProvider {
func fetchThings() -> [Thing] {
return [
Thing(id: "MockThing1", type: thingType1),
Thing(id: "MockThing2", type: thingType2),
Thing(id: "MockThing3", type: thingType3)
]
}
}

Related

SWIFT iterating through structures - issue

Im trying to iterate thorough and array of structures using generics and I keep getting this error. Value of type [T] has no member 'printMessage'
My 2nd questions is - What message would print? The statement in the Foo protocol extension or the statement in the struct instance?
Not sure what the issue is.. and its driving me insane!
protocol Foo {
func printMessage()
}
extension Foo {
func printMessage() {
print("Hello")
}
}
struct test: Foo {
func printMessage() {
print("Goodbye")
}
}
func MessagePrinter<T: Foo>(for message: [T]) {
for message in [message] {
message.printMessage()
}
For more clarity name the array in plural form and and the element in singular form.
And the square brackets in the for loop are wrong, the parameter is already an array
func messagePrinter<T: Foo>(for messages: [T]) {
for message in messages {
message.printMessage()
}
}
And please name functions always with starting lowercase letter.
The method in the protocol extension is called unless the method is implemented.
But consider that T is a single concrete type at runtime, you cannot call the method on a heterogenous Foo array like this
let messages : [Foo] = [Test()]
messagePrinter(for: messages)
You will get the error
Protocol 'Foo' as a type cannot conform to the protocol itself
To be able to call the method on an heterogenous array whose elements conform to Foo you have to declare
func messagePrinter(for messages: [Foo]) { ...
You are wrapping an array in another array here:
func MessagePrinter<T: Foo>(for messages: [T]) {
for message in [messages] {
message.printMessage()
}
}
(I've renamed your function argument from message to messages to make it clearer.)
When you write [messages] you end up with an array containing another array containing T, so the type is [[T]]. The single element message thus has type [T], and an array has no method printMessage.
What you want is this:
func MessagePrinter<T: Foo>(for messages: [T]) {
for message in messages {
message.printMessage()
}
}
As for what's printed when you execute it: that depends on what elements you feed it. If the elements implement printMessage those methods are called (e.g. "Goodbye"). Otherwise the default implementation you have provided for the protocol is called ("Hello").

To create map of array of map in golang

I want to create a json in golang for which I need to first create map of the following:
{"inputs": [{"data": {"image": {"url": "SOME_URL"}}}]}
how to create this map on golang. (for now even hardcoded will also work for me)
In a struct:
type SomeData struct {
Inputs []struct {
Data struct {
Image struct {
URL string `json:"url"`
} `json:"image"`
} `json:"data"`
} `json:"inputs"`
}
But if we wanted to be able to add things individually, AND be more idiomatic, we would do it like this:
type Image struct {
URL string `json:"url"`
}
type Data struct {
Image Image `json:"image"`
}
type Input struct {
Data Data `json:"data"`
}
type SomeData struct {
Inputs []Input `json:"inputs"`
}
Then, of course, we could always just use a map:
someData := map[interface{}]interface{}{}
It really just depends on which route you'd like to go. I suggest the second one as it gives you better fine-grained tooling without any pesky dirty tricks or code-clutter.
Hope this helps!
neededMap := make(map[string][]map[string]map[string]map[string]string)

I can't unmarshal basic string from akka http stream

I am trying to consume a stream of json objects in akka-http. ( akka http version "10.0.9", akka-http-play-json version 1.10.1)
I follow examples on web but, for String I am getting:
could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.FromByteStringUnmarshaller[String]
and for my user defined Foo case class (for which I provided the json protocol):
could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.FromByteStringUnmarshaller[server.Foo]
This is the code that is simplified. I provide a EntityStreamingSupport.json() and for the Foo object a Json Format. I don't think I need one for String. If I don't put the asSourceOf and read a simple String object or a Foo case class object the code works. What am I missing?
package server
import akka.http.scaladsl.common.EntityStreamingSupport
import akka.http.scaladsl.server.{ Directives, Route }
import akka.http.scaladsl.model.StatusCodes
import de.heikoseeberger.akkahttpplayjson.PlayJsonSupport._
import play.api.libs.json._
case class Foo(bar: String)
class StreamingMarketDataUpload extends Directives {
implicit val jsonStreamingSupport = EntityStreamingSupport.json()
implicit val jsonFooFormat = Json.format[Foo]
lazy val routes: Route =
path("upload1") {
post {
entity(as[String]) { input =>
complete(StatusCodes.OK)
}
}
} ~ path("upload2") {
post {
// Compile error here
entity(asSourceOf[String]) { marks =>
complete(StatusCodes.OK)
}
}
} ~ path("upload3") {
post {
entity(as[Foo]) { input =>
complete(StatusCodes.OK)
}
}
} ~ path("upload4") {
post {
// Compile error here
entity(asSourceOf[Foo]) { marks =>
complete(StatusCodes.OK)
}
}
}
}
asSourceOf[T] tries to consume the incoming data as a Source[T, _]. As its method signature indicates, asSourceOf[T] takes an implicit FromByteStringUnmarshaller[T] parameter. The de.heikoseeberger.akkahttpplayjson.PlayJsonSupport utility doesn't provide an implementation of this unmarshaller (as of version 1.19.0), but it does provide the unmarshallers necessary for consuming a simple String or Foo. This is why your code works when it's not using asSourceOf.
The examples in the documentation use SprayJsonSupport, which is shipped as part of Akka HTTP. If you don't want to use SprayJsonSupport, you'll have to implement a FromByteStringUnmarshaller to use asSourceOf: the linked source code can give you an idea of how to do this.

How to get the class of a VALUE in Ruby C API

I created some classes with Ruby's C API. I want to create a function whose behavior will change depending on the class of the Ruby object.
I tried to use is_a? from Ruby, however, I don't think it's the good way to do this. I checked "Creating Extension Libraries for Ruby" without success. The only direct way to check classes is with the default types.
I have my class "Klass" already created:
VALUE rb_cKlass = rb_define_class("Klass", rb_cObject);
And how I wanted to check if the class is the good one:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_check_class(my_argument), rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
Is there a way to do this?
I came across this recently, and used the RBASIC_CLASS macro, but was getting segfaults in certain scenarios for some unexplained reason.
After scanning through ruby.h, I found the CLASS_OF macro, which returns the class as VALUE of a given object.
VALUE obj = INT2NUM(10);
VALUE klass = CLASS_OF(obj); // rb_cInteger
Using Ruby 2.5
Every ruby object is internally represented by RObject struct (I will copy the source here for the sake of future readers):
struct RObject {
struct RBasic basic;
union {
struct {
uint32_t numiv;
VALUE *ivptr;
void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
} heap;
VALUE ary[ROBJECT_EMBED_LEN_MAX];
} as;
};
The very first member, RBasic, defines the class:
struct RBasic {
VALUE flags;
const VALUE klass;
}
To get an access to RBasic metadata of anything, one might use RBASIC macro:
RBASIC(my_argument)
To get the class directly, one might use RBASIC_CLASS macro:
RBASIC_CLASS(my_argument)
If you want to stay close to the is_a? Ruby fashion (i.e. check if any of the ancestors is the expected class), you could directly use the C implementation of is_a?, rb_obj_is_kind_of:
rb_obj_is_kind_of(my_argument, rb_cKlass) // Qtrue OR Qfalse
And since Qfalse == 0, you can just use that method as a condition:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_obj_is_kind_of(my_argument, rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
To find this method, just check Object#is_a? documentation and click to toggle source, you'll see the C implementation if it is a C function (hence this will work for most of the standard lib).

Get results from cloudkit-query

First: I'm really new at CloudKit and the "dispatch"-mechanisms.
But I'd like to write a function in swift which will return the query-results as an array. Now my problem is, that the function doesn't wait for the query to finish and so I receive an empty array. There are records in my DB but I don't get it back properly.
So as I said I don't really understand the whole dispatch_async-mechanism etc. I've also read the tutorial on raywenderlich.com about CloudKit but I still don't get, how I can return the array properly.
This is my actual code. I've often seen people using dispatch_async-methods but I really don't understand how they can return my array.
func loadMyShopsCoolAwesome() ->[Shops]{
let container = CKContainer.defaultContainer()
var publicDB = container.publicCloudDatabase
let myQuery = CKQuery(recordType: "Shops", predicate: NSPredicate(value: true))
var myShops = [MyShops]()
publicDB.performQuery(myQuery, inZoneWithID: nil) {
results, error in
if error != nil {
println(error)
} else {
for record in results{
let shop = MyShops(nameElementAt: record.objectForKey("nameElementAt") as Int, nameElementFromSplit: record.objectForKey("nameElementFromSplit") as Int, nameSplitString: record.objectForKey("nameSplitString"), priceElementAt: record.objectForKey("priceElementAt") as Int, priceSplitString: record.objectForKey("priceSplitString"), shopName: record.objectForKey("shopName"), shopURL: record.objectForKey("shopURL"), xPathName: record.objectForKey("xPathName"), xPathPrice: record.objectForKey("xPathPrice"))
myShops.append(shop)
}
return myShops
}
}
}
You should not let your function return data. This way it will only work if you implement a wait mechanism (usually done with semaphores). If you would do that, you would block your app during the data fetch.
Instead you should return void and instead of returning your shops you should call a new function with the shops. There you should continue processing of the shops. So your function will be:
func loadMyShopsCoolAwesome() {
...
And instead of the
return myShops
You should call a new function. something like:
processShops(myShops)
Which would then call a new function that looks like:
func processShops(shops: [Shops]) {
// do work with shops
...
}
Also be aware that this will be called on a background queue. So if you want to do something with the interface you have call that on the main queue like this:
NSOperationQueue.mainQueue().addOperationWithBlock {
...
}

Resources