Is it possible to get the raw version of a template string in iojs ?
var s = `foo${1+1}bar`
console.log(s); // foo2bar
In the previous example I would like to get the string: foo${1+1}bar
edit1:
My need is to detect whether a template string depends on its context of if is is just a 'constant' string that may contain CR and LF
Is it possible to get the raw version of a template string in iojs ?
No it is not. It's not possible to get the raw representation of the literal, just like there is no way to get the "raw" literal in these cases:
var foo = {[1+1]: 42};
var bar = 1e10;
var baz = "\"42\"";
Note that the term "template string" is misleading (as it may indicate that you could somehow get the raw value of the string (which is also not the case as shown above)). The correct term is "template literal".
My need is to detect whether a template string depends on its context of if is is just a 'constant' string that may contain CR and LF
Seems like a job for a static analysis tool. E.g. you can use recast to parse the source code and traverse all template literals.
For example, the AST representation of `foo${1+1}bar` is:
If such an AST node as an empty expression property, then you know that the value is constant.
There is a way to determine whether a template literal is "static" or "dynamic" at runtime, but that involves changing the behavior of the code.
You can use tagged templates. Tagged templates are functions that get passed the static and dynamic portions of a template literal.
Example:
function foo(template, ...expressions) {
console.log(template, expressions);
}
foo`foo${1+1}bar` // logs (["foo", "bar"], [2]) but returns `undefined`
I.e. if foo gets passed only a single argument, the template literal does not contain expressions. However, foo would also have to interpolate the static parts with the dynamic parts and return the result (not shown in the above example).
Related
How do I convert the data type if I know the Variant.Type from typeof()?
for example:
var a=5;
var b=6.9;
type_cast(b,typeof(a)); # this makes b an int type value
How do I convert the data type if I know the Variant.Type from typeof()?
You can't. GDScript does not have generics/type templates, so beyond simple type inference, there is no way to specify a type without knowing the type.
Thus, any workaround to cast the value to a type only known at runtime would have to be declared to return Variant, because there is no way to specify the type.
Furthermore, to store the result on a variable, how do you declare the variable if you don't know the type?
Let us have a look at variable declarations. If you do not specify a type, you get a Variant.
For example in this code, a is a Variant that happens to have an int value:
var a = 5
In this other example a is an int:
var a:int = 5
This is also an int:
var a := 5
In this case the variable is typed according to what you are using to initialized, that is the type is inferred.
You may think you can use that like this:
var a = 5
var b := a
Well, no. That is an error. "The variable type can't be inferred". As far as Godot is concerned a does not have a type in this example.
I'm storing data in a json file: { variable:[ typeof(variable), variable_value ] } I added typeof() because for example I store an int but when I reassign it from the file it gets converted to float (one of many other examples)
It is true that JSON is not good at storing Godot types. Which is why many authors do not recommend using JSON to save state.
Now, be aware that we can't get a variable with the right type as explained above. Instead we should try to get a Variant of the right type.
If you cannot change the serialization format, then you are going to need one big match statement. Something like this:
match type:
TYPE_NIL:
return null
TYPE_BOOL:
return bool(value)
TYPE_INT:
return int(value)
TYPE_REAL:
return float(value)
TYPE_STRING:
return str(value)
Those are not all the types that a Variant can hold, but I think it would do for JSON.
Now, if you can change the serialization format, then I will suggest to use str2var and var2str.
For example:
var2str(Vector2(1, 10))
Will return a String value "Vector2( 1, 10 )". And if you do:
str2var("Vector2( 1, 10 )")
You get a Variant with a Vector2 with 1 for the x, and 10 for the y.
This way you can always store Strings, in a human readable format, that Godot can parse. And if you want to do that for whole objects, or you want to put them in a JSON structure, that is up to you.
By the way, you might also be interested in ResourceFormatSaver and ResourceFormatLoader.
Answer: it has to do with GString type and "lazy evaluation."
See http://docs.groovy-lang.org/latest/html/documentation/index.html#_string_interpolation for the formal documentation.
See https://blog.mrhaki.com/2009/08/groovy-goodness-string-strings-strings.html for someone's write-up on this.
Firm solution in the code below as commenter said is to explicitly cast it on creation using String targ = "${TARGET_DATA}"
I'm seeing what seems on the surface to be a delayed string interpolation or something in Groovy. I've figured out workarounds for my immediate needs, but the behaviour is a real gotcha, and a potential source for serious bugs...
I strongly suspect it arises from Groovy being a meta-language for Java, and some objects not using the usual string-matching routines.
This was discovered when we were trying to use a string interpolation on some parameter in Jenkins, and checking it against a list of pre-approved values - hence the resulting example below.
Consider this code:
TARGET_DATA= "hello"
data = ["hello"]
targ = "${TARGET_DATA}"
// Case 1: Check for basic interpolated string
if( data.contains(targ) ) {
println "Contained interpolated string"
} else {
println "Interpolation failed"
}
// Case 2: Check to see if using something that actively forces its interpolation changes the variable
println "interpolating targ = ${targ}"
if( data.contains(targ) ) {
println "Contained re-interpolated string"
} else {
println "re-Interpolation failed"
}
// Case 3: Use direct variable assignment
targ = TARGET_DATA
if( data.contains(targ) ) {
println "Contained assigned variable"
} else {
println "Assignment failed"
}
Its output is this:
Interpolation failed
interpolating targ = message: hello
re-Interpolation failed
Contained assigned variable
This indicates that:
In case 1 , the placeholder string is checked for in the list, and fails, as it hasn't been interpolated
In case 2, after forcing the interpreter to perform an interpolation against targ, the content of that variable isn't updated. At this stage, targ still contains a literal placeholder string
In case 3, after assigning the initial variable directly to the target variable, we get a successful match
My guess is that targ literally contains a string starting with a dollar sign, curly brace, and a variable name, etc. This only resolves under certain conditions, like the use of a println , but not in the case of a <list>.contains() which just gets the uninterpolated variable as-is, and does not know during check, to interpolate it.
Using targ = new String("${TARGET_DATA}") does actively interpolate the string however, as the call to function somehow registers as something active.
However this code does interpolate correctly:
TARGET_DATA= "hello"
targ = "${TARGET_DATA}"
def eq(var1) { return var1 == "hello" }
basic_check = eq(targ)
println "${basic_check}" // resolves as true
which means that at some point, the string is interpolated - possibly the == operation has been reimplemented by Groovy to call String's equality function always:
Such that, Groovy re-implemented the String object - and its equality check - but the <list>.contains() function doesn't use that comparator (or it is not caught during script interpretation, due to being compiled code in the Java standard library) and so fails to trigger the interpolation substitution...
Can someone shed some light here please?
targ is of type Gstring, rather than a java String. GString retains the information for how to build itself from the interpolated form.
Because targ isn't a String, it will never pass the equality check required by List.contains, where the List contrains a String.
I'm currently building a small DSL, which needs to specify a set of properties in key=value pairs, however the keys may contain dashes '-' or periods '.' and I can't seem to get it to work.
Boiled down I essentially try passing a Map as a delegate to a closure, but the syntax keeps alluring me.
As an example, consider this:
def map = [:]
map.with {
example1 = 123
//exam-ple2 = 123
//'exam-ple3' = 123
//(exam-ple4) = 123
exam.ple5 = 123
//'exam.ple6' = 123
}
Example 1 is fine, key equals value and easy readable. Examples 2 and 4 are according to the compiler a binary expression and won't compile. Examples 3 and 6 are constant expressions and won't compile. Example 5 will compile, but generate a NPE at runtime.
I can use workarounds like passing the Map as an argument to the closure, which gives me example 3 and 6, but the verbosity of it annoys me.
Does anybody have any ideas how to neatly DSL a property map?
BTW: I call the DSL from java not groovy, so tricks on the parsing side has to be java :)
UPDATE 1 : After the inital comments and answers..
So the script is evaluated by a GroovyShell as a DelegatingScript, where the delegate is a Java object. The closure contains properties from .properties files, that needs to be defined in different context, e.g.
env {
server-name=someHost1
database.name=someHost2
clientName=someHost3
}
The delegating (Java) object would read this block as
public void env(Closure closure) {
Map map = new HashMap();
closure.setDelegate(map);
closure.setResolveStrategy(Closure.DELEGATE_ONLY);
closure.call();
... do something with map...
}
Now the user (i.e. not me) will probably copy from the original property files into the script and change the names, hence I would rather they could do it without having to edit too much as it is bound to cause typos..
As I stated I has also example 3 and 6 covered as well, but yes, Tim, I forgot the implicit it :)
For now I have changed the format to a string, so the DSL writes something like
env '''
server-name=someHost1
database.name=someHost2
clientName=someHost3
'''
That is, using a multi-line string instead of a closure, and then read the string and using a standard java.util.Properties:
public void env(String envString) {
Properties properties = new Properties;
properties.load(new StringReader(envString))
....etc
}
And although this works, the mix of having closures and multi-line string is the only downside for now.
In a map declaration, Groovy parses identifiers such as example1 and example2 as string keys to a map:
[ example1: 1, example2: 2 ]
In the .with{} context, it probably uses a setProperty(property, value) mechanism.
But your case features expressions exam.ple and exam-ple. Those expressions have precedence, thus, Groovy will try to resolve them first (with probably something like exam.getProperty('ple') and exam.minus(ple), respectively).
You have some syntactic alternatives, but you will have to make it clear to Groovy what are supposed to be string keys and what are other expressions:
def map = [
'exam.ple4' : 4, // direct map declaration
example5 : 5 // unambiguous key declaration: no quotes needed
]
map.with {
example1 = 1
put 'exam.ple2', 2 // ambiguous, needs quotes
it.'exam-ple3' = 3 // as per #TimYates suggestion
}
assert map['exam-ple3'] == 3
assert map.'exam.ple2' == 2
assert map['exam.ple4'] == 4
assert map.example5 == 5 // again, no quotes needed for key
I'm a beginner in Haskell playing around with parsing and building an AST. I wonder how one would go about defining types like the following:
A Value can either be an Identifier or a Literal. Right now, I simply have a type Value with two constructors (taking the name of the identifier and the value of the string literal respectively):
data Value = Id String
| Lit String
However, then I wanted to create a type representing an assignment in an AST, so I need something like
data Assignment = Asgn Value Value
But clearly, I always want the first part of an Assignment to always be an Identifier! So I guess I should make Identifier and Literal separate types to better distinguish things:
data Identifier = Id String
data Literal = Lit String
But how do I define Value now? I thaught of something like this:
-- this doesn't actually work...
data Value = (Id String) -- How to make Value be either an Identifier
| (Lit String) -- or a Literal?
I know I can simply do
data Value = ValueId Identifier
| ValueLit Literal
but this struck me as sort of unelegant and got me wondering if there was a better solution?
I first tried to restructure my types so that I would be able to do it with GADTs, but in the end the simpler solution was to go leftroundabout's suggestion. I guess it's not that "unelegant" anyways.
There are some other questions on here that are similar but sufficiently different that I need to pose this as a fresh question:
I have created an empty class, lets call it Test. It doesn't have any properties or methods. I then iterate through a map of key/value pairs, dynamically creating properties named for the key and containing the value... like so:
def langMap = [:]
langMap.put("Zero",0)
langMap.put("One",1)
langMap.put("Two",2)
langMap.put("Three",3)
langMap.put("Four",4)
langMap.put("Five",5)
langMap.put("Six",6)
langMap.put("Seven",7)
langMap.put("Eight",8)
langMap.put("Nine",9)
langMap.each { key,val ->
Test.metaClass."${key}" = val
}
Now I can access these from a new method created like this:
Test.metaClass.twoPlusThree = { return Two + Three }
println test.twoPlusThree()
What I would like to do though, is dynamically load a set of instructions from a String, like "Two + Three", create a method on the fly to evaluate the result, and then iteratively repeat this process for however many strings containing expressions that I happen to have.
Questions:
a) First off, is there simply a better and more elegant way to do this (Based on the info I have given) ?
b) Assuming this path is viable, what is the syntax to dynamically construct this closure from a string, where the string references variable names valid only within a method on this class?
Thanks!
I think the correct answer depends on what you're actually trying to do. Can the input string be a more complicated expression, like '(Two + Six) / Four'?
If you want to allow more complex expressions, you may want to directly evaluate the string as a Groovy expression. Inside the GroovyConsole or a Groovy script, you can directly call evaluate, which will evaluate an expression in the context of that script:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
// Add each numer name as a property to the script.
numNames.eachWithIndex { name, i ->
this[name] = i
}
println evaluate('(Two + Six) / Four') // -> 2
If you are not in one of those script-friendly worlds, you can use the GroovyShell class:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
def langMap = [:]
numNames.eachWithIndex { name, i -> langMap[name] = i }
def shell = new GroovyShell(langMap as Binding)
println shell.evaluate('(Two + Six) / Four') // -> 2
But, be aware that using eval is very risky. If the input string is user-generated, i would not recommend you going this way; the user could input something like "rm -rf /".execute(), and, depending on the privileges of the script, erase everything from wherever that script is executed. You may first validate that the input string is "safe" (maybe checking it only contains known operators, whitespaces, parentheses and number names) but i don't know if that's safe enough.
Another alternative is defining your own mini-language for those expressions and then parsing them using something like ANTLR. But, again, this really depends on what you're trying to accomplish.