groovy dsl optional keyword - groovy

I'm working on a DSL using groovy, and as i'm new to this language, i'm struggling on something.
i have this code
def from(state1) {
def closure
closure = { sensor ->
[becomes: { signal ->
// someProcess;
[and: closure]
}]
}
[to: { state2 ->
// someProcess
[when: closure]
}]
};
what i do is to read this kind of sentances
from "on" to "off" when "button" becomes "high" and "button2" becomes "high"
the and "button2" becomes "high", is optional. So grammatically, everything works as i wanted to.
the problem is that i wanted to add the possibility to treat or also, like this:
from "on" to "off" when "button" becomes "high" or "button2" becomes "high"
but i don't know how to do that. How can i do to add that, and also the possibility to know if it's and or or to have a control statement and a different process for each
it have been two days that i'm on the problem..
Thanks :)

1st of all, I like your question!
Not knowing what your //someProcess is supposed to do and what the whole use-case is all about (IoT-ish?), you can implement the or operator like that:
...
[to: { state2 ->
[when: closure, whenEither:{ Map conds -> conds.any{ sensor, signal -> 'high' == signal } } ]
}]
then you can write:
from "on" to "off" whenEither button:"high", button2:"high"

Related

Alloy:How to understand the counterexample in the Alloy demo?

I write a strange Alloy demo about "assert" out of curiosity.
Assume there is a "Program", the "Program" has 2 "Varieties", and each "Variety" has a "Value" from "Data" set.
Then I also set a "fact" that all of the "Value" of the "Variety" are "data1".
Finally, I set an "assert" that for all "Program", all of "Value" of the "Variety" in the "Program" are "data1".
I think the "assert" satisfies the "fact", however when I check the "assert", it gives a counterexample, I cannot understand about this, why it has the counterexample?
The code appears as follows:
enum Data{data1,data2}
sig Program{
Var1:Variable,
Var2:Variable
}
sig Variable{
Value:Data
}
fact{
all v:Variable{
v.Value=data1
}
}
assert test{
all p:Program{
all v:(Program->Variable){
p.v.Value=data1
}
}
}
The counterexample is as follows:
I'm a bit confused about your example because the var1 and var2 fields don't seem to be used. But the reason you're getting a counterexample is probably because v can be empty, in which case p.v.Value evaluates to the empty relation, and data1 evaluates to a singleton, so they're not equal.
There are two mistakes in my question, I modify the code, and it is right now.
enum Data{data1,data2}
sig Program{
Var1:Variable,
Var2:Variable
}
sig Variable{
Value:Data
}
fact{
all p:Program{
//In theory, there should be "all v:(Program->Variable)", but Alloy does not support HOL.
//all v:(Program->Variable){
p.Var1.Value=data1
p.Var2.Value=data1
// }
}
}
assert test{
all p:Program{
p.Var1.Value=data1
p.Var2.Value=data2
// And here is another mistake, Var1 and Var2 is only the subset of "all v:(Program->Variable)"
// all v:(Program->Variable){
// p.v.Value=data1
// }
}
}
check test for 10 but 1 Program

Terraform module with repeatable variable

Several resources, e.g. aws_dynamodb_table have repeatable variables. In the case of the aws_dynamodb_table resource, attribute is repeatable which allows you to specify multiple attributes using either of the following syntax
attribute {
name = "UserId"
type = "S"
}
attribute {
name = "GameTitle"
type = "S"
}
attribute {
name = "TopScore"
type = "N"
}
or
attribute = [{
name = "UserId"
type = "S"
}, {
name = "GameTitle"
type = "S"
}, {
name = "TopScore"
type = "N"
}]
I like this interface and want to provide the same flexibility in my modules but I can't seem to find any documentation on how to do it. Is this possible for modules or is it only the built-in resources that can do this.
It looks like that either allows you to provide attribute multiple times as separate maps (which are then merged) or as a list.
You're going to want to take a look at the documentation related to Input Variable Configuration
In particular, you will want to look at the section titled Variable Merging.
I believe you could do something like this for similar behavior (from the docs above, give them a read :P)
foo {
quux="bar"
}
foo {
bar="baz"
}
This would mean foo returns:
{
quux = "bar"
bar = "baz"
}
Hope that helps!

How to get value by name with Erlang struct?

