Assume I have:
visit(p) {
case ...
default:
println("This should not happen. All elements should be catched. Check: <x>");
};
How can I print out (in this case as x) what could not be matched?
I tried:
x:default:
\x:default:
default:x:
\default:x:
Tx,
Jos
We have a library named Traversal that allows you to get back the context of a match. So, you can do something like this:
import Traversal;
import IO;
void doit() {
m = (1:"one",2:"two",3:"three");
bottom-up visit(m) {
case int n : println("<n> is an int");
default: {
tc = getTraversalContext();
println("Context is: <tc>");
println("<tc[0]> is not an int");
if (str s := tc[0]) {
println("<s> is a string");
}
}
}
}
tc is then a list of all the nodes back to the top of the term -- in this case, it will just be the current value, like "three", and the entire value of map m (or the entire map, which will also be a match for the default case). If you had something structured as a tree, such as terms formed using ADTs or nodes, you would get all the intervening structure from the point of the match back to the top (which would be the entire term).
For some reason, though, default is matching the same term multiple times. I've filed this as bug report https://github.com/cwi-swat/rascal/issues/731 on GitHub.
You could also try this idiom:
visit(x) {
case ...
case ...
case value x: throw "default case should not happen <x>";
}
The value pattern will catch everything but only after the others are tried.
Related
I have identified 3-5 keywords for every requirement in module-A. Each keyword is separated by a comma. Now I want to search every requirement in module-B to see which of them have words that match each of the key words.
Not sure exactly what you're looking for. You might have to specify if none of these solutions I'm about to propose are exactly what you're looking for.
If you're trying to create a filter which displays only objects with those keywords in your current view, you can create an advanced filter by first going to filter (Tools > Filter > Define) and then select the Advanced button on the bottom left of the filter menu that appears.
At this point you can create custom rules for the filter. I would just create an individual rule for each word with the following definition:
Attribute: Object Text
Condition: contains
Value: <insert word here>
Match Case: uncheck
Regular Expression: uncheck
Then select the Add button to add the rule to the list of available rules in the Advanced Options.
At this point you can select multiple rules in the list of available rules and you can AND/OR these rules together to create a custom filter for the view that you want.
So that's for if you're trying to create a custom view with just objects containing specific words.
If you're talking about writing DXL code to automatically spit out requirements that have a particular word in it. You can use the something that looks like this:
Object o
String s
int offset, len
for o in entire (current Module) do
{
if (isDeleted(o)) continue
s = o."Object Text"""
if findPlainText(s, "<insert word here>", offset, len, false)
{
print identifier(o) // or replace this line with however you want to display object
}
}
Hope this is helpful. Cheers!
Edit:
To perform actions on a comma separated list, one at a time, you can use a while loop with some sort of search function that cuts off words one at a time.
void processWord (string someWord, Module mTarget, Object oSource)
{
Object oTarget
string objID = identifier(oSource)
for oTarget in mTarget do
{
if (<someWord in oTarget Object Text>) // edit function as necessary to do this
{
if (oTarget."Exists""" == "")
oTarget."Exists" = objID
else
oTarget."Exists" = oTarget."Exists" "," objID
}
}
}
int offset, len
string searchCriteria
Module mSource = read("<path of source module>", true)
Module mTarget = edit("<path of target module>", true)
Object oSource
for oSource in mSource do // can use "for object in entire(m)" for all objects
{
if (oSource != rqmt) continue // create conditions specific to your module here
searchCriteria = oSource."Search Criteria"""
while (findPlainText(searchCriteria, ",", offset, len, false))
{
processWord(searchCriteria[0:offset-1], mTarget, oSource)
searchCriteria = searchCriteria[offset+1:]
}
}
processWord(searchCriteria, mTarget, oSource) // for last value in comma separated list
I am previously working with Netlogo and there are some very good built-in methods that allow me to filter and control the desired agents from the total population. (see: http://ccl.northwestern.edu/netlogo/docs/dictionary.html#agentsetgroup). For instance, I could very easily to command the different class of people agent in a simulation with simple codes like:
ask peoples with [wealth_type = "rich"] [donate money...]
ask peoples with [wealth_type = "poor"] [get money from rich people...]
In Repast, are there list of methods specifically built for easy controlling of agent set?
The equivalent in Repast Simphony Java is to use a Query. Queries apply a predicate to each agent in the Context and returns those that evaluate to true in an iterator. The PropertyEquals query evaluates an agent's property w/r to some value (e.g. "wealth_type" and "rich"). Note that "property" here refers to a Java property, i.e., a getter type method:
String getWealthType() {
return wealthType;
}
where "wealthType" is the name of the property.
As an example, in the JZombies example model, we can query Humans whose energy is equal to 5.
Query<Object> query = new PropertyEquals<Object>(context, "energy", 5);
for (Object o : query.query()) {
Human h = (Human)o;
System.out.println(h.getEnergy());
}
The query() iterator returns all the humans whose energy is equal to 5.
You can get a bit more complicated in the equivalence test by providing your own predicate. For example,
PropertyEqualsPredicate<Integer, Integer> pep = (a, b) -> {
return a * 2 == b;
};
Query<Object> query2 = new PropertyEquals<Object>(context, "energy", 8, pep);
for (Object o : query2.query()) {
Human h = (Human)o;
System.out.println(h.getEnergy());
}
Here, we are checking if the energy * 2 == 8. The predicate is passed the agent's property value in the first parameter and the value to compare against in the second parameter. Given that the predicate returns a boolean, you could also test for inequality, greater than etc.
Simphony has a variety of queries available. See,
https://repast.github.io/docs/api/repast_simphony/repast/simphony/query/package-summary.html
https://repast.github.io/docs/RepastReference/RepastReference.html#_repast_model_design_fundamental_concepts
for more info.
You can also do this in Simphony's ReLogo dialect:
ask (turtles()){
if (wealth_type == "rich") {
donateMoney()
}
if (wealth_type == "poor") {
getMoneyFromRichPeople()
}
}
If you want to just collect the richTurtles you can do (where "it" is the default method to access the individual turtle that is iterated over with findAll):
richTurtles = turtles().findAll{
it.wealth_type == "rich"
}
or with an explicit closure argument:
richTurtles = turtles().findAll{x->
x.wealth_type == "rich"
}
I have a nested JSON file, consisting of keys and values which are string only. But the structure of the JSON file is not fixed, so sometimes it could be nested 3 levels, sometimes only 2 levels.
I wonder how i could serialize this in strict mode?
"live" : {
"host" : "localhost",
"somevalue" : "nothing",
"anobject" : {
"one" : "two",
"three" : "four",
"five" : {
"six" : "seven"
}
}
}
If i would know the structure of the JSON, i simply would write my own class for it, but since the keys are not fixed, and also the nesting could be into several levels, i really wonder how i cut put such an object into a specific type.
Any help or hints appreciated
I think invariants will serve you well here. First off, it might be helpful to know that you can type a keyed tree strictly in Hack:
<?hh // strict
class KeyedTree<+Tk as arraykey, +T> {
public function __construct(
private Map<Tk, KeyedTree<Tk, T>> $descendants = Map{},
private ?T $v = null
) {}
}
(It must be a class because cyclic shape definitions are sadly not allowed)
I haven't tried it yet, but type_structures and Fred Emmott's TypeAssert look to also be of interest. If some part of your JSON blob is known to be fixed, then you could isolate the nested, uncertain part and build a tree out of it with invariants. In the limiting case where the whole blob is unknown, then you could excise the TypeAssert since there's no interesting fixed structure to assert:
use FredEmmott\TypeAssert\TypeAssert;
class JSONParser {
const type Blob = shape(
'live' => shape(
'host' => string, // fixed
'somevalue' => string, // fixed
'anobject' => KeyedTree<arraykey, mixed> // nested and uncertain
)
);
public static function parse_json(string $json_str): this::Blob {
$json = json_decode($json_str, true);
invariant(!array_key_exists('anobject', $json), 'JSON is not properly formatted.');
$json['anobject'] = self::DFS($json['anobject']);
// replace the uncertain array with a `KeyedTree`
return TypeAssert::matchesTypeStructure(
type_structure(self::class, 'Blob'),
$json
);
return $json;
}
public static function DFS(array<arraykey, mixed> $tree): KeyedTree<arraykey, mixed> {
$descendants = Map{};
foreach($tree as $k => $v) {
if(is_array($v))
$descendants[$k] = self::DFS($v);
else
$descendants[$k] = new KeyedTree(Map{}, $v); // leaf node
}
return new KeyedTree($descendants);
}
}
Down the road, you'll still have to supplement containsKey invariants on the KeyedTree, but that's the reality with unstructured data in Hack.
The following code prints:
false
false
true
{{a: b}, {a: b}}
code
import "dart:json" as JSON;
main() {
print(JSON.parse('{ "a" : "b" }') == JSON.parse('{ "a" : "b" }'));
print({ "a" : "b" } == { "a" : "b" });
print({ "a" : "b" }.toString() == { "a" : "b" }.toString());
Set s = new Set();
s.add(JSON.parse('{ "a" : "b" }'));
s.add(JSON.parse('{ "a" : "b" }'));
print(s);
}
I am using json and parsing two equivalent objects, storing them in a Set, hoping they will not be duplicated. This is not the case and it seems to be because the first two lines (unexpectedly?) results in false. What is an efficient way to correctly compare two Map objects assuming each were the result of JSON.parse()?
The recommended way to compare JSON maps or lists, possibly nested, for equality is by using the Equality classes from the following package
import 'package:collection/collection.dart';
E.g.,
Function eq = const DeepCollectionEquality().equals;
var json1 = JSON.parse('{ "a" : 1, "b" : 2 }');
var json2 = JSON.parse('{ "b" : 2, "a" : 1 }');
print(eq(json1, json2)); // => true
For details see this answer which talks about some of the different equality classes: How can I compare Lists for equality in Dart?.
This is a difficult one, because JSON objects are just Lists and Maps of num, String, bool and Null. Testing Maps and Lists on equality is still an issue in Dart, see https://code.google.com/p/dart/issues/detail?id=2217
UPDATE
This answer is not valid anymore, see answer #Patrice_Chalin
This is actually pretty hard, as the == operator on Maps and Lists doesn't really compare keys/values/elements to each other.
Depending on your use case, you may have to write a utility method. I once wrote this quick and dirty function:
bool mapsEqual(Map m1, Map m2) {
Iterable k1 = m1.keys;
Iterable k2 = m2.keys;
// Compare m1 to m2
if(k1.length!=k2.length) return false;
for(dynamic o in k1) {
if(!k2.contains(o)) return false;
if(m1[o] is Map) {
if(!(m2[o] is Map)) return false;
if(!mapsEqual(m1[o], m2[o])) return false;
} else {
if(m1[o] != m2[o]) return false;
}
}
return true;
}
Please note that while it handles nested JSON objects, it will always return false as soon as nested lists are involved. If you want to use this approach, you may need to add code for handling this.
Another approach I once started was to write wrappers for Map and List (implementing Map/List to use it normally) and override operator==, then use JsonParser and JsonListener to parse JSON strings using those wrappers. As I abandoned that pretty soon, I don't have code for it and don't know if it really would have worked, but it could be worth a try.
The matcher library, used from unittest, will do this.
in my application I have 2 layers. The first layer is a C legacy exposing cdecl functions that use the "..." syntax for a varying parameter list. The only way I found to call these functions from my .Net layer (the second one) is using the DllImport technics. For example the C function below:
int myFunc(char* name, ...);
looks like that in C#:
[DllImport("MyDll.dll"),
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.Cdecl]
int myFunc(string name, __arglist);
My problem is that sometimes I want to call this function with 2 extra parameters but if one of them is NULL it won't be included in the argument list (my legacy code fails on NULL values). For example I want this call:
int foo(string name, string a, string b)
{
myFunc(name, __arglist(a, b));
}
{
foo("john", "arg1", null);
}
to be interpreted by C as
myFunc("john", "arg1");
Unfortunately doing something like that:
int foo(string name, string a, string b)
{
List<string> args = new List<string>();
if(a != null) args.Add(a);
if(b != null) args.Add(b);
myFunc(name, __arglist(args));
}
{
foo("john", "arg1", null);
}
is interpreted by C like that:
myFunc(name, args);
and not:
myFunc(name, args[0]);
Does anybody have any idea?
How does the C function know which one is the last parameter? It cannot know a priori how many parameters there are. It needs additional information. One common way for functions get the information they need is by parsing the included string parameter to count format specifiers, as in printf. In that case, if the format string only indicates that there is one extra parameter, then the function doesn't know the difference between a call that really had just one extra parameter and a call that had two or a call that had 20. The function should have the self-discipline to only read one parameter, since that's all the format string said there was. Reading more would lead to undefined behavior.
If what I've described is not the way your function works, then there's not much you can do on the calling end to solve it. But if it is how your function works, then there's nothing to do on the calling end, because there's no problem.
Another option, since you indicate that your "legacy code fails on null values," is to fix your legacy code so it doesn't fail anymore.
A third option is to simply write all four possibilities:
if (a != null) {
if (b != null)
return myFunc(name, a, b);
else
return myFunc(name, a);
} else {
if (b != null)
return myFunc(names, b);
else
return myFunc(names);
}
More than two optional parameters, though, and the code starts getting unwieldy.
Try converting your System.List ToArray() before wrapping it in __arglist
myFunc(name, __arglist(args.ToArray()));