For an class in SwiftUI to conform to BindableObject, it has to have a Publisher, usually didChange, which in all of the SwiftUI documentation and videos I've seen so far, is a PassthroughSubject.
For example, if you have a class called TestObject, didChange might equal PassthroughSubject<TestObject, Never>(). I understand that the first type is the type of the data that the PassthroughSubject passes on, but what is Never? What is its purpose and are there any scenarios where the second type is not Never?
The second type provided to PassthroughSubject is the type used in case of failure.
final class PassthroughSubject<Output, Failure> where Failure : Error
The only requirement for this type is to conform to Error.
You can use an error type when the way you get your data can produce an error, like a network error for example.
The accepted answer does not address what Never is and why we may use it with a PassthroughSubject.
Never is defined as a enum with no cases. This means it can never be constructed. Sounds useless. However it can very useful to make sure functions behave as expected.
For example fatalError. fatalError will never return because it crashes the application. So you might be tempted to declare it as:
func fatalError() {}
However this would not be correct. The above function is actually returning an empty tuple (like all functions declared as above in swift). To be type correct we want to let the compiler know that if this function is called it will never return to the code that originally called it. Therefore we can use Never.
Never in PassthroughSubject
Sometimes we want Subjects that can never send errors. By declaring:
PassthroughSubject<TestObject, Never>()
you are saying that this subject will never fail with an error. So in our code we can't call the following because we can't construct a Never type to pass into the .failure:
subject.send(completion: .failure(<Nothing to construct here>))
For example: Let's say we had a timer and we wanted to publish events every 5 seconds. We could use a PassthroughSubject to send messages every 5 seconds to its subscribers. However we know it can't fail so to be clear to any consumers of our api that they don't need to worry about handling the failure case we can declare the PassthroughSubject with Never as the Error type.
Note:
The stream can still be terminated using the following:
subject.send(completion: .finished)
Related
I'm reading this page (I'm not using Amazon, just reading for golang education)
https://aws.amazon.com/blogs/developer/mocking-out-then-aws-sdk-for-go-for-unit-testing/
When I try it for myself, I get type errors.
type Queue struct {
Client ThirdPartyStruct
URL string
}
type mockedReceiveMsgs struct {
ThirdPartyStruct
Resp ValueIWantToMock
}
q := Queue{Client: mockedReceiveMsgs{}}
When I try to do the exact same thing, I get
cannot use mocked literal (type mockedReceiveMsgs) as type ThirdPartyStruct in field value
I feel like I'm copying the Amazon tutorial exactly. How come in there code, mockedReceiveMsgs can be used in place of ThirdPartyStruct?
The issue is not with mocking but with the fact that Queue structure includes ThirdPartyStruct by value (as a substructure), not as a pointer. And so does mockedReceiveMsgs. It just so happened that in Queue structure this substructure can be accessed by Client name and in mockedReceiveMsgs it is supposedly "anonymous" (but actually can be referred by ThirdPartyStruct name if required).
So, q := Queue{Client: mockedReceiveMsgs{}} actually tries to copy over mockedReceiveMsgs into Client and it obviously fails as it has extra bits, which don't fit into ThirdPartyStruct. You can make it compile by changing it to q := Queue{Client: mockedReceiveMsgs{}.ThirdPartyStruct} though I doubt this is what you want.
Note, that if you change Client ThirdPartyStruct to Client interface{} (in your original example) then it will compile as well. And this is most likely what you want. And it will also work with any interface type. Which is what #tkausl most likely was pointing out. The only tricky bit is pointer semantics vs value semantics when you're implementing your interface. It does back fire sometimes. See a quick example here
If ThirdPartyStruct is, as it's name implies, a struct type as opposed to an interface type, then you cannot mock it, it is just not possible in Go. If you read your example article carefully and follow the link that shows the definition of SQSAPI you'll see that it is an interface type.
type SQSAPIinterface{
To make your code "mockable" you need to use an interface type for the Client field. Here's an example that is more true to the aws one: https://play.golang.org/p/puhhgmFCUC4
Edit: TL;DR
I guess my main problem is I don't know how to store a list of functions that all take one argument, where the argument type is different between each function, but always extends from EventBase, for calling later.
i.e: EventChild extends from EventBase. A function with the signature
<void (EventChild&)>
will not fit into a variable of type
std::function<void(EventBase&)>
How do I store functions like this, knowing that a user shouldn't have to modify the class where they are stored each time they create a new event extending from our EventBase class?
Note: I had previously been told I could use a dynamic_cast to accomplish this. I have been trying to do exactly that, but it hasn't been working. I imagine for that to work I would have to use pointers somehow, but I am new enough to C++ that I'm not sure how to do it. Maybe that should be the starting point?
One of the problems with dynamic casting pointers I have been having is 'I can convert a pointer of type:
(Subbscriber*)(getDemoEvent(EventDemo&)
to type:
void(EventBase&)
or something along those lines. (not at my computer right now to try it)
This is obviously a problem limited to member functions, I assume.
I recently posted a question on here with the intention of solving an issue for a C++ Event system based on a "Publisher->Dispatcher->Subscriber" pattern. I don't know the exact name of this pattern, but I hear that it is a variant on the Observer pattern with an added "middle-man."
I have been trying to get this system to work for a while now and I am completely stuck. It was suggested in the comments of the previous question that for what I was trying to accomplish, my program layout is incorrect. This is very likely the case since I had been researching other event systems that were close to what I am after trying to modify them for use they were unintended for. So I figured I would describe what I am after, and ask the more general question of "How would you go about structuring and creating this?"
So here is my general idea of how the system should be laid out and how it should operate in a basic example:
Starting with the idea of 5 different files (plus headers and maybe some subclasses):
main.cpp
dispatcher.cpp
publisher.cpp
subscriber.cpp
eventbase.cpp
publishers and subscribers could be anything, and they only serve as an example here.
The first order of business would be to create an instance of our Dispatcher class.
Following that, we create instances of our publisher/subscriber classes. These 2 classes could be a part of the same file, different files, multiples of each, or not event be classes at all but simply free functions. For the sake of simplicity and testing, they are 2 separate classes that know nothing about each other.
When these 2 classes are created, they should be passed a reference or pointer to our dispatcher instance.
This is easy enough. Now let's get to how you should use the system.
A user of the system should be able to create a class that inherits from our EventBase class. Ideally, there should be no requirement on variables or functions to override from the base class.
Let's say we have created a new event class called EventDemo, with a public const char* demoString = "I am a Demo Event";.
From our subscriber class, we should be able to tell our dispatcher that we want to listen for and receive some events. The syntax for doing so should be as simple as possible.
Lets create a member function in our subscriber that looks like this:
void Subscriber::getDemoEvent(const EventDemo &ev) {
std::cout << ev.demoString;
}
Now we need a way to bind that member function to our dispatcher. We should probably do that in our constructor. Let's say that the reference to our dispatcher that we passed to our subscriber when we created it is just called 'dispatcher'.
The syntax for subscribing to an event should look something like this:
dispatcher->subscribe("EventToSubTo", &getDemoEvent);
Now since we are in a class trying to pass a member function, this probably isn't possible, but it would work for free functions.
For member functions we will probably need and override that looks like this:
dispatcher->subscribe("EventToSubTo", &Subscriber::getDemoEvent, this);
We use 'this' since we are inside the subscribers constructor. Otherwise, we could use a reference to our subscriber.
Notice that I am simply using a string (or const char* in c++ terms) as my "Event Key". This is on purpose, so that you could use the same event "type" for multiple events. I.E: EventDemo() can be sent to keys "Event1" and "Event2".
Now we need to send an event. This can be done anywhere we have a reference to our dispatcher. In this case, somewhere in our publisher class.
The syntax should look something like this to send our EventDemo:
dispatcher->emit("EventToSubTo", EventDemo());
Super simple. It's worth noting that we should be able to assign data to our event through it's constructor, or even template the event. Both of these cases are only valid if the event created by the user supports it.
In this case, the above code would look something like this:
dispatcher->emit("EventToSubTo", EventDemo(42));
or
dispatcher->emit("EventToSubTo", EventDemo<float>(3.14159f));
It would be up to the user to create a member function to retrieve the data.
OK, so, all of that should seem pretty simple, and in fact, it is, except for one small gotcha. There are already systems out there that store functions in a map with a type of .
And therein lies the problem...
We can store our listener functions, as long as they accept a type of EventBase as their argument. We would then have to type cast that argument to the type of event we are after. That's not overly difficult to do, but that's not really the point. The point is can it be better.
Another solution that was brought up before was the idea of having a separate map, or vector, for each type of event. That's not bad either, but would require the user to either modify the dispatcher class (which would be hard to do when this is a library), or somehow tell the dispatcher to "create this set of maps" at compile time. That would also make event templating a nightmare.
So, the overly generalized question: How do we do that?
That was probably a very long winded explanation for something seemingly simple, but maybe someone will come along not not know about it.
I am very interested to hear thoughts on this. The core idea is that I don't want the 2 communicators (publisher and subscriber) to have to know anything about each other (no pointers or references), but still be able to pass arbitrary data from one to the other. Most implementations I have seen (signals and slots) require that there be some reference to each other. Creating a "middle-man" interface feels much more flexible.
Thank you for your time.
For reference to my last question with code examples of what I have so far:
Store a function with arbitrary arguments and placeholders in a class and call it later
I have more samples I could post, but I think it's highly likely that the structure of the system will have to change. Waiting to hear thoughts!
I'm using Generic Type Requests and Handlers.If I have more than one IAsyncRequestHandler DryIoc is resolving multiple instances, instead of a single instance, causing MediatR to throw an exception.How can I solve this problem?Please check this behavior at Net Fiddle here.(Note that in this example Generic Type is only used to prove the point - MediatR throwing the exception - In my production code, Generic Types are actually needed)
The fix for your problem is out with DryIoc 2.10.1.
The reason details are in issue #446.
Update:
Regarding sample with class GoodMorningRequestHandler<T> : IAsyncRequestHandler<GoodMorningRequest, string> the exception is bit misleading but it is here as expected.
Reason is that above mapping is not registered at all by DryIoc RegisterMany. It happens because RegisterMany checks that service type (IAsyncRequestHandler<GoodMorningRequest, string>) should supply open-generic parameter T for implementation GoodMorningRequestHandler<T>, and obviously it cannot do that. Therefore this service type is filtered out.
After that, the remaining implementation would be HelloRequestHandler<T> which does not match to resolved IAsyncRequestHandler<GoodMorningRequest, string>, so the exception.
To confirm for yourself try to just register explicitly:
container.Register(typeof(IAsyncRequestHandler<GoodMorningRequest, string>), typeof(GoodMorningRequestHandler<>)). It will throw the exception. In comparison RegisterMany designed to be more tolerant, therefore it will just skip this pair.
In my system low hiearchy objects talk to the high hiearchy object via calling function of the +1 level hiearchy object, which calls a function of the +1 level hiearchy object, etc etc etc, until the function calling stops at the recipent.
There is a Message abstract class, and there are lots of derivated classes, which hold different kinds of datas.
Like:
FruitMessage: string, int
CoordinateMessage: float, float, float
etc etc
And those methods I mentioned before want Message objects so this chaincalling is done through one kind of method instead of creating methods for all of the Message types.
The problem comes, when the recipent receives the Message object.
The recipent wants to know what's in that message, so it can process receives message as the message type requires it.
(like it decreases the integer by 1 in FruitMessages, divides the coordinates in CoordinateMessages, etc.)
Currently I have two ideas, but maybe none of them is correct and I should use a third one. (tell me please)
The recipent dynamic_casts it while it doesn't the correct type.
Message has an enum field called MessageType, which is initalized in the derived class' constructor to the correct value, so the recipent just uses a switch-case during the process.
My question is that is it worth the redundancy?
dynamic_cast is slower than the integer check
but every time I create a new Message class I have to create a new enum value.
What should I do?
Both ways are OK. Redundancy vs speed is very common problem in Software development.
I would choose dynamic_cast as redundancy is the first step to bugs, but it's really up to you and depends on your performance requirements.
I saw very similar problem while working with Akka, they usually use dynamic_cast (I mean java/scala analogues)
I would recommend using the typeid operator to check the type of the message. This way, you avoid repeatedly calling dynamic_cast until you get the correct type.
void process_message(Message const& msg) {
if (typeid(msg) == typeid(FruitMessage)) {
auto& fruit_msg = static_cast<FruitMessage const&>(msg);
…
}
}
Even better, you could use the C++17 std::any container type. An any object can be copied around like a non-polymorphic value, and does not require the use of a virtual base class. If you don't have access to a C++17 library implementation, you could use boost::any instead.
void process_message(std::any const& msg) {
if (msg.type() == typeid(FruitMessage)) {
auto fruit_msg = std::any_cast<FruitMessage>(msg);
…
}
}
As for whether using an enum field would be faster than typeid or any, you'll have to do the benchmarking yourself.
I am calling a function in a API that returns a Answer object. Under some conditions, the API will return EMPTY_answer, which is defined as such:
#define EMPTY_answer ((Answer)0)
of course, attempting to access a Answer variable or function from an EMPTY_answer object crashes the application.
Trying to test for it using if(lAnswer == EMPTY_answer) also crashes the application. Is there any way to detect if the API is returning EMPTY_answer?
Edit:
I didn't code the api and I can't modify it in any way, I'm just digging through .h files trying to figure this out. And yes, I am aware that casting 0 to a class is a bit too creative to put it mildly. I just noticed that the == operator is overridden
(...)
class ExportedByJS0CORBA Answer
{
(...)
int __stdcall operator==(Answer *ipt) const;
}
the function being called is
static SubClassOfAction Query();
I'm simplifying names and quite a few layers of inheritance
To be more precise, it crashes with a Segmentation Fault.
Instead of doing a very ugly cast which is almost guaranteed to trigger undefined behavior, just make a static global variable which is used as the "empty" answer. You don't need to use this object in any way, just make it exist so it can be used as a sentinel.
In Answer.h:
extern const Answer EMPTY_answer;
In Answer.cpp:
const Answer EMPTY_answer; // use any constructor parameters that will be appropriate
If Answer is a class type, as the text of your questions suggest, then (Answer) 0 will construct a temporary Answer object using the constructor that accepts 0 as an argument (apparently such constructor exists). In this case attempting to access the members of that object will not crash anything, unless Answer class is specifically implemented to crash in this case (intentionally or unintentionally). So your "Of course..." claim makes no sense whatsoever. There's no immediate reason for such code to crash.
If you observe crashed in someAnswer == EMPTY_answer comparison, that would either mean that the implementation of == operator is buggy, or that either the LHS or the RHS are not valid objects. For example, it might turn out that it is illegal (by design) to construct an Answer object by conversion from 0. If so, then you should simply stop using (Answer) 0 in your code and find another, correctly supported object value to indicate an empty answer.
your original method of just checking for EMPTY_answer is the right way to solve this. Your real problem is why that crashes. What type is lAnswer? Or Answer for that matter... you can't cast 0 to a class like that.