At what point is the "Cmd Msg" of the init function delivered? - elm

I'm having trouble wrapping my head around the behaviour of the init function. I'm trying to build a login page, which goes into the CheckingAuth stage upon page-load. Here's my init function:
init : (Model, Cmd Msg)
init = (LoginModel Login.CheckingAuth, Cmd.map (\_ -> LoginMsg Login.CheckAuth) Cmd.none)
Here's a snippet of code from my Login.Page module:
type Model = CheckingAuth | Display String | Redirecting String
type Msg = CheckAuth | AuthResult (Result Http.Error (Either String (Entity User))) | RedirectTo String
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case (Debug.log "MSG DELIVERED" msg) of
CheckAuth -> (CheckingAuth, Debug.log "making API request" <| Http.send AuthResult Api.login)
-- other cases come here
I've tried a lot of things, but can't get the CheckAuth message to be delivered upon application startup.
Edit: I finally got something working with the following code snippet, but I have no idea why the Cmd Msg constructed by Task.perform works, but the one constructed by Cmd.map doesnt:
init = (LoginModel Login.CheckingAuth, Task.perform (always <| LoginMsg Login.CheckAuth) (Task.succeed ()))

The problem is that your init it not doing anything. If you map anything over a Cmd.none you still have a Cmd.none.
The command you really want to send is in your update function, so just promote that directly into init and you should be good to go:
init =
(LoginModel Login.CheckingAuth, Http.send AuthResult Api.login)
Your second code example does indeed have a command in it, so that returns immediately and gets passed to the update function, but as you can see, this is not simplest way to your goal.

Related

How to handle simple error in Kotlin function Android

I'm having trouble handling error in the following function. I'm basically new to Kotlin. Here's my RevenueCat Login Code and I want to handle ::error in this code:
Purchases.sharedInstance.logInWith(
myUserID,
::error // <- How to handle this? I want to retrieve error Code and Error Message.
)
{ customerInfo, created ->
// Handle Successful login here
}
Here's the code behind the function (within RevenueCat SDK)
#Suppress("unused")
fun Purchases.logInWith(
appUserID: String,
onError: (error: PurchasesError) -> Unit = ON_ERROR_STUB,
onSuccess: (customerInfo: CustomerInfo, created: Boolean) -> Unit
) {
logIn(appUserID, logInSuccessListener(onSuccess, onError))
}
The double colon in ::error is a function reference. It is basically a reference to the function error().
And from your logInWith() function, we have onError: (error: PurchasesError) -> Unit = ON_ERROR_STUB, meaning that the function should take PurchasesError as input parameter and does not need to return.
So we can derive a function as the following:
fun error(error: PurchasesError) {
// And you can do something with the error here
}
I solved it like this:
Purchases.sharedInstance.logInWith(
myUserID,
onError = { error ->
// Handle error here
}

F# Console app is completely bombing out ignoring error handling

Excuse all the Console.WriteLines! Trying to figure out what is happening here.
The following code works if I run it in visual studio. When I compile and run it as a command line program - the line that tries to access an API using HttpClient completely stops the whole process and ends the program. No error handling, nothing. How can this happen? It bombs out if I remove the try/ with block as well. I am baffled.
let getTransactionData(ewayCSVData: EwayCSVData, httpClient: HttpClient) = task{
try
Console.WriteLine("get transaction data 1")
if ewayCSVData.transactionType.ToLower() = "refund" then
Console.WriteLine("get transaction data 2")
let url = "https://api.ewaypayments.com/Transaction/"+ewayCSVData.transactionNumber.ToString() + "/Refund"
Console.WriteLine("get transaction data 3")
let! postResult = httpClient.PostAsync(url, null)
Console.WriteLine("get transaction data 4")
let! result = postResult.Content.ReadAsStringAsync()
Console.WriteLine("get transaction data 5")
return result
else
Console.WriteLine("get transaction data 6")
let url: string = "https://api.ewaypayments.com/Transaction/"+ewayCSVData.transactionNumber
let! result = httpClient.GetStringAsync(url) // This line kills the whole process
Console.WriteLine("get transaction data 7")
return result
with (ex) ->
Console.Write(ex.Message)
Console.WriteLine("get transaction data 8")
return ""
}
I suspect your command-line program is simply exiting because it has reached the end of its code. You're launching an asynchronous task to access the API, but your program doesn't wait for this task to complete before exiting. That's why there are no exceptions or error messages.
To fix this, you can either explicitly wait on the result (e.g. via Task.Result), or put something at the end of your program to prevent the main thread from exiting. One common way to do this is by calling Console.ReadLine() on the last line of your top-level function.
For example, the following program (usually) exits without writing anything to the console:
open System
open System.Threading.Tasks
Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
|> ignore
You can fix this by calling Result:
let task = Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
task.Result
Or by calling Console.ReadLine:
Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
|> ignore
Console.ReadLine() |> ignore
Note that my examples use Task.Run to illustrate the point. I don't think the F# task builder behaves quite the same way, but it sounds similar enough from your description.

In Android Kotlin, when creating a dialog, the samples I've seen include "_, _ ->" what does that mean or do?

The tutorial I'm working on gives this code:
private fun showFinalScoreDialog() {
MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.congratulations))
.setMessage(getString(R.string.you_scored, viewModel.score))
.setCancelable(false)
.setNegativeButton(getString(R.string.exit)) { _, _ ->
exitGame()
}
.setPositiveButton(getString(R.string.play_again)) { _, _ ->
restartGame()
}
.show()
}
The tutorial took this moment to explain "trailing lambda syntax", but didn't bother to explain the actual content of the lambda. The part that I'm clueless on is _, _ -> what is this? What does it do?
The tutorial says "...the setNegativeButton() method takes in two parameters: a String and a function, DialogInterface.OnClickListener()..."
In your case, the -> is used for lambda expressions to separate parameters from the function body. The lambda you're writing for both buttons will be invoked when the buttons are clicked. So, the exitGame operation will execute when clicking the "NegativeButton", and the restartGame operation will execute when clicking the "PositiveButton".
When writing _ as the parameters, it basically means that you don't care about them, because they won't be used in your function body.

