Passing a collection of interface types to a function - interface

I'm having trouble figuring out the correct way to use interfaces in Go. My function needs to take a map of items that implement a certain method. It looks like this:
type foo interface {
bar() string
}
func doSomething(items map[string]foo) {
}
I'm trying to call this function with a type that implements the foo interface.
type baz struct { }
func (b baz) bar() string {
return "hello"
}
items := map[string]baz{"a": baz{}}
doSomething(items)
But I get the following error:
cannot use items (type map[string]baz) as type map[string]foo in function argument
However, it works fine when I do this:
items := map[string]foo{"a": baz{}}
doSomething(items)
But I want to reuse this same map against different interfaces. Basically I'm indexing a lot of objects and then passing them to various functions that require different interfaces implemented to compute results. I want to pass the map to one function as a map of foo and another function as a map of foobar.
I've tried various type assertions and conversions but nothing seems to work so I'm not sure if I'm just not using the correct syntax or just doing it completely wrong.
Go Playground at http://play.golang.org/p/8mMWCDG7vm.

This is a fairly common mistake.
You are mixing these two distinct types:
map[string]foo
map[string]baz
You cannot simply convert from one map type to another. The same goes with converting []T slices to []interface{} slices, or converting chan T to chan interface{} (same question/answer but for channels).
map[string]foo means a map of foo interfaces, not all types map[string]T where T implements the foo interface.
You can solve it by making this change:
items := map[string]foo{"a": baz{}}
Playground: http://play.golang.org/p/HxIVGSptwk
Edit:
Having a map of interfaces allows you to type cast the different interface values to other types of interfaces. So the map can be reused.
Playground: http://play.golang.org/p/20YMWmDjYT
But then you should have a map of an interface type that is the intersection of all the different methods implemented by the types to be stored in the map. If there is no intersection, then you will have to use interface{} to ensure that any type might be stored.

Related

Returning lazy sequences

I have a lazy sequence I do some operations on and want to return from a function
func getSeq() -> ??? {
let a = array.lazy
./* ... operations like map, filter, etc */
}
The final type of a is:
LazyMapSequence<FlattenSequence<LazyMapSequence<LazyFilterSequence<LazySequence<[[ComponentId] : ArchetypeId]>.Elements>.Elements, Zip2Sequence<Zip2Sequence<[C1], [C2]>, [C3]>>>, (C1, C2, C3)>
now how do I return a without having to specify the return type as that long type?
Opaque result types were created for exactly this purpose. They were added in Swift 5.1. You'll see them often in SwiftUI, where view contents are expressed as some View, meaning the result is some complex generic type (whose particular type is hidden from the user code), so long as it conforms to View.
For your particular case here, you would need to them in conjunction with primary associated types, to express exactly what kind of elements the resulting sequence should produce, like so:
func getSeq() -> some Sequence<Element> {
return array.lazy
./* ... operations like map, filter, etc */
}
Primary associated types were only recently introduced in Swift 5.7. As far as I can tell, they're a purely compile-time feature, so they don't require any specific OS version at runtime.
If Apple dropped support for your Mac and you can't run the necessary Xcode version for Swift 5.7, your next best bet is to do what we used to do: Use a type-eraser to erase the concrete type. For cases like yours, the standard library provides two type erasers, AnySequence and AnyCollection. This limits the type information to work with, so it might not optimize as nicely, but it works well enough.
func getSeq() -> AnySequence<Element> {
return AnySequence(
array.lazy
./* ... operations like map, filter, etc */
)
}

Error "Inout argument could be set to a value with a type other than ..." when passing in a protocol type

I am coming from C++ to Swift. I have this situation with respect to protocols and structs (I am working with random numbers):
(1) A protocol RandomPr that specifies there are methods such as randFloat() that returns a Float between 0 and 1.
(2) A struct RandomS that implements RandomPr using a "real" random number generator.
(3) A struct FakeRandomS that implements RandomPr, but has additional methods such as loadFloat() to load an array of Floats that are then regurgitated when I call randFloat() on a FakeRandomS instance. (For testing purposes.)
Now I have a function DoSomething(rng: inout RandomPr), which I want to use with both RandomS and FakeRandomS. The parameter has to be in-out as I need to update the RNG (whether it is real or fake). No problem calling DoSomething with an instance of RandomS.
But if I do
var fakeRng = FakeRandomS()
fakeRng.loadFloat([0.1, 0.2, 0.3])
DoSomething(rng: &fakeRng)
I get an error "Inout argument could be set to a value with a type other than 'FakeRandomS'. The suggested fix is to define fakeRng as
var fakeRng: RandomPr = FakeRandomS()
But now trying to call loadFloat on fakeRng fails because RandomPr doesn't have a method loadFloat, and the compiler doesn't see that fakeRng does have one.
I tried making another protocol FakeRandomPr that contains the extra methods that FakeRandomS has, and defining
var fakeRng: RandomPr & FakeRandomPr = FakeRandomS()
but, frustratingly, I now get the "Inout argument could be set to a value with a type other than ..." error back again.
I could do the equivalent of this in C++ without problems (a pure abstract base class and two child classes, passed in by reference), and it didn't matter that one of the things I wanted to pass in has extra methods. I want to translate this into protocols and structs. What is the Swift solution?
What is the Swift solution?
You may need to use generics:
func doSomething<RP: RandomPr>(rng: inout RP) {
//...
}
Swift is not just another syntax of C++, better think in Swifty way.

