The Representation of an Empty Argument in a "Call"

The representation of an empty argument in a call

If looks like l[[2]]'s value is a special object: the empty symbol. Some facts about the empty symbol (speculated based on casual experimentation).

(1) The empty symbol is a symbol:

> is.symbol(l[[2]])
[1] TRUE

(2) The empty symbol cannot be created explicitly:

> as.name("")
Error in as.name("") : attempt to use zero-length variable name
> ``
Error: attempt to use zero-length variable name
> quote()
Error in quote() : 0 arguments passed to 'quote' which requires 1

(3) The only way to create an empty symbol is by quote-ing a function call and passing an empty argument, e.g.:

> c <- quote(f(,0))
> d <- quote(f(x, n=, 0))

The empty symbol can now be accessed thus: c[[2]], d$n, as.list(d)[[3]]

(4) The empty value is unique and does not equal any other symbol:

> identical(c[[2]], d$n)
[1] TRUE

> identical(c[[2]], `a`)
[1] FALSE

(5) The empty symbol cannot be assigned to a standalone variable. If assigned to such a variable, the variable is actually assigned the "missing argument" value:

> x <- d$n
> missing(x)
[1] TRUE
> missing(d$n)
Error in missing(d$n) : invalid use of 'missing'

However, the empty symbol can be assigned to a list slot:

> p <- list(`a`, k=`b`)
> p[[1]] <- d$n
> p$k <- c[[2]]

> identical(p[[1]], d$n)
[1] TRUE

> identical(p[[1]], p[[2]])
[1] TRUE

And it can be passed as a function argument:

> h <- function(x) identical("", d$n)
> h(c[[2]])
[1] TRUE

When passed as a function argument, the argument is not considered to be missing:

> h2 <- function(x) missing(x)
> h2(c[[2]])
[1] FALSE

But compare

> h2(x)
[1] TRUE

(6) The character value of the empty symbol is the empty string:

> identical("", as.character(d$n))
[1] TRUE

(7) There is no primitive function that checks whether a value is the empty symbol. To check whether a value is the empty symbol, its character representation needs to be compared to the empty string:

> is.symbol(d$n) && identical("", as.character(d$n))
[1] TRUE

Appendix

Here are a number of function definitions to facilitate the creation and identification of empty symbols and "missing argument" objects.

> isEmptySymbol
function(x) is.symbol(x) && identical("", as.character(x))

> EmptySymbol
function() (quote(f(,)))[[2]]

> isMissingArgObject
function(x) {
if ("x" %in% names(match.call())) return (missing(x))
stop("An argument must be supplied.") }

> MissingArgObject
function() quote(expr=)

Pass empty argument as array index

You can use missing, so that a missing index implies "select all", which I assume means that the user would just want the grand mean.

myfun <- function(index)
{
if(missing(index)) mean(data) else apply(data[, index, ], 1:2, mean)
}

how to treat empty parameters in function calls?

The data type of missed parameters is ERROR.

I wrote an example, try the following:

Function IsMissing(p)
IsMissing = (VarType(p) = vbError)
End Function

Function Myfunc(p1, p2, p3, p4)
If IsMissing(p1) Then Response.Write "p1 is missing "
If IsMissing(p2) Then Response.Write "p2 is missing "
If IsMissing(p3) Then Response.Write "p3 is missing "
If IsMissing(p4) Then Response.Write "p4 is missing "
End Function

str = myfunc(, , , 1)
'str = myfunc(1, 2, , ) 'causes error

Notice: The last parameter of function / sub cannot be blank because of syntax error.

handle empty object passed as argument in javascript

You can use:

function playAnimation(options) {
options = options || {}
var timeOutAnimation = options.animationDuration || 15;
var color = options.color;
}

To set options to an empty object if it doesn't exist. You can also check for undefined like this if you want:

if(typeof options === "undefined") {
// options not passed
}

Here is a fiddle which demonstrates.

Are empty macro arguments legal in C++11?

If I understand correctly, empty macro argument is allowed since C99 and
C++0x(11).

C99 6.10.3/4 says:

... the number of arguments (including those arguments consisting of
no preprocessing tokens) shall equal the number of parameters ...