Newbie of Erlang here.
Have Json like this:
{
"ReadCardResultResult":{
"amount":"0",
"balance":"9400",
"Status":1,
"Commands":[
],
"message":"0000000000000000",
"ret":{
"code":0,
"desc":"SUCCESS",
"subReturn":null
},
"transactionId":103979,
"txnInfo":[
{
"infoId":101,
"infoName":"TestName1",
"infoValue":"04432FBAA53080"
},
{
"infoId":102,
"infoName":"TestName2",
"infoValue":""
},
{
"infoId":103,
"infoName":"TestName3",
"infoValue":"9400"
},
{
"infoId":104,
"infoName":"TestName4",
"infoValue":"5"
}
]
}
}
My task is to get specific infoValue out of txnInfo according to infoName. For example: I need to get infoValue with "TestName3", that would be "9400".
So far I narrowed the Json with proplists:get_value(<<"txnInfo">>, ReadCardResultResult). and now I have this:
[{struct,[{<<"infoId">>,101},
{<<"infoName">>,<<"TestName1">>},
{<<"infoValue">>,<<"043A2FBAA53080">>}]},
{struct,[{<<"infoId">>,108},
{<<"infoName">>,<<"TestName2">>},
{<<"infoValue">>,<<"772">>}]},
{struct,[{<<"infoId">>,108},
{<<"infoName">>,<<"TestName3">>},
{<<"infoValue">>,<<"772">>}]},
{struct,[{<<"infoId">>,125},
{<<"infoName">>,<<"TestName4">>},
{<<"infoValue">>,<<>>}]}]
Now, where do I go from here? I'm really stuck on this. Any help would be appreciated.
To efficiently get the first item of a list matching a predicate, you can invert the predicate and use lists:dropwhile/2 (see this answer for more info about that). Other than that, it's just some pattern matching and a case expression:
-module(a).
-compile([export_all]).
main() ->
TxnInfo = [{struct,[{<<"infoId">>,101},
{<<"infoName">>,<<"TestName1">>},
{<<"infoValue">>,<<"043A2FBAA53080">>}]},
{struct,[{<<"infoId">>,108},
{<<"infoName">>,<<"TestName2">>},
{<<"infoValue">>,<<"772">>}]},
{struct,[{<<"infoId">>,108},
{<<"infoName">>,<<"TestName3">>},
{<<"infoValue">>,<<"9400">>}]},
{struct,[{<<"infoId">>,125},
{<<"infoName">>,<<"TestName4">>},
{<<"infoValue">>,<<>>}]}],
WantName = <<"TestName3">>,
case lists:dropwhile(fun({struct, PropList}) -> proplists:get_value(<<"infoName">>, PropList) /= WantName end, TxnInfo) of
[] ->
io:format("no matches~n");
[{struct, PropList} | _] ->
io:format("first match: ~p~n", [proplists:get_value(<<"infoValue">>, PropList)])
end.
Output:
first match: <<"9400">>
If you only care about the first result and want to crash if none is found, you can replace the case with just:
[{struct, PropList} | _] = lists:dropwhile(...),

Knockout Binding with Multiple If statements

I am applying binding on a style and have succeeded in making the background colour change based on two scenarios. At present it says if the status is 'START', make the background #d10000, else make the background #93d667.
style: { background: ManagerStatus() == 'START' ? '#d10000' : '#93d667' }
I would like the following functionality:
If START, make #d10000
else if CONTINUE, make #93d667
else make #f7f7f7
How do I achieve these multiple case statements in Knockout binding?
Regards
Alexandra
Thanks guys. For future reference someone showed me that you can actually have multiple cases in the data-bind attribute:
{background: ManagerStatus() == 'START' ? '#d100000' : (ManagerStatus() == 'CONTINUE' ? '#93d667' : '#f7f7f7')}
Alexandra
You avoid filling your html with conditional logic and create a knockout computed observable in your viewmodel like so:
// or however your viewModel is currently set up.
var viewModel = {
ManagerStatus: ko.observable()
}
viewModel.statusBackground = ko.computed(function() {
status = this.ManagerStatus(),
switch (status) {
case "START": return "#d10000";
case "CONTINUE": return "#93d667";
default: return #f7f7f7;
}
}, viewModel);
html
style: { background: statusBackground }
You could do it by nesting two ternary operator expressions. But doing so it's not a good idea: it's much better to modify your View Model, and include a computed observable that returns the backgraound color. Something like this:
var vm = function() {
var self = this;
self.ManagerStatus = ko.observable();
self.backgroundcolor = ko.computed(function() {
ManagerStatus() == 'START'
? '#d10000' : ManagerStatus() == 'CONTINUE'
? '#93d667' : '#f7f7f7';
});
return self;
};
The binding would be like this:
style: { background: backgroundcolor }
Note that you in this case can use a pure computed, instead of a regular computed.
NOTE: I've shown how to write a nested ternary operator, and you could include it in the binding expression. But, if it looks ugly in a view model definition, it's even more ugly in a binding expression. In fact, I wouldn't write it like this in the view model definition. Much better to use chained if else or switch to make it more readable.

Adding optional clauses to a Groovy DSL

I am developing a DSL with Groovy and I have run into the following problem. I have a method which performs some action on an object with the given parameters.
def run(x) {
[with:{ y -> foo(x,y) }]
}
run "thing" with "param" // evaluates to foo("thing","param")
Now, assume I want to add a default functionality to my DSL:
def runDefault(x) {
foo(x)
}
runDefault "thing" // evaluates to foo("thing")
Is there a way to combine the two into a single function, such that the with "param" part becomes an optional clause? I want to be able to use the DSL as shown below:
run "thing" with "param" // should do foo("thing","param")
run "thing" // should do foo("thing")
if you are able to distinguish both calls in the run-method, you could do something like this:
def run(x) {
switch (x) {
case 'foo':
println "foo($x)"; break;
case 'bar':
[with:{ y -> println "bar($x,$y)" }]; break;
}
}
run "bar" with "param"
run "foo"

Resources