what does the brackets after function name do when calling a function in scala?

When reading some scala code, i see something like fooString
but I couldn't find anything that expalins this sort of commands when calling a function.
I know we should define the parameter and expected return type in scala when defining a function or class. Consider this code:
def socketTextStream(
hostname: String,port: Int
): ReceiverInputDStream[String] = withNamedScope("socket text stream") {
socketStream[String](hostname, port, SocketReceiver.bytesToLines)
}
what [String] after "socketStream" do here and I wonder why there is another function( withNamedScope) after "=" here.
First, def socketTextStream(hostname: String, port: Int): ReceiverInputDStream[String] is declaring a method called socketTextStream which receives two inputs (host & port) and returns a ReceiverInputDStream which is a generic class, and in this case the result will be parameterized with the type String.
Then, = withNamedScope("socket text stream") { .. } means that the implementation of that method is call other method (withNamedScope) that takes a String (presumably a name) as its first argument, and a block (probably a by name parameter) as its second argument.
In this case, the two arguments are on separated parameters lists, which is called currying.
Finally, socketStream[String](hostname, port, SocketReceiver.bytesToLines) (which is the body of the block) is calling another method socketStream which is a polymorphic / generic method.
The [String] part is specifying that the type parameter of that method, is String. Maybe this information is redundant or maybe it is used to force an specific implicit, without the definition of such method is hard to tell.
Anyways, all here is basic syntax and structures of the language, all covered by the tour (which many people highlight for being too brief and just covering the basis of the language). Thus, I would recommend you to check more resources before continue with reading code.

Element vs. Generic Type <T>

I wonder why Swift uses Element rather than Generic <T> in the following example.
What is the difference between Element vs T
From Generics:
Type Parameters
Type parameters specify and name a placeholder type, and are written immediately after the function’s name, between a pair of matching angle brackets (such as <T>).
Naming Type Parameters
In most cases, type parameters have descriptive names, such as Key and Value in Dictionary<Key, Value> and Element in Array<Element>, which tells the reader about the relationship between the type parameter and the generic type or function it’s used in. However, when there isn’t a meaningful relationship between them, it’s traditional to name them using single letters such as T, U, and V, such as T in the swapTwoValues(_:_:) function above.
So
func createArray<Element>(element: Element) -> [Element] { ... }
func createArray<T>(element: T) -> [T] { ... }
func createArray<Rumpelstilzchen>(element: Rumpelstilzchen) -> [Rumpelstilzchen] { ... }
are identical functions. Here the placeholder type is the element type of the returned array, therefore Element is a suitable “descriptive name.”
But it makes no difference otherwise, is it up to you to choose a name for the placeholder, balancing between readability and conciseness.
T is not particularly traditional. In FP, Backus uses T, but ML, from around the same time, uses a. Haskell uses a, Scala uses A. There's a mix of choices.
Swift, however, has strong reasons to use descriptive names. First, it's a quite descriptive language. Types are named with fully spelled-out words. Methods typically are literate in construction. Variables and properties are rarely abbreviated. There's no reason that type parameters should be uniquely obscure.
It also matches well with associated types which are quite naturally verbose. What would you call Collection's index type besides Index? Why should its "element" type be specially abbreviated? And if Array implements Collection, why should it create a distinct name (T) that it would then have to associate with Collection's Element? Why would you special-case all this just to make the type name unintuitive?
The deeper question would be, why wouldn't Array's element be called Element?

Is IEnumerable<object> the proper container for generic data sets?

Using Entity Framework, is IEnumerable the correct container to use to send back a generic data set? I.e. when I do not want to send back a list of the object, but just a generic a result set.
public IEnumerable<object> SelectPlayerFirstAndLastNameList()
{
return (from p in rlpEntities.Players select new { p.PlayerFirstName, p.PlayerLastName });
}
Thanks.
Here is the reference article, which talks about IList(inherits ICollection( and IEnumerable(Base Generic Interface for IQueryable,ICollection,List).
Here are the links which states generics & it's differences & it's usages,
Difference among IEnumerable , IQueryable, ICollection,IList, List
IEnumerable vs. ICollection vs. IQueryable vs. IList
Looking at your linq, it's about specific object & can be extended further in future. IQueryable is right fit for such scenario, as it gives client to iterate/add/remove items.
Check this link out Why use ICollection and not IEnumerable or List<T> on many-many/one-many relationships?.
It really depends on your scenario, but IEnumerable<> would be used when you need to iterate, and List<> when you need to iterate and modify or sort the data.
IEnunerable<> - http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx
List<> - http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
You can also use generics, to pass on whatever types you are querying against, like for instance
public IEnumerable<T> SelectPlayerFirstAndLastNameList<T>()
{
return (IEnumerable<T>)(from p in rlpEntities.Players);
}
So you can pass either object, or a known defined type. To call this you would do
var x = SelectPlayerFirstAndLastNameList<YourClassHere>();
I think what you have is correct but decide for yourself whether you should use it.
From MSDN: Anonymous Types in the Remarks section:
Anonymous types are class types that derive directly from object, and
that cannot be cast to any type except object.
and
To pass an anonymous type, or a collection that contains anonymous
types, as an argument to a method, you can declare the parameter as
type object. However, doing this defeats the purpose of strong typing.
If you must store query results or pass them outside the method
boundary, consider using an ordinary named struct or class instead of
an anonymous type.