In Grails and Groovy, do Strings (in single quotes) outperform GStrings? - performance

Since in Grails and Groovy, single-quoted Strings are different class from GStrings (double quoted Strings allowing ${variable} value injection), is it more efficient to use single quotes, except when ${variables} are being used? I am guessing that the presence of the double quotes would require parsing of the String that an ordinary single-quoted String would not require. Therefore I would expect a very slight performance hit from the extra time looking for the presence of the ${}.
So, it would seem that it would be beneficial in general to have a convention to encourage the use single quotes, unless there is a specific advantage to using the double quotes. Am I off base?

Take a look at the first note under Double Quoted String.
Double quoted strings are plain java.lang.String if there’s no
interpolated expression, but are groovy.lang.GString instances if
interpolation is present.
This is possible because the interpolation is detected lazily and therefore determined whether to refer it as a GString or String. For example try to assertions below:
assert 'sample'.class.simpleName == 'String'
assert "sample".class.simpleName == 'String'
assert "sample ${1 != 2}".class.simpleName == 'GStringImpl'
Second assertion above makes it clear that double quotes are String by default until there is an interpolation (as in third assertion).
So, it does not matter if single or double quotes are used for as long as interpolation is not present. However, I personally do not think there should be any worry about performance benefits at the scale of using String or GString.

is it more efficient to use single quotes, except when ${variables}
are being used?
No. For the scenario where no ${variables} are used, they perform exactly the same. If there are no ${variables} in a double quoted String then the system does not create a GString. It creates a standard java.lang.String.
EDIT To Address A Separate Question Posted In A Comment Below:
It happens at compile time. The code below:
void someMethod(String a) {
def s1 = "some string"
def s2 = "some string with arg ${a}"
}
#groovy.transform.CompileStatic
void someOtherMethod(String a) {
def s1 = "some string"
def s2 = "some string with arg ${a}"
}
Compiles to this:
public void someMethod(String a)
{
CallSite[] arrayOfCallSite = $getCallSiteArray();
Object s1 = "some string";
Object s2 = new GStringImpl(new Object[] { a }, new String[] { "some string with arg ", "" });
}
public void someOtherMethod(String a)
{
String s1 = "some string";
GString s2 = new GStringImpl(new Object[] { a }, new String[] { "some string with arg ", "" });
}

Related

Regexp.escape adds weird escapes to a plain space

I stumbled over this problem using the following simplified example:
line = searchstring.dup
line.gsub!(Regexp.escape(searchstring)) { '' }
My understanding was, that for every String stored in searchstring, the gsub! would cause that line is afterwards empty. Indeed, this is the case for many strings, but not for this case:
searchstring = "D "
line = searchstring.dup
line.gsub!(Regexp.escape(searchstring)) { '' }
p line
It turns out, that line is printed as "D " afterwards, i.e. no replacement had been performed.
This happens to any searchstring containing a space. Indeed, if I do a
p(Regexp.escape(searchstring))
for my example, I see "D\\ " being printed, while I would expect to get "D " instead. Is this a bug in the Ruby core library, or did I misuse the escape function?
Some background: In my concrete application, where this simplified example is derived from, I just want to do a literal string replacement inside a long string, in the following way:
REPLACEMENTS.each do
|from, to|
line.chomp!
line.gsub!(Regexp.escape(from)) { to }
end
. I'm using Regexp.escape just as a safety measure in the case that the string being replaced contains some regex metacharacter.
I'm using the Cygwin port of MRI Ruby 2.6.4.
line.gsub!(Regexp.escape(searchstring)) { '' }
My understanding was, that for every String stored in searchstring, the gsub! would cause that line is afterwards empty.
Your understanding is incorrect. The guarantee in the docs is
For any string, Regexp.new(Regexp.escape(str))=~str will be true.
This does hold for your example
Regexp.new(Regexp.escape("D "))=~"D " # => 0
therefore this is what your code should look like
line.gsub!(Regexp.new(Regexp.escape(searchstring))) { '' }
As for why this is the case, there used to be a bug where Regex.escape would incorrectly handle space characters:
# in Ruby 1.8.4
Regex.escape("D ") # => "D\\s"
My guess is they tried to keep the fix as simple as possible by replacing 's' with ' '. Technically this does add an unnecessary escape character but, again, that does not break the intended use of the method.
This happens to any searchstring containing a space. Indeed, if I do a
p(Regexp.escape(searchstring))
for my example, I see "D\\ " being printed, while I would expect to get "D " instead. Is this a bug in the Ruby core library, or did I misuse the escape function?
This looks to be a bug. In my opinion, whitespace is not a Regexp meta character, there is no need to escape it.
Some background: In my concrete application, where this simplified example is derived from, I just want to do a literal string replacement inside a long string […]
If you want to do literal string replacement, then don't use a Regexp. Just use a literal string:
line.gsub!(from, to)

ruby on rails replace single-quotes with double-quote in a string