ModelMapper - condition AND provider

All -
I'm trying to do an "addmapping" with a condition and a provider... bottom line is, one of my values are an Instant, and without the provider, it blows up telling me that Instant doesnt have a default constructor (which it doesnt)
I've gotten this far:
.addMappings(mapper -> {
mapper.when(ctx -> customerSource(ctx).getEnableDuplicatePOChangedTime().isDirty())
.<Instant>map(src -> src.getEnableDuplicatePOChangedTime().getValue(), (dest, v) -> dest.setEnableDuplicatePOChangedTime(v));
mapper.with(req -> req.getSource()).<Instant>map(src -> src.getEnableDuplicatePOChangedTime().getValue(), (dest, v) -> dest.setEnableDuplicatePOChangedTime(v));
})
However, what seems to happen now is, it skips the condition all together - it maps it no matter what!
In debug, this seems to overwrite the condition, setting it to null.
Any thoughts??
well, I seemed to figure it out by using a provider up front, and getting rid of the add mappings.... so it would be something like this
.setProvider(request -> {
CustomerPreferencesDirty source = CustomerPreferencesDirty.class.cast(request.getSource());
PreferencesByCustomer dest = new PreferencesByCustomer();
if (source.getEnableDuplicatePOChangedTime().isDirty()) {
dest.setEnableDuplicatePOChangedTime(source.getEnableDuplicatePOChangedTime().getValue());
return dest;
})
and then I continue on with addMappings for properties other than this one.... I'm good with that.

Is it necessary to use async keyword when using IDisposable in F#?

I get a Cannot access a disposed object error when running the following code (MyClient is a WCF client generate by a service reference in a C# project).
type Action =
| Add
| Update
let addStuff (myClient:MyClient) arg = async {
let! response = myClient.AddAsync arg |> Async.AwaitTask
return response.ID
}
let updateStuff (myClient:MyClient) arg = async {
let! response = myClient.UpdateAsync arg |> Async.AwaitTask
return response.ID
}
let doStuff arg =
use myClient = new MyClient()
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
let args = [Add, Add, Update, Add]
let results =
args
|> List.map doStuff
|> Async.Parallel
It seems the client is being disposed before I expect it to. If I change doStuff to:
let doStuff arg = async {
use myClient = new MyClient()
return!
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
}
The return type of both functions is Async<int>. Why is the client being disposed early in the first example? I would think both examples are logically identical. My understanding is that the async workflow is only necessary if you need to use the ! bindings which I do not think is necessary in this case as the actual await is happening in the specific functions.
The problem is with doStuff:
let doStuff arg =
use myClient = new MyClient()
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
You are passing myClient into an async function which captures the MyClient instance. However, when doStuff returns it calls Dispose on the MyClient instance and disposes the client. When your async method gets around to running it is using a disposed instance.
Making doStuff works because the dispose becomes part of the async workflow.
Another option would be to not use the MyClient instance but instean have addStuff and updateStuff create their own MyClient instance.
What the async { ... } block gives you in this case are two things:
It delays the execution of all the code inside it until the async computation is executed,
It handles the use keyword accordingly (i.e. the IDisposable will be disposed after the nested addStuff/updateStuff workflow executes).
As to whether the pattern you use is wrong - yes, it is.
F# async and C# async-await are two very different constructs with very different semantics, and experiences from one don't carry easily to the other.
C# async-await is a way of chaining Tasks. A Task<'t> is a future, that is, a container for a value of type 't that becomes available at a later time. The computation that produces that value is, by default, scheduled immediately to execute on a background thread, accessing the value is a blocking operation until that computation finishes, and further attempts to access it return a cached value.
On the other hand, F# Async<'t> is value that represents an abstract specification of a computation that, once executed, yields a value of type 't. The execution however is deferred to the caller - who can make a choice how (and if at all) to execute the computation. Unlike a task, async doesn't carry a value of type 't - each execution yields a new (and potentially different) value.
Going back to your sample:
let doStuff arg =
use myClient = new MyClient()
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
What you have here is a function that does some work and returns an Async<'t> value to the caller. The caller is then free do to whatever they want with it - execute it, ignore it, or pass it further without executing.
The reason why it fails is because myClient is being disposed when doStuff returns - which is before the caller has a chance to execute the async.
The problem comes from the fact that this pattern you use splits execution of a particular piece of logic into two - one part executes when the function is called, the other when the async is executed, whereas the code is written with the intent that everything there executes as a single unit.
It is a pattern that invites more or less subtle bugs, even if in many cases there would be no easy to observe effects of this discrepancy - especially if async is unconditionally executed immediately after the function returns.