and C++ N3290 16.3/4 has the same statement, while C++03 16.3/10 mentions:

... any argument consists of no preprocessing tokens, the behavior is
undefined.

I think empty argument comes under the representation arguments consisting of
no preprocessing tokens
above.

Also, 6.10.3 in Rationale for International Standard Programming Languages C rev. 5.10
says:

A new feature of C99: Function-like macro invocations may also now
have empty arguments, that is, an argument may consist of no
preprocessing tokens.

R function calls, ... and missing values

Here is a possibility for approaching this:

#https://stackoverflow.com/a/20906150/1412059
isEmptySymbol <- function(x) is.symbol(x) && identical("", as.character(x))

foo <- function(...) {
i <- as.list(match.call())[-1] #call before evaluation

#replace empty symbols (here with 0 as an example)
i[vapply(i, isEmptySymbol, FUN.VALUE = TRUE)] <- 0

#evaluate all list elements
lapply(i, eval)
}

x <- 2
foo(1, , x)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 0
#
#[[3]]
#[1] 2

Call function without optional arguments if they are None

Pass the arguments as kwargs from a dictionary, from which you filter out the None values:

kwargs = dict(p1='FOO', p2=None)

alpha(**{k: v for k, v in kwargs.items() if v is not None})

Accept function in argument with empty interface return type

You tripped over a very common misconception for Go newcomers: The empty interface interface{} does not mean "any type". Really, it does not. Go is statically typed. The empty interface interface {} is an actual (strongly typed type) like e.g. string or struct{Foo int} or interface{Explode() bool}.

That means if something has the type interface{} it has that type and not "any type".

Your function

func test(x func() interface{})

takes one parameter. This parameter is a (parameterless function) which returns a specific type, the type interface{}. You can pass any function to test which matches this signature: "No parameters and return interface{}". None of your functions a and b match this signature.

As said above: interface {} is not a magical abbreviation for "whatever",it is a distinct static type.

You have to change e.g. a to:

func a() interface{} {
return "hello"
}

Now this might look strange as you return a string which is not of type interface{}. This works because any type is assignable to variables of type interface{} (as every type has at least no methods :-).

How does one represent the empty char?

You can use c[i]= '\0' or simply c[i] = (char) 0.

The null/empty char is simply a value of zero, but can also be represented as a character with an escaped zero.

Why if I send a string as argument in a function it comes back empty?

It's not just that the string is immutable, but also that while string is a reference type, a reference itself is not. That is, you are passing the string by reference, but the reference itself is passed by value.

Thus, for reference types, you can modify the object that is referred to by the parameter (as long as it's modifiable), but you cannot modify what the argument refers to unless you pass it by reference.

So, when you try to change what the string variable refers to:

str = tmpStr;

It changes what str refers to locally, but does not affect what the original argument localString refers to.

Think of it this way, let's say that the argument localString refers to an object at location 1000:

localString 
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
+---------------+

Then when we pass localString to the method, it creates a copy of the reference (as str) and updates the reference count...

localString 
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 2 |
| Value: "" |
str +---------------+
+---------------+ ^
| 1000 | ---------------------+
+---------------+

Then, when you assign str to a new string, it modifies the reference str but not localString:

localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
str +---------------+
+---------------+ 2500
| 2500 | ---------------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+

So your modification of str only changed what str refers to, not the original refernce localString, if you want to change that, then you pass by reference, which means that str is a reference back to the original argument (much like a ptr to a ptr):

localString
+---------------+ 1000
| 2500 | ------------------> +---------------+
+---------------+ | Count: 2 |
^ | Value: "" |
str | +---------------+
+---------------+
| |
+---------------+

Now, when you change str it changes the refernce localString as well:

localString
+---------------+ 1000
| 1000 | -----+ +---------------+
+---------------+ | | Count: 0 |
^ | | Value: "" |
str | | +---------------+
+---------------+ | 2500
| | +----------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+

And then, of course, the original string (assuming nothing else refers to it as in this example) can be garbage collected...

So, if you really want to modify the string parameter, pass it by ref or out, or you can return the new mutated version, or store in an instance member (though pass-by-instance-member is a higher order of coupling and can cause other issues...).



Related Topics



Leave a reply



Submit