Dictionary with dynamic entries in StringTemplate - stringtemplate

I'm using StringTemplate 4.0.8 with Java.
In the StringTemplate-4 documentation, it says that
Dictionary strings can also be templates that can refer to attributes
that will become visible via dynamic scoping of attributes once the
dictionary value has been embedded within a template.
How exactly do I do that? Can I do something like this:
output(input) ::= "The output is: <aDicitionary.input>"
aDictionary ::= [
"someKey":"someValue",
"someOtherKey":"someOtherValue",
"aCertainKey": **HERE** i want the value to be <input>,
default:"doesnt matter"
]
So that output("someKey") results in The output is: someValue
and output(aCertainKey) results in "The output is: aCertainKey". If so, how exactly would the syntax look like?
I know that I could achieve the same by just not passing an input in one case and then checking if I have an input or not. But that would result in a lot of if's on the Java side which I

To use a dynamic dictionary entry:
output(input) ::= <%The output is: <aDicitionary.(input)>%>
Use no quotes around the template and put input in parentheses to evaluate it.
To have dynamic content in a dictionary (the subject of the cited block):
aDictionary ::= [
"someKey":"someValue",
"someOtherKey":"someOtherValue",
"aCertainKey": {input from scope <inputFromScope>},
default:"doesnt matter"
]
Use braces around the keys and variable (or template) references inside. Now calling
<output(input="aCertainKey", inputFromScope="myInput")>
will output
The output is: input from scope myInput

Related

Splunk: Entry looks like an array but can't be accessed as one

I've got a portion of a log entry which looks like an array, but I can only access it with the {} notation.
For example, I think the path is line.ul-log-data.meta.data[0].foo, but the only way I can access the value is line.ul-log-data.meta.data{}.foo.
I've been experimenting with various multivalue field evaluations but coming up short. For example, when I do an mvcount("line.ul-log-data.meta.data"), it returns 1.
What do I have to do to use the array notation [0] and get that count to return 2?
Splunk uses curly brackets to access JSON arrays because square brackets have a very different, historical function.
Have you tried mvcount("line.ul-log-data.meta.data{}")?

display working out of order in Chez Scheme

I'm using chez 9.5.4 on a Mac.
The following code:
;; demo.ss
(map display (list "this " "is " "weird "))
does this:
$ chez --script demo.ss
weird this is
Why the accidental Yoda?
How do I prevent this?
It works as expected in Chicken Scheme.
As answered by u/bjoli on reddit:
Your code is relying on unspecified behaviour: The order of map is unspecified.
You want for-each.
Chez has no stack overflow (like racket or guile). Doing a right fold with map means no (reverse ...) At the end. It is faster, except in some continuation-heavy code.
Schemes without the expanding stack optimization all do a left fold. Like chicken.
The short answer is that this is just what map does.
According to the r7rs-small specification, on page 51 of https://small.r7rs.org/attachment/r7rs.pdf :
The dynamic order in which proc is applied to
the elements of the list s is unspecified.
That's because map is intended for transforming lists by applying a pure function to each of their elements. The only effect of map should be its result list.
As divs1210 quotes u/bjoli in pointing out, Scheme also defines a procedure that does the thing you want. In fact, for-each is described on the very same page of the r7rs-small pdf! It says:
The arguments to for-each are like the arguments to map,
but for-each calls proc for its side effects rather than for
its values. Unlike map, for-each is guaranteed to call proc
on the elements of the list s in order from the first ele-
ment(s) to the last, and the value returned by for-each
is unspecified.

Is it possible to preserve variable names when writing and reading term programatically?

