How can I use Cmd.map within a update-function using multiple arguments? - elm

In Elm 0.19.1, I have the following Msg (among others):
type Msg
= Yay Multiselect.Msg
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Yay sub ->
let
( subModel, subCmd, _ ) =
Multiselect.update sub model
in
( { model | multiselectC = subModel }, Cmd.map Yay subCmd )
I'm using an external library here (Multiselect: https://github.com/inkuzmin/elm-multiselect). For this Msg, I'm correctly following the examples of the library. Goal here is handling events from this library to update the Model in this module. This correctly works.
Here comes the problem. I want to add multiple arguments to this Msg. For example, let's add the Multiselect.Model to it, creating the following type:
type Msg
= Yay Multiselect.Msg Multiselect.Model
This gives an error in the Cmd.map (makes sense since it is missing de Model). I've tried updating the Cmd.map-function in the following function:
Yay sub msModel ->
let
( subModel, subCmd, _ ) =
Multiselect.update sub msModel
in
( { model | multiselectC = subModel }, Cmd.map (\cmd -> Yay cmd subModel) subCmd )
This will remove the compile errors and will work for most of the events. However, some some events (for example, removing items), the library will behave unexpectedly and different from the code before.
I've also added some logging, creating the following command line:
It looks like it is correctly updating the Model when removing an selected item. However, with the next triggered event, it looks like the function is using the old model, removing the update. This basically means that nothing happens.
How can I correctly write the Cmd.map with multiple arguments which will behave the same as the first update-function with only 1 argument?

The way you pass multiple arguments to your Msgs is correct.
But you ran into a special case, because you passed state from the view.
Most times, it is better to only pass information what is supposed to change and not both the supposed change and an old state as part of your message.
My take at an explanation:
This behavior is due to the Elm runtime and optimizations for rendering:
The DOM is only rendered between 30 and 60 times a second, and the event that is fired from the view is using an old state.
So the state of your model was updated (because it is executed as fast as possible), but then later overwritten with the old state that is still being displayed by the browser.
When looking at this image from the official documentation, you can see that not every update triggers an immediate re-rendering of the DOM, but the work is done out-of-sync:

I actually fixed this issue in my case. It turns out that this method of mapping the Cmd is correct and works. However, in my case using the external library, it turns out that my view will fire multiple messages to my update-function using the same Multiselect.Model. My update-function updates this model, but this updated model will not be used for the messages fired from the view.
What I've done to fix this is removing the Multiselect.Model argument from the Msg. I will now use other arguments (that will not be updated in between the different messages) to search for the Multiselect.Model within the model of my module. This will take much code, but it actually works.

Related

Pyomo dynamic optimisation ERROR: variable that is not attached to an active block on the submodel being written

I am trying to set up a model for a dynamic optimisation problem with pyomo.DAE.
I defined my state variable as well as it's corresponding Derivative (both indexed by m.Time). I then set up a simple constraint that expresses the relationship between state and derivative variable in the most simple terms. Solving the problem with a dummy objective (so just testing the constraint), I get the following error:
ERROR: Model contains an expression (calc_my_state[0])
that contains a variable (derivative_var[0]) that is not
attached to an active block on the submodel being written
Here's an excerpt of what I wrote:
(.....)
m.state_var = Var(m.Time, initialize=0)
m.derivative_var = DerivativeVar(m.state_var, wrt=m.Time)
def calc_my_state(m,i):
return m.derivative_var[i] == m.state_var[i]*2
m.calc_my_state = Constraint(m.Time, rule=calc_my_state)
m.obj = Objective(expr=1)
opt = SolverFactory("glpk")
results = opt.solve(m)
I tried to reproduce the simple setup of an DAE in pyomo, more or less copied and pasted lines from the pyomoDAE docu.
I printed derivative_var.get_state_var() and it gives me the right state variable without error.
I also tried solving simple DAE examples that I found on the internet and solving them with my solver settings worked fine as well.
What am I missing? I am grateful for any input!!! Thanks!
I found the missing link: I did not specify the "Discretization Transformation". Once something like the following was added, the script ran without error!
discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(m, wrt=m.Time)

Pymongo: insert_many() gives "TypeError: document must be instance of dict" for list of dicts

I haven't been able to find any relevant solutions to my problem when googling, so I thought I'd try here.
I have a program where I parse though folders for a certain kind of trace files, and then save these in a MongoDB database. Like so:
posts = function(source_path)
client = pymongo.MongoClient()
db = client.database
collection = db.collection
insert = collection.insert_many(posts)
def function(...):
....
post = parse(trace)
posts.append(post)
return posts
def parse(...):
....
post = {'Thing1': thing,
'Thing2': other_thing,
etc}
return post
However, when I get to "insert = collection.insert_many(posts)", it returns an error:
TypeError: document must be an instance of dict, bson.son.SON, bson.raw_bson.RawBSONDocument, or a type that inherits from collections.MutableMapping
According to the debugger, "posts" is a list of about 1000 dicts, which should be vaild input according to all of my research. If I construct a smaller list of dicts and insert_many(), it works flawlessly.
Does anyone know what the issue may be?
Some more debugging revealed the issue to be that the "parse" function sometimes returned None rather than a dict. Easily fixed.

