advanced ffl: conditional expression then-expressions activation - conditional-statements

Here is a snippet from https://github.com/anura-engine/anura/blob/55bc02244f0faba5e0831578a3c1c9a82e7bf569/src/formula_function.cpp#L923-L931:
FUNCTION_DEF(if, 2, -1, "if(a,b,c)")
const int nargs = static_cast<int>(NUM_ARGS);
for(int n = 0; n < nargs-1; n += 2) {
const bool result = EVAL_ARG(n).as_bool();
if(result) {
return EVAL_ARG(n+1);
}
}
As we can see, if there is more than one condition evaluating as true, only the then-expression corresponding to the first condition evaluating as true is returned.
Actually, only the first condition evaluating as true gets to be evaluated as true.
Meta discussing FFL, (1) would it make sense that the expression should evaluate all the conditions and return a list of all then-expressions corresponding to true conditions, as long as the inside of the whole conditional expression is free from execution triggers (bind_command, ;, etc.)? Also (2) does this exist already (obviously with a different signature)?

I think it could make sense for the if function to evaluate and return passing. I've only seen the 2- and 3-parameter if functions used in the wild, so I can't comment on the n-parameter version as I just found out about it. (It seems to be equivalent to "if, else if, …, else". Hunh.)
The closest syntax I know of for the list of condition/statements is something like:
on_create: "filter([
true and debug('cmd 1'),
false and debug('cmd 2'),
true and debug('cmd 3'),
], value)",
This will print 'cmd 1' and 'cmd 3' to screen.
This works because and short-circuits, and only returns the first thing to pass or the last thing to fail. The filter() call is required only if you want to use true and false, otherwise you can use true and null and drop filter(). Note that you can also use ; with this construct, I think it evaluates to a command sequence which you can use and process like a normal command. For example:
on_create: "filter([
true and debug('cmd 1'),
false and (debug('cmd 2'); debug('cmd 3')),
true and (debug('cmd 4'); debug('cmd 5')),
], value)",
Prints 'cmd 1', 'cmd 4', and 'cmd 5' to screen.
This is equivalent to:
on_create: "[
if(true, debug('cmd 1')),
if(false, debug('cmd 2'); debug('cmd 3')),
if(true, debug('cmd 4'); debug('cmd 5')),
]",
Which also prints 'cmd 1', 'cmd 4', and 'cmd 5' to screen. If you need to eliminate the null elements from the list, filter can be used as in the first example.

What you want is a chain of if statements. That is already easily achieved by putting multiple if statements in a row. And it is very clear and common to see in other languages. Having a custom structure for this would thus be redundant and only reduce clarity.
On the other hand, a structure to implement repeated else-if's is very useful to reduce nesting. (Excessive nesting causes readability issues and creates opportunities for confusion.)
if condition, then action
else-if condition, then action (optional)
...
else-if condition, then action (optional)
else action (optional)

Related

Multiple MySQL queries returning undefined when outputting value

I am running two database queries to retrieve data that I will outputting in a message embed. The queries are returning the proper rows when I just dump the entire result into the console. However, whenever I try to output the actual value for one of the rows, it displays as undefined in the message embed.
From what I've found based on examples, rows[0].somevalue should be outputting the correct results.
let mentionedUser = message.mentions.members.first();
let captainUser = client.users.find(user => user.id == `${mentionedUser.id}`);
con.query(`SELECT * FROM captains WHERE id = '${mentionedUser.id}';SELECT * FROM results WHERE captain = '${captainUser.username}'`, [2, 1], (err, rows) => {
if(err) throw err;
console.log(rows);
const infoEmbed = new Discord.RichEmbed()
.setColor("#1b56af")
.setAuthor('Captain Information', client.user.displayAvatarURL)
.setThumbnail('https://i.imgur.com/t3WuKqf.jpg')
.addField('Captain Name', `${mentionedUser}`, true)
.addField('Cap Space', `${rows[0].credits}`, true) // Returns undefined
message.channel.send(infoEmbed);
});
This is the console result
[ [ RowDataPacket {
id: '91580646270439424',
team_name: 'Resistance',
credits: 85,
roster_size: 2 } ],
[ RowDataPacket { id: 'Sniper0270', captain: 'BTW8892', credits: 10 },
RowDataPacket { id: 'Annex Chrispy', captain: 'BTW8892', credits: 5 } ] ]
In the code posted above, the expected output of rows[0].credits should output 85. No error codes are present, it just displayed as "undefined" in the message embed.
You are executing two queries inside a single query call. It looks like the mysql library returns an array of arrays in this scenario where the first value is the result of the first query and the second is the result of the second query. This is non standard. Normally you would either execute each query in its own query call or you would use a union to join the two queries into a single resultset.
this is not the practical way to send query request , as query is a single statement excluding the bulk update , you cannot execute two different query using a single con.query , it is not a proper way. execute them separately

