Delete/remove/drop variable in q - kdb

I've created a variable in the :
q)myvar: 1
How can I delete it?
I've tried:
q)delete myvar from `.z
but the namespace `.z is clearly not the right one, as the variable still does exist:
q)myvar
1

The top namespace is actually called `., so the following will work:
q)delete myvar from `.
`.
q)myvar
`myvar
Also, running key `. will show all variable defined in the top namespace.

Related

How do I unassign variables in KDB?

Let's say I've written:
d: 3
How do I then unassign this, if I want to delete this variable?
I tried delete d and _d but neither of these worked.
To delete a variable from the root namespace you can use:
delete d from `.
More information can be found here:
https://code.kx.com/q/ref/delete/

Define global variable within a function in q kdb

I can see two ways to define a global variable from a function in q.
Using ::
q){gv::10}[]
q)gv /- 10
Using set
q){`gv set 20}[]
q)gv /- 20
There is a catch with set i.e. if a global variable already has a symbol assigned to it, then the value which is assigned to global variable within the function is assigned to the symbol which is assigned to global variable.
q)gv:`t
q){gv set 20}[]
`t
q)gv
`t
q)t
20
Can someone please explain me which is the better way (set or ::) to define a global variable within a function and why is it better?
There is no "better" really - but set has the advantage of assigning to a variable name which is itself a variable (as you showed in your example).
I'm confused about your confusion in the last example though......if you wanted 20 to be assigned to a global called gv then you should put a backtick in front of gv, aka `gv set 20; and conversely if you wanted 20 to be assigned to the symbol/name that gv contains then don't use the backtick, aka gv set 20;
Final point to note is that you can also create globals in non-root directories/namespaces using a single colon assignment
q){.this.that:1;}[]
q)
q).this
| ::
that| 1

How to test if a variable exists

I need to run SPSS syntax in an IF statement, which tests if a variable exists in the document. I am having trouble getting the IF test right. I'm trying to do this:
do if (test if myVariable exists).
// execute code here
end if.
Execute.
I've looked here and tried this:
DO IF (myVariable) exist=1.
END IF.
Execute.
But I get the error 'There is extraneous text following the logical expression on a DO IF command. Have I misunderstood the code?
spssinc select variables command creates a list of variables according to a specified propertie. In this case the property will be the variable called "MyVar". If the variable doesn't exist, the list will stay empty:
spssinc select variables macroname="!findMyVar" /properties pattern="MyVar".
Now we define a macro that will run some commands only if the above list is not empty:
define doifMyVarexists ()
!if (!eval(!findMyVar)<>"") !then
* put your commands here, like following examples.
compute MyVar=MyVar*2.
freq MyVar.
!ifend
!enddefine.
* the macro is ready, now we call it:
doifMyVarexists.
If you run this multiple times, you will face a problem that if MyVar exists once and in a later run doesn't exist - the list doesn't get emptied (it is only overwritten if there were variables to put into it).
To solve that use the following line to empty the list before running select variables again:
define !findMyVar() !enddefine.

How to pass arguments by reference to robot framework keywords?