I am trying to replace a single-quote with double quotes inside a string, as following:
current_res = 25
lowest_res = 15
str = "The result of the child is '#{current_res}' and the lowest grade is '#{lowest_res }'."
I need the output to look like:
str = The result of the child is "25" and the lowest grade is "15".
I tried different method using gsub but nothing work so far. Any ideas?
If that's the only case you're covering where you need to show some output in double quoted string then. How about something simple like following
str = "The result of the child is \"#{current_res}\" and the lowest grade is \"#{lowest_res }\" ."
You can escape quotes in double quoted strings.

Passing double quotes into ruby script from the Linux terminal sometimes results in \" and other times in nothing being picked up in ARGV

I'm calling a ruby script from a bash terminal using the following line:
./receiveJSON.rb whatsin.json { "workers": { "Bot1": { "sentmessages": "11" } } }
it picks up parameters like this:
ARGV.each do |arg|
if !jsonStarted && filename.empty? && arg != "{"
filename = arg
elsif !jsonStarted && arg == "{"
jsonStarted=true
contentString += arg
elsif jsonStarted
contentString += arg
end
end
It is part of a chat bot to chat bot communication method that sends JSON through the chat (as they cannot communicate otherwise) and constructs a JSON file on the other side child value by child value. I've run into an unexpected issue though, which I believe is caused by a version inconsistency, however I'm hoping that it's a config difference in the versions that can be changed or overridden.
In ruby 2.1.9 the content string is passed through as valid JSON:
{"workers":{"Bot1":{"sentmessages":"11"}}}
However in ruby 2.2.6 and 2.2.7 the content string is passed through as:
{workers:{Bot1:{sentmessages:11}}}
The obvious first answer is can't you use keys, rather than strings, and the answer is yes, I possibly could in this example, however that would fail if I passed something intended as string as the value, for instance here:
./receiveJSON.rb whatsin.json { "workers": { "Bot1": { "sendcomplete": "2017-07-03 11:57:21 UTC" } } }
I'm hoping someone will come back saying that I don't have to change ruby version, that it's a new ruby parameter or it's a configuration setting, since an upgrade could affect other scripts, however if that's not the case I'll just have to resort to a few minutes of nerd rage before seeing what negative affects an upgrade will bring (perhaps none).
the quotes and curly braces are syntactical in shell see shell grammar (http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_10).
to use literal must be quoted.
quoting between single quotes prevent from variable expansion, but the string can't contain single quotes even with a \ because \ are also literal between single quotes, a solution to insert a single quote is to close the single quote string and to append escaped quote \' or enclosed between double quotes "'" then open new single quote string.
./receiveJSON.rb whatsin.json '{ "workers": { "Bot1": { "sentmessages": "11" } } }'
# string with single quote
./receiveJSON.rb whatsin.json '{ "workers": { "Bot1": { "bot'\''s messages": "11" } } }'

How to add single quotes across a string in ruby?

I am iterating over a config.yml from from which parsing the values in a string form as follows:
machines:
A:
ip: 10.11.12
pass: vass
B:
ip: 10.11.13
pass: grass
The above config.yml is parsed as follows:
machines = YAML.load_file('machine.yml')
var=''
machines[A].each do |letters,hash|
var += "[" + hash['ip'] + "]\n" + hash['pass'] + "\n"
end
The "var" value i am getting as :
"[10.11.12]\nvass\n[10.11.13]\ngrass\n"
but instead like above i dont want double quotes rather single quotes across complete atring as follows:
'[10.11.12]\nvass\n[10.11.13]\ngrass\n'
So, please suggest how can have single quotes across the string.
Generally the puts will print the value of the string without double quotes in the console.
So may be you can use puts var so that double quotes are not getting printed. And now you can wrap your content with single quote using string interpolation.
var += "'#{actual_value}'"

How do you print a dollar sign $ in Dart

I need to actually print a Dollar sign in Dart, ahead of a variable. For example:
void main()
{
int dollars=42;
print("I have $dollars."); // I have 42.
}
I want the output to be: I have $42. How can I do this? Thanks.
Dart strings can be either raw or ... not raw (normal? cooked? interpreted? There isn't a formal name). I'll go with "interpreted" here, because it describes the problem you have.
In a raw string, "$" and "\" mean nothing special, they are just characters like any other.
In an interpreted string, "$" starts an interpolation and "\" starts an escape.
Since you want the interpolation for "$dollars", you can't use "$" literally, so you need to escape it:
int dollars = 42;
print("I have \$$dollars.");
If you don't want to use an escape, you can combine the string from raw and interpreted parts:
int dollars = 42;
print(r"I have $" "$dollars.");
Two adjacent string literals are combined into one string, even if they are different types of string.
You can use a backslash to escape:
int dollars=42;
print("I have \$$dollars."); // I have $42.
When you are using literals instead of variables you can also use raw strings:
print(r"I have $42."); // I have $42.

Resources