SailsJS, Waterline populate records with select

I have looked at a lot of old SO questions which have broken GitHub links and SailsJS Trello, however I am still unclear.
Is it possible, to populate a field (one-to-one relationship) in SailsJS and return only specific fields (either via select or omit).
await Document.find({id: id}).populate('createdBy', {select: ['name']})
I am getting
UsageError: Invalid populate(s).
Details:
Could not populate `createdBy` because of ambiguous usage. This is a singular ("model") association, which means it never refers to more than _one_ associated record. So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association
, since it generally wouldn't make any sense. But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!
(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense. This usage will be supported in a future version of Waterline.)
Here's what was passed in:
{ select: [ 'name' ] }
In models,
createdBy: {
model: 'user',
description: 'Who is this document assigned to'
},
I am using sails 1.1.0, waterline 0.13.5-0
Am I doing this right? Is there a way to do this?
I solved the problem and made a pull request. Since the pull request has not yet been accepted, be careful and use it on your ask.
Go to
node_modules/waterline/lib/waterline/utils/query/forge-stage-two-query.js
Go to this section
// If this is a singular ("model") association, then it should always have
// an empty dictionary on the RHS. (For this type of association, there is
// always either exactly one associated record, or none of them.)
if (populateAttrDef.model) {....}
Change it to:
if (populateAttrDef.model) {
// Tolerate a subcriteria of `{}`, interpreting it to mean that there is
// really no criteria at all, and that we should just use `true` (the
// default "enabled" value for singular "model" associations.)
if (_.isEqual(query.populates[populateAttrName], {})) {
query.populates[populateAttrName] = true;
}
// Otherwise, this simply must be `true`. Otherwise it's invalid.
else {
if (query.populates[populateAttrName] !== true && (_.isUndefined(query.populates[populateAttrName].select) && _.isUndefined(query.populates[populateAttrName].omit))) {
throw buildUsageError(
'E_INVALID_POPULATES',
'Could not populate `'+populateAttrName+'` because of ambiguous usage. '+
'This is a singular ("model") association, which means it never refers to '+
'more than _one_ associated record. So passing in subcriteria (i.e. as '+
'the second argument to `.populate()`) is not supported for this association, '+
'since it generally wouldn\'t make any sense. But that\'s the trouble-- it '+
'looks like some sort of a subcriteria (or something) _was_ provided!\n'+
'(Note that subcriterias consisting ONLY of `omit` or `select` are a special '+
'case that _does_ make sense. This usage will be supported in a future version '+
'of Waterline.)\n'+
'\n'+
'Here\'s what was passed in:\n'+
util.inspect(query.populates[populateAttrName], {depth: 5}),
query.using
);
}//-•
else {
query.populates[populateAttrName] = {
select: query.populates[populateAttrName].select? query.populates[populateAttrName].select : undefined,
omit: query.populates[populateAttrName].omit? query.populates[populateAttrName].omit : undefined
};
}
}//>-•
}
This is the pull request to see exactly what you should change:
https://github.com/balderdashy/waterline/pull/1613
When u use One-to-one association u can't use subcriteria like error say.
So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association
U can use customToJSON function on model createdBy to omit data.
customToJSON: function() {
return _.omit(this, ['createdAt', 'updatedAt', 'id'])
}

Filtering dstore collection against an array field

