Why we are unable to evaluate comprehension if we have defined it inside a rule body in OPA? - open-policy-agent

The following is my sample code: https://play.openpolicyagent.org/p/oyY1GOsYaf
Here when I try to evaluate names array, it is showing:
error occurred: 1:1: rego_unsafe_var_error: var names is unsafe
But when I define the same comprehension outside the allow rule definition : https://play.openpolicyagent.org/p/Xv0cF7FM8b, I am able to evaluate the selection
[
"smoke",
"dev"]
could someone help me to point out the difference and if I want to define the comprehention inside the rule is there any syntax I need to follow? Thanks in advance
Note: I am getting the final output as expected in both cases, only issue is with the names array evaluation.

The way the Rego Playground generates a query when evaluating a selection is much more simplistic than one might assume. A query will be generated from your selected text, without taking into account where in the document that text was selected. This means that even if you select a local variable inside a rule body, the query will simply contain that variable name (names, in your case); which will be perceived as a reference to a top-level variable in the document's body, even though a rule-local variable was selected. This is why your first sample returns an error, as there is no top-level variable names in the document; whereas the second sample does, and therefore succeeds.
You can test this quirk by selecting and evaluating the word hello on line 3 here: https://play.openpolicyagent.org/p/n5OPoFnlhx.
package play
# hello
hello {
m := input.message
m == "world"
}
Even though it's just part of a comment, it'll evaluate just as if you had selected the rule name on line 5.

Related

Lua Pattern matching only returning first match

I can't figure out how to get Lua to return ALL matches for a particular pattern match.
I have the following regex which works and is so basic:
.*\n
This just splits a long string per line.
The equivelent of this in Lua is:
.-\n
If you run the above in a regex website against the following text it will find three matches (if using the global flag).
Hello
my name is
Someone
If you do not use the global flag it will return only the first match. This is the behaviour of LUA; it's as if it does not have a global switch and will only ever return the first match.
The exact code I have is:
local test = {string.match(string_variable_here, ".-\n")}
If I run it on the above test for example, test will be a table with only one item (the first row). I even tried using capture groups but the result is the same.
I cannot find a way to make it return all occurrences of a match, does anyone know if this is possible in LUA?
Thanks,
You can use string.gmatch(s, pattern) / s:gmatch(pattern):
This returns a pattern finding iterator. The iterator will search through the string passed looking for instances of the pattern you passed.
See the online Lua demo:
local a = "Hello\nmy name is\nSomeone\n"
for i in string.gmatch(a, ".*\n") do
print(i)
end
Note that .*\n regex is equivalent to .*\n Lua pattern. - in Lua patterns is the equivalent of *? non-greedy ("lazy") quantifier.

Dealing with read no parse error for lists

Hello can someone please explain me how can you deal with failed computations (in our case parsings) in Haskell when performed in a list,retrieving the successful elements?
The error i get is
main: Prelude.read: no parse and that stops all the list from being processed
I am using a forM over a collection of Text , and for each element i am using a read::String->Double for the result value.
Currently the parsing fails at the first element and i can not parse the remaining elements.How can i make single elements "fail-able" but still get partial results ( for the elements of the list that could be parsed) ?
Example :Input: ["asta","1.23","2.44"]
Desired Output:[1.23,2.44]
import qualified Data.Text as T
parseDfile::[T.Text]->IO [Maybe Double]
parseDfile []=do
return [Nothing]
parseDfile lines = forM lines $ \line ->
do
Prelude.putStrLn ("line value:"++(T.unpack line))
let value = (read::String->Double) . T.unpack $ //fails here for first element
print .show $ value
return (Just value)
P.SDo i have to define a method using the Maybe monad separately only for that one line of code ?
The Text.Read library also has a function called readMaybe that returns a Maybe a instead of just an a like read does.
In the case that you're not sure whether or not a string can be parsed, you clearly want a Maybe a. Now you need to deal with the Maybe though, however the Maybe monad has tons of functions that do exactly what you need.
For more complicated parsing you could look into the Haskell ParseLib which is really good. However it might be a little overkill if you're not trying to parse more than your example.

