Detecting if a variable can be printed in Lua - string

I've got a variable that could be a number of types - sometimes it's a string, sometimes a number, table or bool. I'm trying to print out the value of the variable each time like this:
print("v: "..v)
with v being my variable. Problem is, when I get a value that can't be concatenated I get this error:
myscript.lua:79: attempt to concatenate a table value
I've tried changing it to this in case it manages to detect whether or not the variable can be printed:
print("v: "..(v or "<can't be printed>"))
but I had the same problem there. Is there some sort of function I can use to determine if a variable can be concatenated to a string, or a better way of printing out variables?

You can provide the values as separate arguments to print:
print("v:", v)
This would print something like
v: table: 006CE900
Not necessarily the most useful, but better than a crash if it's just for debugging purposes.
See here for information on more useful table printing.

tostring(v) works for all possible v values (including nil). So writing your line as:
print( "v: " .. tostring( v ) )
will always work.
Alternatively you could have a look at type( v ) and if its "string" print it, otherwise print something else (if that's what you want).

Related

string.gsub return as a distinct variable for each replace result

Input:
stringdata = '{"abcd://ipaddress/directory1/Images/subfolder/Image0.png","abcd://ipaddress/directory1/Images/subfolder/Image1.png","abcd://ipaddress/directory1/Images/subfolder/Image2.png","abcd://ipaddress/directory1/Images/subfolder/Image3.png","abcd://ipaddress/directory1/Images/subfolder/Image4.png"}'
Source Code
string.gsub(stringdata, "(.....................%w%w................................%w)",print)
Current output:
abcd://ipaddress/directory1/Images/subfolder/Image0.png
abcd://ipaddress/directory1/Images/subfolder/Image1.png
abcd://ipaddress/directory1/Images/subfolder/Image2.png
abcd://ipaddress/directory1/Images/subfolder/Image3.png
abcd://ipaddress/directory1/Images/subfolder/Image4.png
Expected output (where each of the below could be stored in a different variable)
directory1/Images/subfolder/Image0.png
directory1/Images/subfolder/Image1.png
directory1/Images/subfolder/Image2.png
directory1/Images/subfolder/Image3.png
directory1/Images/subfolder/Image4.png
With so many . in your pattern, it's hard to read and unclear what's your purpose.
Instead, use a pattern that's specific to the format:
string.gsub(stringdata, "%w+://%w+/(%w+/%w+/%w+/%w+%.png)", print)
In this way, it's much more clear what each %w+ represents.
To store the result, you are using the wrong function. string.gsub is used for substitution, use string.gmatch instead:
for m in string.gmatch(stringdata, "%w+://%w+/(%w+/%w+/%w+/%w+%.png)") do
print(m)
-- do whatever with m
end

Understanding string.gsub in Lua

I'm trying to print a gsub string (in Lua) to stdout here how my code look like.
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>', string.gsub('VEECTORY','EE','I'))
Everytime I run this, although I get the desired result but I see 1 appearing in the output.
So, the output look like this.
string.gsub('VEECTORY','EE','I') => VICTORY 1
I'm unable to understand what does that 1 stand for but if I used a variable I don't see that 1 anymore.
local replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
I get output as
string.gsub('VEECTORY','EE','I') => VICTORY
I also notice that when I run the above code in Lua console
i.e this code
local replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
I get the output as nil
What am I missing ?
string.gsub has two return values. The first is result string, while the second is the total number of matches that occurred.
In your example:
string.gsub('VEECTORY','EE','I')
The second return value is 1 because the substitution happened once.
When you assign the result as:
local replace_string = string.gsub('VEECTORY','EE','I')
The first return value is assigned to replace_string, while the second return value is discarded.
You can get the second return value explicitly by:
local replace_string, num = string.gsub('VEECTORY','EE','I')
Finally, in interactive mode, each line is a chunk by itself, so the local variables are out of scope in the next line, therefore you saw replace_string becomes nil. If you use global variables:
replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
The output will be as expected in interactive mode as well.

Dropping various string variables in a loop in Stata

I want to a drop a great number of string variables that contain the word "Other" in their observations. As such, I tried the following loop to drop all the variables:
foreach var of varlist v1-v240 {
drop `var' if `var'=="Other"
}
What I get in return is the answer "syntax error". I would like to know not only a way to perform the task of dropping all the variables that contain the word "Other", but also why the code that I've entered returns an error.
The short answer on why your syntax is illegal, which #Dimitriy Masterov doesn't quite spell out, is that drop supports just two syntaxes, which can't be mixed, dropping variables and dropping observations. This is documented: see e.g. http://www.stata.com/help.cgi?drop and the corresponding on-line help and manual entry within Stata.
In addition to other solutions, findname from the Stata Journal would allow this solution:
findname, any(# == "Other")
drop `r(varlist)'
Your interpretation of contain is evidently 'is equal to' judging by your use of == as an operator, echoed above. If contain really means 'includes as substring', then you need a syntax such as
any(strpos(#, "Other"))
or
any(regexm(#, "Other"))
as #Dimitriy also explains.
If they are actual strings, this should work:
sysuse auto, clear
ds, has(type string) // get a list of string variables
// loop over each string variable, count observations that contain Buick anywhere, and drop the variable if N>0
foreach var of varlist `r(varlist)' {
count if regexm(`var',"Buick")
if r(N)>0 {
drop `var'
}
}
If "contains" means only contains, then you need to use "^Buick$" instead or
count if `var'=="Buick"
Beware of leading/trailing spaces.
The if qualifier restricts the scope of a command to those observations for which the value of the expression is true. Your code errors because you are asking Stata to drop a variable (a column) if some observations (rows) satisfy a condition. You could use the if qualifier to drop those observations or you can drop a variable, but not both simultaneously. My code uses the if command (a different beast) to verify the condition, and then drops the variable if that condition is satisfied.
You might be tempted to do something like
if `var'=="Other" {
drop `var'
}
but that will usually not work as expected (it would drop the variable only if the first observation was "Other").

Coffeescript - how do I check string equality when passing string through a splat?

I'm having trouble checking whether two strings are equal when one of them was passed through a splat argument. Because coffeescript uses strict comparisons, and because it makes a copy of the arguments when they go through a splat, I can't get the strings to compare properly without resorting to backticks. Is there a better way? Here's a minimal piece of code that demonstrates the problem:
check=(arg) ->
if arg == 'foo' then "'#{arg}'=='foo'" else "'#{arg}'!='foo'"
emit=(args...) ->
check(args)
console.log(emit('foo'))
console.log(check('foo'))
The output from this will be as follows:
> coffee mincase.coffee
'foo'!='foo'
'foo'=='foo'
EDIT:
mu is too short gave me the key, so the revised working code looks like this (everything is the same except emit)
emit=(args...)->
check.apply(null,args)
When you use a splat, the splat puts the splatted arguments into an array. For example:
f = (x...) -> console.log(x instanceof Array)
f(6)
will give you a true in the console. The fine manual isn't so fine in this case, it doesn't exactly spell it out, it assumes that you understand how JavaScript's arguments object works and leaves out the explicit splat puts your arguments into an array part.
So you end up passing an array to check and an array compared with a string using CoffeeScript's == (or JavaScript's ===) will never be true.
If you want emit to check the first argument, then you need to say so:
emit = (args...) -> check(args[0])
Demo: http://jsfiddle.net/ambiguous/TBndM/

Convert string to a variable name

I am using R to parse a list of strings in the form:
original_string <- "variable_name=variable_value"
First, I extract the variable name and value from the original string and convert the value to numeric class.
parameter_value <- as.numeric("variable_value")
parameter_name <- "variable_name"
Then, I would like to assign the value to a variable with the same name as the parameter_name string.
variable_name <- parameter_value
What is/are the function(s) for doing this?
assign is what you are looking for.
assign("x", 5)
x
[1] 5
but buyer beware.
See R FAQ 7.21
http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f
You can use do.call:
do.call("<-",list(parameter_name, parameter_value))
There is another simple solution found there:
http://www.r-bloggers.com/converting-a-string-to-a-variable-name-on-the-fly-and-vice-versa-in-r/
To convert a string to a variable:
x <- 42
eval(parse(text = "x"))
[1] 42
And the opposite:
x <- 42
deparse(substitute(x))
[1] "x"
The function you are looking for is get():
assign ("abc",5)
get("abc")
Confirming that the memory address is identical:
getabc <- get("abc")
pryr::address(abc) == pryr::address(getabc)
# [1] TRUE
Reference: R FAQ 7.21 How can I turn a string into a variable?
Use x=as.name("string"). You can use then use x to refer to the variable with name string.
I don't know, if it answers your question correctly.
strsplit to parse your input and, as Greg mentioned, assign to assign the variables.
original_string <- c("x=123", "y=456")
pairs <- strsplit(original_string, "=")
lapply(pairs, function(x) assign(x[1], as.numeric(x[2]), envir = globalenv()))
ls()
assign is good, but I have not found a function for referring back to the variable you've created in an automated script. (as.name seems to work the opposite way). More experienced coders will doubtless have a better solution, but this solution works and is slightly humorous perhaps, in that it gets R to write code for itself to execute.
Say I have just assigned value 5 to x (var.name <- "x"; assign(var.name, 5)) and I want to change the value to 6. If I am writing a script and don't know in advance what the variable name (var.name) will be (which seems to be the point of the assign function), I can't simply put x <- 6 because var.name might have been "y". So I do:
var.name <- "x"
#some other code...
assign(var.name, 5)
#some more code...
#write a script file (1 line in this case) that works with whatever variable name
write(paste0(var.name, " <- 6"), "tmp.R")
#source that script file
source("tmp.R")
#remove the script file for tidiness
file.remove("tmp.R")
x will be changed to 6, and if the variable name was anything other than "x", that variable will similarly have been changed to 6.
I was working with this a few days ago, and noticed that sometimes you will need to use the get() function to print the results of your variable.
ie :
varnames = c('jan', 'feb', 'march')
file_names = list_files('path to multiple csv files saved on drive')
assign(varnames[1], read.csv(file_names[1]) # This will assign the variable
From there, if you try to print the variable varnames[1], it returns 'jan'.
To work around this, you need to do
print(get(varnames[1]))
If you want to convert string to variable inside body of function, but you want to have variable global:
test <- function() {
do.call("<<-",list("vartest","xxx"))
}
test()
vartest
[1] "xxx"
Maybe I didn't understand your problem right, because of the simplicity of your example. To my understanding, you have a series of instructions stored in character vectors, and those instructions are very close to being properly formatted, except that you'd like to cast the right member to numeric.
If my understanding is right, I would like to propose a slightly different approach, that does not rely on splitting your original string, but directly evaluates your instruction (with a little improvement).
original_string <- "variable_name=\"10\"" # Your original instruction, but with an actual numeric on the right, stored as character.
library(magrittr) # Or library(tidyverse), but it seems a bit overkilled if the point is just to import pipe-stream operator
eval(parse(text=paste(eval(original_string), "%>% as.numeric")))
print(variable_name)
#[1] 10
Basically, what we are doing is that we 'improve' your instruction variable_name="10" so that it becomes variable_name="10" %>% as.numeric, which is an equivalent of variable_name=as.numeric("10") with magrittr pipe-stream syntax. Then we evaluate this expression within current environment.
Hope that helps someone who'd wander around here 8 years later ;-)
Other than assign, one other way to assign value to string named object is to access .GlobalEnv directly.
# Equivalent
assign('abc',3)
.GlobalEnv$'abc' = 3
Accessing .GlobalEnv gives some flexibility, and my use case was assigning values to a string-named list. For example,
.GlobalEnv$'x' = list()
.GlobalEnv$'x'[[2]] = 5 # works
var = 'x'
.GlobalEnv[[glue::glue('{var}')]][[2]] = 5 # programmatic names from glue()

Resources