I'm trying to write an SWI-Prolog predicate that applies numbervars/3 to a term's anonymous variables but preserves the user-supplied names of its non-anonymous variables. I eventually plan on adding some kind of hook to term_expansion (or something like that).
Example of desired output:
?- TestList=[X,Y,Z,_,_].
> TestList=[X,Y,Z,A,B].
This answer to the question Converting Terms to Atoms preserving variable names in YAP prolog shows how to use read_term to obtain as atoms the names of the variables used in a term. This list (in the form [X='X',Y='Y',...]) does not contain the anonymous variables, unlike the variable list obtained by term_variables, making isolation of the anonymous variables fairly straightforward.
However, the usefulness of this great feature is somewhat limited if it can only be applied to terms read directly from the terminal. I noticed that all of the examples in the answer involve direct user input of the term. Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input? That is, is there some way to 'write' a term (preserving variable names) to some invisible stream and then 'read' it as if it were input from the terminal?
Alternatively... Perhaps this is more of a LaTeX-ish line of thinking, but is there some way to "wrap" variables inside single quotes (thereby atom-ifying them) before Prolog expands/tries to unify them as variables, with the end result that they're treated as atoms that start with uppercase letters rather than as variables?
You can use the ISO core standard variable_names/1 read and write option. Here is some example code, that replaces anonymous variables in a variable name mapping:
% replace_anon(+Map, +Map, -Map)
replace_anon([_=V|M], S, ['_'=V|N]) :- member(_=W, S), W==V, !,
replace_anon(M, S, N).
replace_anon([A=V|M], S, [A=V|N]) :-
replace_anon(M, S, N).
replace_anon([], _, []).
variable_names/1 is ISO core standard. It was always a read option. It then became a write option as well. See also: https://www.complang.tuwien.ac.at/ulrich/iso-prolog/WDCor3
Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.25)
?- read_term(X,[variable_names(M),singletons(S)]),
replace_anon(M,S,N),
write_term(X,[variable_names(N)]).
|: p(X,Y,X).
p(X,_,X)
To use the old numbervars/3 is not recommended, since its not compatible with attribute variables. You cannot use it for example in the presence of CLP(FD).
Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input?
if you want to get variable names from source files you should read them from there.
The easiest way to do so using term expansion.
Solution:
read_term_from_atom(+Atom, -Term, +Options)
Use read_term/3 to read the next term from Atom.
Atom is either an atom or a string object.
It is not required for Atom to end with a full-stop.
Use Atom as input to read_term/2 using the option variable_names and return the read term in Term and the variable bindings in variable_names(Bindings).
Bindings is a list of Name = Var couples, thus providing access to the actual variable names. See also read_term/2.
If Atom has no valid syntax, a syntax_error exception is raised.
write_term( Term ) :-
numbervars(Term, 0, End),
write_canonical(Term), nl.

StringTemplate4 - Storing attribute value in variable

I am injecting an attribute into my StringTemplate4 template which has multiple levels of sub-attributes.
As I work through the template outputting various elements of it I need to refer to attributes quite far down in the nesting at differing points, leading to the template quite often doing multiple references such as...
attribute.subattribute.subattribute2.finalattribute1
attribute.subattribute.subattribute2.finalattribute2
Is there a way in StringTemplate4 to store the subattribute2 in a "Variable" that I could then refer to instead to tidy up the logic somewhat?
Any help would be greatly appreciated :)
You could use a helper template:
foo(attribute) ::= <<
<helper(attribute.subattribute.subattribute2)>
>>
helper(sub) ::= <<
<sub.finalattribute1>
<sub.finalattribute2>
>>

Yaml-cpp parser doesn't handle key:value fragment correctly

today I found following strange behavior in yaml-cpp library.
Following yaml fragment:
- { a: b }
is correctly parsed as key:value element with key=a and value=b. But when I updated fragment to this:
- { a:b }
fragment is evaluated as scalar value "a:b".
Is this correct behavior? And is there a simply way how to force parser to evaluate this fragment as key:value ?
Thanks!
This is correct behavior. From the YAML spec:
Normally, YAML insists the “:” mapping value indicator be separated from the value by white space. A benefit of this restriction is that the “:” character can be used inside plain scalars, as long as it is not followed by white space. This allows for unquoted URLs and timestamps. It is also a potential source for confusion as “a:1” is a plain scalar and not a key: value pair.
...
To ensure JSON compatibility, if a key inside a flow mapping is JSON-like, YAML allows the following value to be specified adjacent to the “:”. This causes no ambiguity, as all JSON-like keys are surrounded by indicators.
For example, you could write:
- { "a":b }
However, as they point out, this isn't very readable; stick with putting a space after the colon.