I am writing a Stata do file and I would like to provide default values if the user does not supply some parameters. To do so, I woud like to check if a macro is undefined.
I have come up with a hacky way to do this:
*** For a local macro with the name value:
if `value'1 != 1 {
...do stuff
}
But I would like to know if there is a idiomatic way to do this.
If it's undefined, the contents of the macro would be empty. You can do this:
if missing(`"`mymacroname'"') {
display "Macro is undefined"
}
The quotes aren't really needed if the macro will contain a number. The missing(x) function can handle strings and numbers. It is kind of like testing (x=="" | x==.) Placing `' around "`mymacroname'" allows the macro to contain quotes, as in local mymacroname `"foo"' `"bar"'.
The question asked for an idiomatic way to do this and across Stata programmers
if "`macroname'" != ""
is far by the most commonly used test of whether a macro is defined. Macros contain strings when they are defined, and this is the general usage; use of numeric characters is just a special case.
OP asked if there was a way to test if a local is undefined. The concept of defined/undefined doesn't really exist in Stata (which is confusing to users new to Stata but not new to programming).
A more Stata like way to think about this is if the local is missing or not missing. If a local has not been defined it is considered missing. But if a local has been defined to a missing value, like the empty string "", it is also considered missing.
So, there is no way in Stata to differentiate between a string local being undefined or being defined but contains a missing value, i.e. the empty string "". Both the answers already given does not capture the difference between localA (defined but as the empty string) and localB (undefined) in the example below:
*initiating localA to the empty string
local localA ""
*Both these conditions will evaluated identically
if missing("`localA'")
if missing("`localB'")
*Both these conditions will evaluated identically
if "`localA'" != ""
if "`localB'" != ""
Related
I have a csv, which looks like this:
name,code,age
Himsara,9877,12
John,9437721,16
Razor,232,45
I have to replace the column code according to some regular expressions. My logic is shown in a Scala code below.
if(str.trim.length == 9 && str.startsWith("369")){"PROB"}
else if(str.trim.length < 8){"SHORT"}
else if(str.trim.startsWith("94")){"LOCAL"}
else{"INT"}
I used a UpdateRecord Processor to replace the data in the code column. I added a property called /code which contains the value.
${field.value:replaceFirst('^[0-9]{1,8}$','SHORT'):replaceFirst('[94]\w+','OFF_NET')}
This works when replacing code's with
length less than 8 with "SHORT"
starting with 94 with "LOCAL"
I am unable to find a way to replace data in the column, code when it's equal to 8 digits AND when it starts with 0. Also how can I replace the data if it doesn't fall into any condition mentioned above. (Situation which the data should be replaced with INT)
Hope you can suggest a workflow or value to be added to the property in Update record to make the above two replacements happen.
There is a length and startsWith functions.
${field.value:length():lt(8):ifElse(
'SHORT', ${field.value:startsWith(94):ifElse(
'LOCAL', ${field.value:length():equals(9):and(${field.value:startsWith(369)}):ifElse(
'PROB', 'INT'
)})})}
I have put the line breaks for easy to recognize the functions but it should be removed.
By the way, the INT means that some string values to replace? Sorry for the confusion.
Well, if you want to regular expression only, you can try the below code.
${field.value
:replaceFirst('[0-9]{1,8}', 'SHORT')
:replaceFirst('[94]\w+', 'OFF_NET')
:replaceFirst('369[0-9]{6}', 'PROB')
:replace(${field.value}, 'INT')
}
I have a namespace variable which is defined as below:
namespace eval ::SMB::{
variable SmbInfo
------
------
proc ::SMB::SmbCreate {name dutport} {
variable SmbInfo
global DutPorts DutPort_2 DutPorts_3 smb
------
------
if{"" != [info command SMB::$name]} {
return -code error "command name \"$name\" already exists"
}
set SmbInfo($name -DutPort) $dutport
I am new to Tcl and trying to understand the above piece of code. Few questions, please correct me if I am wrong at any point:
The variable SmbInfo defined on top in namespace is getting overridden by the one declared in the procedure SmbCreate. I am unable to figure out what is the objective of the line:
set SmbInfo($name -DutPort) $dutport
I can see that 'DutPorts' is defined as global but I could not find 'DutPort'. I have not executed the code yet. Could it be an error?
Is ($name - DutPort) creating an array index for the variable SmbInfo and the value of $dutport is being set to that particular array variable?
I have similar code structures in the file like below
set SmbInfo($name - SmbSetDmac) [BuildMac1 $SmbInfo($from_name-DutPort)]
Where BuildMac1 is a procedure. A bit explanation of the above code might also make the thing clear.
If anything I missed to post in the question, kindly point me, I will edit my question.
Thanks in advance.
The second declaration doesn't override, it's the same variable in both cases.
The command is a syntax error because of the space after $name. The intent seems to be to assign the value of $dutport to the member of SmbInfo that has the name "$name -DutPort" (where $name is replaced by the variable value).
A similar assignment, but here the value comes from the result of the command.
There are a few syntax errors in the code, too many or too few spaces here and there. It seems unlikely this code has ever been executed.
The purpose of the smb::SmbCreate command would seem to be to 1) create a new command in the SMB namespace named by the first parameter (unless such a command already exists) and 2) store metadata in the SmbInfo namespace variable, indexed by a) the name parameter and b) a keyword such as -DutPort or -SmbSetDmac.
Code like this essentially implements an ad-hoc object-oriented interface. If the whitespace issues are resolved, it should work fine.
You have many syntactic problems that are going to cause you much grief. Tcl cares very much about its syntax level, which includes exactly where the spaces and newlines are, and whether there are {braces} and [brackets] as expected. You must get these things right.
Looking at the specific code you're having problems with, this line:
set SmbInfo($name -DutPort) $dutport
would appear to be highly unlikely, as it is passing three arguments to the set command when that only takes one or two. I'd guess that you've got a command that you're calling to obtain a key for an array, and that the code therefore ought to be this:
set SmbInfo([$name -DutPort]) $dutport
See those [brackets]? They matter here, as they say “run my contents as a little subscript and use the result”. With that sorted out, there's also the question of whether $name -DutPort works at all, but you'll just have to be guided by the error messages there. Tcl usually gives very good error messages, though sometimes you have to think about why the code got in the state where it is giving that message in order to figure out what the actual problem is. You know, usual debugging…
I would expect similar problems with:
set SmbInfo($name - SmbSetDmac) [BuildMac1 $SmbInfo($from_name-DutPort)]
and would guess that it is actually supposed to be:
set SmbInfo([$name -SmbSetDmac]) [BuildMac1 $SmbInfo([$from_name -DutPort])]
Note again that I have modified the spaces to follow the existing pattern (which I'm guessing is a property access; it looks like it's OTcl or XOTcl) and added brackets.
Finally, this line:
if{"" != [info command SMB::$name]} {
is also syntactically wrong, and should instead be:
if {"" != [info command SMB::$name]} {
That extra space matters, because it separates the word that is the command name (if) from the word that is the condition expression. The remainder of the line is probably correct (the SMB::$name might be suspicious, except you're using it in info command, but then you probably only need info command $name as it already knows about what namespace you're working in and you're using the unqualified name elsewhere).
In a recent question I asked about the ' operation, and learned it is used for getting at language-defined "attributes" of certain types. From what I can gather, there is no way to create your own attributes for your types.
I came across this line of code that I don't understand:
function Image(C: Ada.Containers.Count_Type) return String renames
Ada.Containers.Count_Type'Image;
What is this doing?
Certain attributes, like 'Read, 'Write, 'Input and 'Output, can be overridden by user-defined subprograms, like so:
procedure My_Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in My_Type);
for My_Type'Write Use My_Write;
The 'Image attribute can't be overridden.
The function definition in you example is a renaming of the attribute, allowing you to call the attribute as if it were a normal subprogram:
Image(My_Count);
instead of
Ada.Containers.Count_Type'Image(My_Count);
I am just trying to use the OR function in Excel for analyzing some string variables. Instead of using a character count to verify whether someone anwered correctly, I would like to use the or function to accept more than one answer as correct.
For instance, return 1 if cell = "she was always there" or "she was there always".
How would I do this?
=IF(OR(A1="this",A1="that"),1,0)
IF takes three values:
The logical test
The value if true
The value if false
Each value can take other functions as it's argument. In this case, we use an OR function as the logical test. The OR can take any number of arguments (I'm sure there is a limit but I've never seen it). Each OR argument takes the form of a logical test and if any of the logical tests are TRUE, then the result of the OR is TRUE.
As a side note, you can nest many functions to create complex tests. But the nesting limit seems to be set at 7. Though there are tricks you can use to get around this, it makes reading the function later very difficult.
If you can live with "TRUE" or "FALSE" returns, then you don't need the IF function. Just:
=OR(A1="she was always there",A1="she was there always")
I found that by Googling "EXCEL OR FUNCTION"
http://office.microsoft.com/en-us/excel-help/or-function-HP010062403.aspx
I was training a new developer the other day and realized I don't know the actual term for "catching" a return value in a variable. For example, consider this pseudocoded method:
String updateString(newPart) {
string += newPart;
return string;
}
Assume this is being called to simply update the string - the return value is not needed:
updateString("add this");
Now, assume we want to do something with the returned value. We want to change the call so that we can use the newly updated string. I found myself saying "catch the return value", meaning I wanted to see:
String returnedString = updateString("add this");
So, if you were trying to ask someone to make this change, what terminology would you use? Is it different in different languages (since technically, you may be calling either a function or a method, depending on the language)?
assign the return value to a variable?
Returned values can be assigned or discarded/ignored/not used/[insert synonym here].
There isn't really a technical term for it.
I would say "returnedString is to be initialised with the return value of updateString".
"Catch" makes me think of exceptions, which is a bit misleading. How about something like "use" or "store" or "assign"?
Common ones that I know:
You assign a value to a variable.
You store a value into a variable.
check the function's return value, do not ignore return values
In the example, you're simply assigning the return value of the function to a new variable.
When describing the behavior of that single line of code, it doesn't really matter that the return value is not essential to the use of the function. However, in a broader context, it is very important to know what purpose this "Interesting Return Value" serves.
As others have said there isn't really a word for what you describe. However, here's a bit of terminology for you to chew on: the example you give looks like it could be a Fluent Interface.
I suggest "cache", meaning store it for later.
Maybe there's a subliminal reason you're saying "catch".
It's better too state the purpose rather than the implementation details (because actual implementation can be different in different programming langugages).
Generally speaking:
- Save the return value of the call.
If you know the return value is a result of something:
- Save the result of the call.
If you know the return value is to signify a status (such as error):
- Save the status of the call.
By using the word "save", you can use that same statement across the board, regardless of the mechanism used in that particular language to save the return value.