How to get a reference on the Itcl class member variable? - reference

Say I have the following structure:
package require Itcl
itcl::class AAA {
private variable m_list {}
constructor {} {
fill m_list list
}
}
How to get a reference on the m_list in order to write
foreach elem $reference {.......}
Consider that list is really big and I don't want to copy it!

Tcl variables use copy-on-write semantics. You can safely pass a value around, assigning multiple variables to it, without worrying about it taking up more space in memory.
For example
set x {some list} ;# there is one copy of the list, one variable pointing at it
set y $x ;# there is one copy of the list, two variables pointing at it
set z $y ;# there is one copy of the list, three variables pointing at it
lappend z 123 ;# there are two copies of the list
;# x and y pointing at one
;# z pointing at the other
;# which is different from the first via an extra 123 at the end
The above code will result in two giant lists, one with the original data that both x any y point at, and one with the extra element of 123 that only z points to. Prior to the lappend statement, there was only one copy of the list and all three variables pointed at it.

Here is how to get a reference on the member of a class:
package require Itcl
itcl::class AAA {
public variable m_var 5
public method getRef {} {
return [itcl::scope m_var]
}
}
AAA a
puts [a cget -m_var]
set [a getRef] 10
puts [a cget -m_var]

Related

Remove character after a range function - Helm [duplicate]

I'm trying to write a string looking like this using go's template system:
(p1, p2, p3), where p1, p2, ... comes from an array in the program. My problem is how to place the comma properly for the last (or the first) element.
My non working version that outputs (p1, p2, p3, ) looks like this:
package main
import "text/template"
import "os"
func main() {
ip := []string{"p1", "p2", "p3"}
temp := template.New("myTemplate")
temp,_ = temp.Parse(paramList)
temp.Execute(os.Stdout, ip)
}
const paramList =
`{{ $i := . }}({{ range $i }}{{ . }}, {{end}})`
My best clue so far is found here http://golang.org/pkg/text/template/ in the following statement:
If a "range" action initializes a variable, the variable is set to the successive elements of the iteration. Also, a "range" may declare two variables, separated by a comma:
$index, $element := pipeline
in which case $index and $element are set to the successive values of the array/slice index or map key and element, respectively. Note that if there is only one variable, it is assigned the element; this is opposite to the convention in Go range clauses.
where it's suggested that the index
This suggests that it's possible to get hold of the index in the iteration but I just can't figure out what is meant with the range declaring two variables and where in the template those variables are supposed to be declared.
See this example from the go-nuts mailing list. One key to this trick is that a template if is different than a Go language if. A template can test for a value of zero, unlike the Go language that requires a boolean. The magic is then {{if $index}},{{end}} where $index needs no declaration other than its appearance in the assignment.

Find union of two variable-name scalars

I have a Stata program that outputs a local scalar of space-separated variable names.
I have to run the program twice on two samples (same dta) and store the union (intersection - variable names appearing in both scalars) as a new space-separated local scalar (for input to another program).
I can't figure out how to split (per spaces) and or test the occurrences of variable names in each.
Stata has a bunch of extended macro functions to use on lists that you can find with help macrolists, where you can see that A & B returns the intersection of A and B. If A="a b c d" and B="b c f g", then A & B = "b c".
This allows you to do something like this:
clear
scalar l1="vara varb varc"
scalar l2="varc vard vare"
local l1 = scalar(l1)
local l2 = scalar(l2)
local inter: list l1 & l2
scalar inter="`inter'"
scalar list inter
You convert the scalars to locals, get their union, and convert that into a scalar. It is probably easier to just modify your code to use locals rather than scalars so you don't have to deal with conversions.
I am not sure I perfectly understand your question, if this is not the appropriate answer, please add an example for us to work with.
Here is the code that checks two space-separated macros and gets their intersection, even if it's not the most elegant, unless your macros are huge it should still be quite fast.
local list1 first list here
local list2 list two here
local intersection
foreach l1 in `list1' {
foreach l2 in `list2' {
// if they overlap, add to the intersection macro
if "`l1'" == "`l2'" {
local intersection `intersection' `l1'
}
}
}
mac list // show the macros stored currently in the do file

How to assign values to a string? [duplicate]

This question already has answers here:
Create variables with names from strings
(6 answers)
Closed 6 years ago.
I have a loop running on multiple workstations, each loop is dealing with 5 different classes, when the results is acquired it is to save the result with the name of the classes it used.
For example on workstation 1 I am using:
class1 = 1;
class2 = 10;
%code that will run on all images associated with classes 1:10
% final_result from all 10 classes is calculated here
I want to save this now, with the name such as:
result_1_10 = final_result;
save result_1_10 result_1_10;
I can do this manually but its becoming very difficult to change the values on all machines after one value is changed, I would rather it save these and pick up the numbers from the two variables class1 and class2.
Here is what I tried:
['result_' num2str(class1) '_' num2str(class2)];
This would give me result_1_10. Which is what I wanted but it is a string, rather than a variable, so I cannot assign the result value to it
['result_' num2str(class1) '_' num2str(class2)] = final_result;
Would give the error:
Error: An array for multiple LHS assignment cannot contain
LEX_TS_STRING.
I even tried str2num(num2str(class1)) but that would also give an error.
How do I actually do this?
Thank you
While you can do this, it is very much discouraged by The Mathworks themselves. Any time you are trying to store information about what a variable contains within the variable name itself, that's a sign that maybe things should be rearranged a bit. Maybe consider using a different data structure.
Consider for example using a struct where you keep the classes as fields and the result as a field.
S.class1 = 1;
S.class2 = 10;
S.result = final_result;
You could then even create an array of structs holding your data.
S = struct('class1', {1, 2, 1}, ...
'class2', {10, 11, 10}, ...
'result', {rand(10), rand(10), rand(10)});
Then you could grab all results when class1 was 1:
S([S.class1 == 1]);
Or all results when class1 as 1 and class2 was 10
S([S.class1 == 1] & [S.class2 == 10]);
If you insist on doing it the way that you've laid out, you'll have to use eval or assignin to do that. Also, sprintf is often more concise than string concatenations.
variable = sprintf('result_%d_%d', class1, class2);
eval([variable, '= final_result;']);

Groovy DSL: creating dynamic closures from Strings

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.

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