I have a keyword in robot framework; it takes an argument, performs some process on it and returns it after all:
My Keyword Name
[Arguments] ${arg}
# Some process on ${arg}
[Return] ${arg}
So it would be the usage:
${x} = My Keyword Name ${x}
Which implies that I gave the old value of ${x} to the keyword and it returned me the new value of it.
I want to make a call by reference on My Keyword Name, so I don't need to use an assignment for setting new value for ${x}. I have read the BuiltIn and UserGuide,
but there was no line about this subject. Can anyone help me on this?
If ${x} is a mutable type such as a list or dictionary, you can pass the object itself. If it represents a scalar value such as a string or int, you can't do what you want. Your only choice is to return the new value and re-assign it to the original variable.
It will work if you initialize the variable as
My Keyword Name
[Arguments] ${arg}
${arg} = Set Variable 56
[Return] ${arg}
Test
Log To Console \n\nin Test
${x} = Set Variable 0
${x} = My Keyword Name ${x}
Log To Console ${x}
Or
Can you explore whether you can make use of Set Global Variable or Set Test Variable?
I'd spent some time before i got the solution!
* Variables
${someVar} initial value
* Test Cases
[Check reference]
Set this \${someVar} new value
Should Be Equal ${someVar} new value
* Keywords
Set this
[Arguments] ${varName} ${value}
Set Test Variable ${varName} ${value}
The point is in the magic "\" char :)
It actually comes down to mutable/immutable variables in python, and how they are passed to functions.
Details here in this answer, but in RF context it boils down to - you can change lists and dictionaries, and not strings and numbers (int, float). Example:
A testcase
Log To Console \n
${var}= Create List member1
Log To Console ${var}
Mutate The List ${var}
Log To Console ${var}
*** Keywords ***
Mutate The List
[Arguments] ${lst}
Append To List ${lst} new one
The output when ran would be:
==============================================================================
A testcase
['member1']
['member1', 'new one']
| PASS |
, e.g. the variable defined in the case got changed by a keyword. The same can be done with dictionaries.
If you reassign the variable in the function though, it will not change; e.g. with a keyword like this:
Mutate The Dict
[Arguments] ${lst}
${lst}= Create List fsf
Append To List ${lst} bogus
, the original variable ${var} will not be changed.
Why so? In short, in python variables are just identifiers ("names") to memory addresses; when you assign ${lst} to a new list, the variable now points to a new address in the memory, and further interactions don't change the original one.
Welp I just ran into the same issue, as I was using a Run Keyword If statement in a For Loop. Knowing that if I used a keyword that returns a value, robot framework freaks out.
So I just thought of this as a potential solution. It'll use my example. It does have redundancy, but thats because you just have to in this case.
***Keywords***
| Increment | [Arguments] | ${var} |
| | ${var} | Evaluate | ${var} + 1 |
| | Set Test Variable | ${var} | ${var} |
Usage:
| Increment | ${idx} |
| Set Test Variable | ${idx} | ${var}
Now I'm not saying this is the best solution, but if you run into the scenario that you have to return a value to a variable with a keyword, and you're inside a "Run Keyword If", this should allow you to circumvent the issue. I don't really like it that much, but it gets the job done.

SPSS Macro - Generate dynamic Varnames

I am currently trying to create dynamic variable names based on the valuelabels of the passed Argument. Currently, I have something like this:
COMPUTE counter = 0.
APPLY DICTIONARY FROM *
/SOURCE VARIABLES = V601
/TARGET VARIABLES = counter.
DEFINE !macro1 (!POS !CMDEND).
STRING name (A20).
!DO !#i = 1 !TO 62
COMPUTE counter = #i
!IF (!POS !EQ !i)
!THEN
COMPUTE name = VALUELABEL(!POS)
COMPUTE !CONCAT('wasnot', name) = 1.
!ELSE
COMPUTE name = VALUELABEL(!counter).
COMPUTE !CONCAT('wasnot', name) = 0.
!IFEND
!DOEND
CROSSTABS v15 by !CONCAT('wasnot', name) /cells = column.
!ENDDEFINE.
The idea is, that for every unique value of V601 a flag variable will be created (e.g. "wasnotvaluelabel1"). This variable will either have value = 1 or 0 respectively. However, it seems that concat cannot be used the way I intended. I get these errors:
Error # 6843 in column 7. Text: !POS
The end of a macro expression occurred when an operand was expected.
Execution of this command stops.
Error # 6846 in column 7. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6836 in column 12. Text: !EQ
In a macro expression, an operator was not preceded by an operand.
Error # 6846 in column 2. Text: !THEN
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6846 in column 28. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Questions I have right now:
Is it even possible to generate dynamic names? I have tried
different attempts over the last hours but the SPSS macro "language"
seems very restricted.
Is there perhaps some other way to achieve this Task? It seems rather unconvenient.
Please note, working with the Python AddIn is sadly not an Option. I'm grateful for any received advice.
There is an extension command, SPSSINC CREATE DUMMIES, that will create all these dummy variables automatically. It's on the Transform menu. And it is implemented in Python.
Using Python you can easily read case data and do lots more.
Thanks for all the Help. In the end I did it with generating new syntax using Outfile.