FitNesse: Variable assignment and simple arithmetic

According to the user guide it is possible to assign values to variables and then perform simple arithmetic.
Imagine I have fixture designed to take an element on the page and extracting the numerical value as a Double (i do this now using the HSAC Slim BrowserTest fixture and my own code)
|script |numbers extraction |
|$testval1=|numeric value of |element1 | |
|$testval2=|numeric value of |element2 | |
Running this gives me something like:
|script |numbers extraction |
|$testval1<-[20.04]|numeric value of |element1 ->[€ 20,04] | |
|$testval2<-[5.1] |numeric value of |element2 ->[€ 5,1] | |
Now say I want to compare the sum of the two doubles with the numeric value of a third element:
|script|numbers extraction |
|check |numeric value of |element3|{=${ ${testval1} + ${testval2} =}|
No matter what combination of parentheses and dollar-signs I use in the last cell, I always get 'invalid expression'.
${= $testval1 + $testval2 =} invalid expression: $testval1 + $testval2
{${=$testval1 + $testval2 =}} {invalid expression: $testval1 + $testval2}
${=${testval1} + ${testval2} =} [invalid expression: undefined variable: testval1 + undefined variable: testval2]
${= !-$testval1-! + !-$testval2-! =} invalid expression: $testval1 + $testval2
${= !-${testval1}-! + !-${testval2}-! =} invalid expression: ${testval1} + ${testval2}
Running the last line (without parenthesis around testval1 and testval2) returns:
|check|numeric value of|element3 ->[€ 25.14]| [25.14] expected [invalid expression: $testval1->[20.04] + $testval2->[5.1]] |
Unfortunately you can can't do what you are looking for. The variables you assign the value of the elements to are actually SLIM symbols, and not variables at the wiki level. If you scroll a bit down on the user guide page you linked to in the question you will find a section called "Difference between variables and SLIM symbols":
Variables are evaluated at render time, before the test executes. This allows for values to be set based on page hierarchy and other things that are purely inputs to the tests.
Symbols only exist at execution time. They can be changed at runtime, so are distinct from variables, which cannot.
I find the three types of variables in FitNesse/SLIM are confusing to people and their different usage, syntax and possibilities cause many issues. My understanding is:
Markup variables (aka wiki variables). For instance ${myVar}, defined using !define. They get their value at page render time, so even before a test is started, so you see their value when you browse to a wiki page, and only in the page's source do you see it is a variable. These can be used in markup expressions, which is what you are trying to do in the question.
Scenario parameters. For instance #{myVar} (or #myVar), defined in the first row of a SLIM scenario table. These are the 'formal parameters' to the scenario, which get their actual value based on the invocation of the scenario (i.e. each usage of the scenario, either from a script table, other scenario or row in a decision table defines their value). They get their value at the start of a test, before its first action is performed. You see the variable when you look at the scenario table that defines it. (When you use the 'table template' table type defined by hsac-fitnesse-plugin (which is included in hsac-fitnesse-fixtures project baseline) you don't need to define the variable names in the first row of the table, they are automatically found based on their occurrence (e.g. #{myVar}) inside the table.)
SLIM symbols. For instance $myVar, they are assigned their value using $myVar=. These are 'runtime variables' that get their value during test execution, they are global to a test suite and their value might be changed during test execution. These are the only kind of variables that can get their value from a property obtained from the 'system under test', and they are the variables you are using in your question's tables. They are actually references to objects inside the SLIM process so fixtures might change the internal state of the object the variable refers to, without this change showing in the wiki representation of the variable (which is just the object's toString() result at time of last assignment).
P.S. The conversion of a string to a double does not require a custom fixture (like your numbers extraction) when you using the hsac-fitnesse-fixtures. You could just use the convert to double method of the library's string fixture.
You seem to be using browser test, this is an HSAC installation I take it? Please mention this in the question as HSAC is a FitNesse fixture.
Anyway, removing the curly brackets should do the trick. With curly brackets it is expecting a global variable, those that are implemented using !define var {foo}
When using variables that are locally defined such as with |$bar=|value of|foo| have to be called in the test using the variable without curly brackets.
|$bar=|value of|foo|
|enter|$bar|as|inputField|
Find more stuff on HSAC usage here: https://github.com/fhoeben/hsac-fitnesse-fixtures/wiki/2.-Slim-Fixtures
Sidenote:
Then there are also table templates that use #var or #{var}, where the use of #{var} is preferred because #{var} will look for the column var and #var will accept a column v or va, if you happen to implement that. Using curly brackets here ensures the full variable name is used.

