1

Ok, suppose I create a very simple histogram with my function:

hist(my.fun(100))

The title of my histogram show Histogram of my.fun(100). This is perfectly fine for me! I like the way R automatically recognize my.fun(100) and put it in the title and label.

But then I do complex computation, says:

n <- my.complex.algo.that.compute.size(args)
hist(my.fun(n))

This time, the title show Histogram of my.fun(n). Which gives no clue on how large is n. I know that n will be evaluate to some integer, suppose that for this run n == 42, I like to see the title of histogram show Histogram of my.fun(42) instead.

Is this possible without specifying the title by myself (no main=paste(...)). I've try these and fail:

hist(my.fun(`n`))
hist(my.fun(eval(n)))
neizod
  • 1,582
  • 15
  • 24
  • 6
    "How can I do something in R without using the argument that's provided to do exactly that?" is a very odd question. Obviously your attempts fail. On the help page of `hist` it says you change the title with the argument `main`. If you don't like that, you write your own hist function that does what you want. – Joris Meys Jul 15 '17 at 09:12
  • 2
    Maybe we'd be less perplexed if you explain why? Particularly, "(no main=paste(...))", why? – rosscova Jul 15 '17 at 09:35
  • I find that R have very weird evaluation aspect (compare to other general purpose language such as C, Python). For this one I'm curious why `hist()` can catch the expression `my.fun(100)` and make it a string in title later! – neizod Jul 15 '17 at 09:54
  • @neizod The evaluation aspects of R are nothing weird once you understand them. R comes from the corner of functional programming languages, and works with closures. If you look at the source code of `hist`, you see immediately how exactly the function does that. Or Spacedman's answer shows you that as well. – Joris Meys Jul 15 '17 at 10:17
  • @JorisMeys since I'm very new to R, I don't know where to look for the source code of `hist` function (I've try searching for `hist` on and felt overwhelmed). A link to exact file is welcome. Thanks in advance. – neizod Jul 15 '17 at 11:13
  • @neizod You can just type the name of the function at the console -without parentheses! - press enter, and you see the source code of that function. If you want to know more about the evaluation system `hist` uses, check this page: http://adv-r.had.co.nz/Computing-on-the-language.html – Joris Meys Jul 15 '17 at 11:25
  • 3
    You don't know where to look for the source code of `hist`? There's a [question for that](https://stackoverflow.com/q/19226816/271616). ;-) – Joshua Ulrich Jul 15 '17 at 12:09

2 Answers2

3

If you restrict the thing you are histogramming to a function of a single argument, n, then you can do this:

nhist = function(f,n){
   hist(f(n),
   main=paste0(
     "Histogram of ",
     deparse(substitute(f), 500),"
     (",n,")", collapse = "\n"))}

Which you call slightly differently:

Z=100
nhist(runif, Z)

You have to pass f and n separately since there's no way hist can figure out what was passed to f.

Spacedman
  • 92,590
  • 12
  • 140
  • 224
0

After I look up and learn from hist source code, I can say that this is impossible when hist is called as top level function. Because of this line in the source code:

xname <- paste(deparse(substitute(x), 500), collapse = "\n")

The deparse(substitute(x)) try to catch (not-yet-evaluated) expression tree and turn it into a string. This mean whatever expression I type as first argument for the hist function, it will be turned into a string right away without any evaluation.

To achieve this, I need to force evaluation at some leaf of the expression tree. Which (luckily enough that I just learn about it) can be done with substitute, and use do.call to pass the evaluated expression tree as an argument for hist function:

n <- my.complex.algo.that.compute.size(user.args)   # suppose this calc return 42
evaluated.arg <- substitute(my.fun(x), list(x=n))   # now this will be my.fun(42)
do.call(hist, list(evaluated.arg))
neizod
  • 1,582
  • 15
  • 24