How to structure message and update functions with a variable number of UI elements in Elm? - elm

Greetings StackOverflow!
Suppose I have an Elm app with a variable number of text input fields. I'd like to reflect the state of these input fields in the model.
Model and view are easy enough: View just has a Array String field in it somewhere.
The view is then computed simply by calling List.map (HTML input ...) on that list of strings.
However, I'm a bit lost how to do the update function and message type.
The message could be somethign like this:
type Msg = InputFieldUpdated Int String
Here, the Int refers to the position in the Array that the string to be updated has. However, if I do it this way, I can create messages that refer to non-existant array positions simply by setting the Int to something that is out of range.
For a fixed number of input elements, one can solve this problem very elegantly by simply using a union type with a different value for each input, but what about my situation? In the domain of "making impossible states impossible", is there some trick for that that I'm missing?

However, if I do it this way, I can create messages that refer to non-existant array positions simply by setting the Int to something that is out of range.
According to the documentation of Array.set, the array stays untouched if the index is out of range.
Please, have a look at this ellie-app example. It mostly models the problem, that you've described. Array of elements is rendered and the elements can be added dynamically:
view : Model -> Html Msg
view model =
div []
[ div [] (toList (Array.indexedMap viewElement model.elements))
, button [ onClick Add ] [ text "Add" ]
]
In order to update a particular element, you need to get it by index. Since the type of the result from Array.get is Maybe a, type system will force you to process all the cases (when the element exists and doesn't):
Increment index ->
case get index model.elements of
Just element ->
{ model | elements = set index (element + 1) model.elements }
Nothing ->
model
The example is just for demonstration purposes, if you don't need the current element, then Array.set function can be safely used.

Related

Index return "data" field entirely in fauna db

I am trying to create an index that returns entire data object of the documents in a collection;
here is the code:
CreateIndex({
name: "users_by_data",
source: Collection("users"),
values: { field: ['data'] }
})
but after creation it says: Values Not set (using ref by default)
If I specifically define fields (separately by their name), it will behave as expected, but data isn't working. the question is:
Is it impossible (e.g. for performance reasons) or am I doing it wrong?
side note: I am aware that I can do Lambda function on Paginate and achieve similar result, but this question specifically is about the Index level;
You can currently index regular values (strings, numbers, dates, etc) and you can index an array which will more or less 'unroll' the array into separate index entries. However, what you are trying, indexing an object is not possible at this point. An object (like data) will be ignored if you try to index it.
Currently, you have two options:
as you mentioned, using Map/Get at query time.
listing all values of the data object in the index since you can select specific values of an object in the index (which is however less flexible if new attributes arrive later on in the object)
We intend to support indexing of objects in the future, I can't provide an ETA yet though. There is a feature request on our forums as well that you can vote up: https://forums.fauna.com/t/object-as-terms-instead-of-scalar-s/628
You're going to want to use the Select function on the Ref you get back from the Index if you only want the data field back.
For an individual document, you can do something like this
Select( "data",
Get(
Match(
Index("yourIndexName"),
**yourIndexTerm // Could point to String/Number/FQL Ref
)
)
)
For a list of documents, you can use Paginate as you said but you can still pull the data property out of each document
Map(
Paginate(
Match(
Index("yourIndexName"),
**yourIndexTerm // Could point to String/Number/FQL Ref
)
),
Lambda("doc", Select("data", Get(Var("doc"))))
)

BACnet deserialization: How do I know if a new list elements starts

I'm implementing a generic BACnet decoder and came across the following question, of which I can't seem to find the answer within the BACnet standard. The chapter "20.2.1.3.2 Constructed Data" does not answer my question, or I might not fully understand it.
Let's assume I have a List (SEQUENCE OF) with elements of type Record (SEQUENCE).
Said record has 4 fields, identified by context tag, where field 0 and 1 are optional.
I further assume that the order, in which those fields are serialized, can be arbitrary (because they're identified by their context tags).
The data could look like that (number indicates field / column):
[{ "3", "0", 2" }, {"1", "2", "3"}]
Over the wire, the only "structure information" I assume I get are the open / close tags for the list.
That means:
Open Tag List
ctxTagColumn3, valueColumn3,
ctxTagColumn0, valueColumn0,
ctxTagColumn2, valueColumn2,
ctxTagColumn1, valueColumn1,
ctxTagColumn2, valueColumn2,
ctxTagColumn3, valueColumn3
Close Tag List
How do I know, after I've read the last column data ("2") of my first list item, that I must begin decoding the second item, starting with a value for column "1"?
Which of my assumptions is wrong?
Thank you and kind regards
Pascal
The order of elements of a SEQUENCE is always known and shall not be arbitrarily by definition. Further, not all conceivable combinations are possible to encode. Regarding BACnet, all type definitions shall be decodable universally.
Assuming I understand you correctly; the "order" cannot be "arbitrary"; i.e.:
SEQUENCE = *ordered* collection of variables of **different** types
SEQUENCE OF = *ordered* collection of variables of **same** type
The tag-number for the item (SD) context-tag will be different (/possibly an incremented value/maybe +1) from the containing (PD) context-tag; so you could check for that, or better still if the tag-number value is <= 5 (/'length' value) then it's a SD context-tag for one of your items, rather than a (/the closing) PD context tag (/'type' value) delimiting the end of your items.

Incrementing uniqueID over each List.map iteration

I'm trying to initialise a set of elements with a unique identifier. The elements are part of the initial model.
What I have in mind is a function
initElement: Int -> InputElement -> Output
initElement id element = ...
that adds the given id to the given element. Now I'm iterating over these elements in another function like this:
uid = 0
elementsList = ...
newList = List.map (initElement uid++) elementsList
and I would want this integer uid increased with every iteration over an element by List.map, so that every element gets a unique number assigned. The ++ obviously doesn't work though.
Is this possible, or am I thinking too object-oriented? I'm pretty new to functional programming.
One option is to use List.indexedMap
http://package.elm-lang.org/packages/elm-lang/core/3.0.0/List#indexedMap
It gives you a nice incrementing index as a parameter to your function as first parameter. Which you can then use to modify the incoming uid approriattely

How to use Get command in Monkey talk?

Does anybody know how to use the Get command in monkey talk?
In monkey talk guide only the command is written but no syntax is present.
Here is an example for you,
var x = app.label("label1").get("x","value")
Above line will get the value of label1 and store it in variable x. You can change the second parameter "value" to ".text" or ".size" depending on your needs
since the question is not marked Answered and For the future reference i am answering this.
‘GET’ ACTION RETRIEVES COMPONENT PROPERTY VALUES
Syntax:
ComponenType MonkeyId Get varName propName
Works like an assignment statement (varName= propName)
The default property is “value”
// Get label value currently displayed
Label lastname Get name
// Enter name into input field
Input query EnterText ${name}
// Get the first table item
Table countries Get country items1
// Enter into input field
Input * EnterText ${country}
you can refer this document here, thanqs
I will try to explain using example. Suppose there is a ListView(Table) and you want to scroll till its last item.
//Define a variable
Vars * Define row
//Store size of list in variable row using Get. Check use of "Get" here
Table * Get row size %thinktime=20000
//Now stored variable can be used as per need. here I am using for scrolling
Table * ScrollToRow ${row} %thinktime=2000
Hope it helps you !!

How to use a single NSValueTransformer subclass to toggle the titles of multiple menu items

I would like to make some bindings that toggle item titles in a popup menu based on a single numerical value in a text field. Let me explain:
This is my UI:
I want my menu items to automatically adjust to singular or plural based on the number in the text field. For example, when I type "1" in the box, I want the menu items to be labeled "minute", "hour" and "day". When I type "4", I want the menu items to be labeled "minutes", "hours" and "days".
What I did to date:
I bound the three menu item's labels to the same key path as the text field's value.
I created an NSValueTransformer subclass to interpret the value in the text field and return singular or plural to be used as item titles.
I applied this value transformer to the three bindings.
The issue:
My value transformer can either return singular or plural but it can't set the appropriate string based on the menu item it's applied to.
It looks to me like a value transformer is generic and can't return different values for different destinations. That would mean that to have the three titles change automatically, I would need to have three different value transformers that return the appropriate string for each menu item. That doesn't seem optimal at all.
Ideally I would be able to combine a string stored in the destination menu item (let's say in the item's tag property) with an "s" in the value transformer when the text field's value is larger than one, or something similar that would enable me to use a single value transformer for all the menu items.
Is there something I missed? What would be an ideal solution?
Okay, this is probably not an ideal solution, but something you could consider: if you set your value transformers from your code (and not in IB), you could instantiate 3 different transformers of the same class. You could give your value transformer an ivar NSString *unit (and add something like [[MyValueTransformer alloc] initWithUnit:]) to allow each to return their own string, but you still have to write the value transformer's code only once.
(Also, if you're ever going to consider making your application localizable, simply appending an "s" to create the plurals is not going to work. You could of course add ivars for both NSString *singular and NSString *plural to do that.)
Edit: Wait, I just realized you can register value transformers! If you register them as MyValueTransformerHours and MyValueTransformerMinutes (by manually allocating and initializing them in your code), you can use them from Interface Builder. See also https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ValueTransformers/Concepts/Registration.html#//apple_ref/doc/uid/20002166-BAJEAIEE.