How to write an array into a text file in maxima?

I am relatively new to maxima. I want to know how to write an array into a text file using maxima.
I know it's late in the game for the original post, but I'll leave this here in case someone finds it in a search.
Let A be a Lisp array, Maxima array, matrix, list, or nested list. Then:
write_data (A, "some_file.data");
Let S be an ouput stream (created by openw or opena). Then:
write_data (A, S);
Entering ?? numericalio at the input prompt, or ?? write_ or ?? read_, will show some info about this function and related ones.
I've never used maxima (or even heard of it), but a little Google searching out of curiousity turned up this: http://arachnoid.com/maxima/files_functions.html
From what I can gather, you should be able to do something like this:
stringout("my_new_file.txt",values);
It says the second parameter to the stringout function can be one or more of these:
input: all user entries since the beginning of the session.
values: all user variable and array assignments.
functions: all user-defined functions (including functions defined within any loaded packages).
all: all of the above. Such a list is normally useful only for editing and extraction of useful sections.
So by passing values it should save your array assignments to file.
A bit more necroposting, as google leads here, but I haven't found it useful enough. I've needed to export it as following:
-0.8000,-0.8000,-0.2422,-0.242
-0.7942,-0.7942,-0.2387,-0.239
-0.7776,-0.7776,-0.2285,-0.228
-0.7514,-0.7514,-0.2124,-0.212
-0.7168,-0.7168,-0.1912,-0.191
-0.6750,-0.6750,-0.1655,-0.166
-0.6272,-0.6272,-0.1362,-0.136
-0.5746,-0.5746,-0.1039,-0.104
So I've found how to do this with printf:
with_stdout(filename, for i:1 thru length(z_points) do
printf (true,"~,4f,~,4f,~,4f,~,3f~%",bot_points[i],bot_points[i],top_points[i],top_points[i]));
A bit cleaner variation on the #ProdoElmit's answer:
list : [1,2,3,4,5]$
with_stdout("file.txt", apply(print, list))$
/* 1 2 3 4 5 is then what appears in file.txt */
Here the trick with apply is needed as you probably don't want to have square brackets in your output, as is produced by print(list).
For a matrix to be printed out, I would have done the following:
m : matrix([1,2],[3,4])$
with_stdout("file.txt", for row in args(m) do apply(print, row))$
/* 1 2
3 4
is what you then have in file.txt */
Note that in my solution the values are separated with spaces and the format of your values is fixed to that provided by print. Another caveat is that there is a limit on the number of function parameters: for example, for me (GCL 2.6.12) my method does not work if length(list) > 64.

node label/key in XText when translating from grako

In grako one can use the following name:e to add the result of e to the AST using name as key. For example
var_def
=
var+:ID {',' var+:ID}*
What would be a good translation of this to Xtext?
I tried
var_def:
var=ID (',' var=ID)*;
which is not failing, but is raising the following warning
Multiple markers at this line
- The possibly assigned value of feature 'var' may be overridden
by subsequent assignments.
- This assignment will override the possibly assigned value of
feature 'var'.
I think I am trying to mimic the name behavior, but do not have much success.
With your solution only the last ID will be available in the AST. I assume var should be a multi-valued feature holding all IDs, not only the last one. This can be expressed as
var_def:
var+=ID (',' var+=ID)*;
In the resulting AST var is a list of IDs.

Resources