0

I have a function called "p". In this function, there is an object called "marginal" which I need to make recognizable and retrievable outside this function when called. Right now, when I call the object "marginal" outside the function, I get an wrror message that:

object 'marginal' not found

Question: How can I make "marginal" recognizable outside the function?

p <- function(t, N1, N2=NULL, delta) {

    efN = ifelse(is.null(N2), N1, N1*N2/(N1+N2))
    df  = ifelse(is.null(N2), N1 - 1, N1 + N2 - 2)

    prior <- function(delta) dnorm(delta, 0, 1)
    likelihood <- function(delta) dt(t, df, delta*sqrt(efN) )

    marginal <- integrate(function(x) prior(x)*likelihood(x), -Inf, Inf)[[1]]

    post <- function(x) prior(x)*likelihood(x) / marginal

    return(post(delta))

    list(marginal) ## What to use instead of list to object "marginal" recognizable 
                    # outside the function?
 }

 marginal

object 'marginal' not found

rnorouzian
  • 7,397
  • 5
  • 27
  • 72
  • 1
    Possible duplicate of [Global and local variables in R](http://stackoverflow.com/questions/10904124/global-and-local-variables-in-r) – Ronak Shah Apr 03 '17 at 06:18
  • 1
    I tried refactoring your function and taking it apart, and I couldn't, `marginal()` is dependent upon so many other pieces. If you need the `marginal()` function standalone, you should consider redesigning your code. You _could_ use the global assignment operator here, but it is usually not recommended. – Tim Biegeleisen Apr 03 '17 at 06:21
  • Everything after the `return()` call is going to be ignored. If you need to return multiple values, put them in a list and return the list. – Marius Apr 03 '17 at 06:32
  • @Marius, that didn't work. – rnorouzian Apr 03 '17 at 06:35
  • You could use an assignment which will write to the global environment. This is of course "legal", but far better way is to return everything in a list and return that. When you assign result of the `p()`, you can access any element you want, which you can pass on to other (or the same) functions. Try returning this: `list(marginal = marginal, posterior = post(delta))`. You can now access `xy$marginal` or `xy$posterior`. – Roman Luštrik Apr 03 '17 at 07:40

2 Answers2

2

The best solution for you would be to refactor your current function, possibly into smaller functions, in such a way that you can easily get the value of marginal separately. Then, use it to complete your current calculation.

That being said, if you want a quick fix you could resort to using the parent scope assignment operator <<-, e.g.

marginal <- NULL

p <- function(t, N1, N2=NULL, delta) {
    efN = ifelse(is.null(N2), N1, N1*N2/(N1+N2))
    df  = ifelse(is.null(N2), N1 - 1, N1 + N2 - 2)

    prior <- function(delta) dnorm(delta, 0, 1)
    likelihood <- function(delta) dt(t, df, delta*sqrt(efN) )

    # note the assignment being done here carefully
    marginal <<- integrate(function(x) prior(x)*likelihood(x), -Inf, Inf)[[1]]

    post <- function(x) prior(x)*likelihood(x) / marginal

    return(post(delta))
}

# now marginal contain the value assigned in the function call above

However, it is usually not recommended to take such an approach. I only offer it as a quick fix, with the strong suggestion that you rethink your code design.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • `marginal` is not a function in OP's code, is it? It's just a single value from what I can tell. – Marius Apr 03 '17 at 06:31
  • @Marius You might be right, I haven't used most of the functions in the OP. If he just wants another value returned, why not return a vector of values? – Tim Biegeleisen Apr 03 '17 at 06:32
0

To access multiple values from inside a function, make sure all the values you want to access get returned by putting them in a list. Then return the list, assign the results of the function call, and access the values you want:

multi_return = function() {
    x = 3
    y = 4
    res = list(x = x, y = y)
    return(res)
}

results = multi_return()
y = results$y
y
# Output:
## [1] 4

This kind of approach is generally preferred over having functions make global assignments, as then calling a function can have unpredictable side effects.

Marius
  • 58,213
  • 16
  • 107
  • 105