I'm trying to filter a dstore collection by a field that has an array of values. My json data looks like the following (simplified):
[{
user_id: 1,
user_name: "John Doe",
teams: [{team_id: 100, team_name: 'Red Sox'}, {team_id: 101, team_name: 'Buccaneers'}]
},
{
user_id: 2,
user_name: "Fred Smith",
teams: [{team_id: 100, team_name: 'Buccaneers'}, {team_id: 102, team_name: 'Rays'}]
}]
I can do a simple filter against the username field and it works perfectly.
this.dstoreFilter = new this.dstore.Filter();
var results = this.dgrid.set('collection', this.dstore.filter(
this.dstoreFilter.match('user_name',new RegExp(searchTerm, 'i'))
));
How, though, do I construct a filter to show me only those players who play for the Red Sox, for example. I've tried using the filter.contains() method, but I can't find any adequate documentation on how it works. Looking at the dstore code, I see that the filter.contains() method has the following signature: (value, required, object, key), but that's not helping me much.
Any guidance would be much appreciated. Thanks in advance!
You can find documentation on Filtering here.
In your case, .contains() will not work because it is intended to work on values of array type. What you want to filter here is array of objects. Here is a quote from the doc link:
contains: Filters for objects where the specified property's value is an array and the array contains any value that equals the provided value or satisfies the provided expression.
In my opinion, the best way here is to override the filter method where you want to filter by team name. Here is some sample code:
this.grid.set('collection', this.dstore.filter(lang.hitch(this, function (item) {
var displayUser = false;
for(var i=0; i < item.teams.length; i++){
var team = item.teams[i];
if(team.team_name == 'Red Sox'){
displayUser = true;
break;
}
}
return displayUser;
})));
this.grid.refresh();
For each user in the store, if false is returned, it's display is set to false and if true is returned it gets displayed. This is by far the easiest way that I know of to apply complex filtering on dstore.
Some similar questions that you might want to read up: link, link, link

How to check if a key element exists and if present update it?

I am using mule community edition. So no Dataweave. I am consuming a rest service in my application. In the json response from this backend rest service. I need to check if a particular element exists inside muliple multiple elements of an array and wherever it exists I need to update its value.
E.g. (sample)
Input Request : [ { "id" : "1", "item" : "car", "make" : "Tonda" }, { "id" : "1", "item" : "car" } ]
using foreach to iterate array . Inside for each need to do something like below in expression component.
if( payload.make exists) { payload.make = "Tero"; }
But I do not know , how to check "if element exists"" condition. I tried below in expression component
if( payload.make != empty) { payload.make = "Tero"; }
But it did not work and gives error "Execution of the expression failed (org.mule.api.expression.ExpressionRuntimeException)"" for each array element wherever the particular key(make) is not present
inside foreach use the expression: #[payload.containsKey('make')] to check if the json key make exists or not. This will return true or false
Easy and simple!
Ref: https://forums.mulesoft.com/questions/71478/how-to-check-if-a-key-element-exists-and-if-presen.html?childToView=71502#answer-71502
Tested in a flow, if your payload is a single object and not a collection you can do MEL:
#[(payload.?make != empty) ? "EXISTS" : " OPS NO"]
Just change "EXISTS" with your true condition and "OPS NO" with the false one.
According to documentation: https://docs.mulesoft.com/mule-user-guide/v/3.7/mule-expression-language-reference
Null Safety
To access properties in a null safe manner, add the .? operator before one or more objects in a chain. In the following expression, if fieldA is null, the expression evaluates to null instead of a NullPointerException.

Dojo Enhanced grid Set Filter does not retains filter condition applied

In my scenario I have set enhanced grid with a filter query (values, conditions, columns and logicany or logicall.
But it works fine with below code except "isempty" condition. On edit or update the filter applied, it does not retains the filter condition applied, instead it takes the first option from condition drop down list.
Here is the code:
grid.setFilter([{
type: 'string',
column: 1,
condition: 'startsWith',
value: 'XXX'
}, {
type: 'number',
column: 2,
condition: 'lessthan',
value: 100
}], 'logicany');
}