Elm: Pass current time as an effect to Tick Action, after model update

In update I would like to call my Tick Action every time Input is called.
The scenario is that a user enters a value in a text field, on update the model is updated via Input and then Tick is called and more stuff is performed on the model.
In 0.16 I could do something like this :
Input query ->
({ model | query = query }, Effects.tick Tick)
Tick clockTime ->
-- do something with clockTime
I'm not sure how to do this in 0.17.
I'm not sure if this would be a subscription and if it were, how you could go about configuring it to call Input then Action.
Any help is appreciated.
The functionality for retrieving the current time as an effect has been moved into a Task, in the Time module under Time.now.
http://package.elm-lang.org/packages/elm-lang/core/4.0.1/Time#now
You can reproduce your functionality by making the following changes:
1) Make sure there is a NoOp message available in your messages. Time.now returns a Task which we know will never fail, but we still need a failure message to hand to Task.perform
type Msg
= Input String
| Tick Time
| NoOp
2) Replace Effects.tick Tick with Time.now and Task.perform
Input query ->
( { model | query = query }
, Time.now |> Task.perform (\_ -> NoOp) Tick
)
If you don't like the NoOp message, there are other ways around it, such as using Debug.crash or performFailproof from Task.Extra (found here: http://package.elm-lang.org/packages/NoRedInk/elm-task-extra/2.0.0/Task-Extra#performFailproof)

Sap Code Inspector - Generating a table of all PCodes linked to the classes

I have problems to read the error codes and corresponding messages of SCI message classes.
Is there an way to easy access those?
I'm using "Praxishandbuch SAP Code Inspector" as a reference, but in that regard it is of no help.
I looked in Se11 but the information to the messages isn't helpful.
Has someone an approch to build such a table?
You can try this, perhaps it will work for you. I use the code below to get the access to all the errors found by Code Inspector for particular user(s):
data: ref_inspec_a type ref to cl_ci_inspection.
ref_inspec_a = cl_ci_inspection=>get_ref(
p_user = pa_iuser
p_name = pa_inam
p_vers = pa_ivers ).
data: ls_resp type scir_resp,
lt_resp type scit_resp.
clear: ls_resp, lt_resp.
ls_resp-sign = 'I'.
ls_resp-option = 'EQ'.
ls_resp-low = pa_fuser.
insert ls_resp into table lt_resp.
call method ref_inspec_a->get_results
exporting
p_responsibl = lt_resp
exceptions
insp_not_yet_executed = 1
overflow = 2
others = 3.
Playing around with LT_RESP you can get results for more users at the same time.
After you execute the code above, you can check the attributes SCIRESTPS and SCIRESTHD of the object REF_INSPEC_A. These are the large tables, which contain the result data of the SCI check. You can either work with them on your own, or you can simply pass the object REF_INSPEC_A into the function module SCI_SHOW_RESULTS to get regular SCI user interface.
I found out that you can get all the changeable messages (found in SCI GoTo/Management Of/ Message Priorities) can be read from the scimessages attribute of the test classes.
With this help you can get about 60% of all errors.

D3 Graph Example Using In Memory Object

This seems like it should be simple, but I have spent literally hours without any success.
Take the D3 graph example at http://bl.ocks.org/mbostock/950642. The example uses a local file called graph.json. I have set up a Rails app to serve a similar graph, however I don't want to write a file of the JSON. Rather, I generate the nodes and links into an object such as:
{"nodes":[{"node_type":"Person","name":"Damien","id":"damien_person"}, {"node_type":"Person","name":"Grant","id":"grant_person"}}],
"links":[{"source":"damien_person","target":"grant_person","label":"Friends"}}
Now when I render the D3, I need to update the call d3.json("graph.json", function(json) {...}); to reference my in-memory object rather than the local file (or url). However, everything I've tried breaks my html/javascript. For example I tried setting the var dataset = <%= raw(#myInMemoryObject) %>;, and that works for assignment (I did an alert on the dataset), however I can't get the D3 code to use it.
How can I replace the d3.json call in order to use my in-memory object?
Thank you,
Damien
Your idea of using, for example, var dataset = <%= raw(#myInMemoryObject) %>; is the right way to go but you need to prep your object to be in the right format.
The nodes specified in the links need to either be numeric references to nodes in the nodes array eg. 0 for first, 1 for second
var json ={
"nodes":[{"name":"Damien","id":"a"}, {"name":"Bob","id":"b"}],
"links":[{"source":0, "target":1,"value":1}]
}
or links to the actual objects which make the nodes themselves:
var a = {"name":"Damien","id":"a"};
var b = {"name":"Bob","id":"b"}
var json ={
"nodes":[a,b],
"links":[{"source":a,"target":b,"value":1}]
};
Relevant discussion is here: https://groups.google.com/forum/?fromgroups=#!topic/d3-js/LWuhBeEipz4
Example here: http://jsfiddle.net/5A9eV/1/