stan-dev / rstan

RStan, the R interface to Stan
https://mc-stan.org
1.04k stars 265 forks source link

rstan::stanc doesn't always return an object #342

Open syclik opened 7 years ago

syclik commented 7 years ago

Summary:

stanc doesn't do as the doc says. It only returns an object when it is successful. When it is unsuccessful, it doesn't return.

Description:

It's hard to use stanc programmatically due to inconsistent output.

Reproducible Steps:

library(rstan)

r <- rstan::stanc(model_code = "foo")
str(r)

Current Output:

> r <- rstan::stanc(model_code = "foo")
SYNTAX ERROR, MESSAGE(S) FROM PARSER:

ERROR at line 1

  1:    foo
       ^

PARSER EXPECTED: <model declaration (or perhaps an earlier block)>
Error in rstan::stanc(model_code = "foo") : 
  failed to parse Stan model 'foo' due to the above error.
> str(r)
Error in str(r) : object 'r' not found

Expected Output:

> r <- rstan::stanc(model_code = "foo")
SYNTAX ERROR, MESSAGE(S) FROM PARSER:

ERROR at line 1

  1:    foo
       ^

PARSER EXPECTED: <model declaration (or perhaps an earlier block)>
Error in rstan::stanc(model_code = "foo") : 
  failed to parse Stan model 'foo' due to the above error.
> str(r)
List of 5
 $ status       : logi FALSE
 $ model_cppname: <not sure what goes here>
 $ cppcode      :  <should be empty>
 $ model_name   : chr "anon_model"
 $ model_code   : atomic [1:1] model { }
  ..- attr(*, "model_name2")= chr "anon_model"

RStan Version:

2.12.1

R Version:

3.3.1

Operating System:

Mac OS X 10.11.6.

bgoodri commented 7 years ago

That's how R works when an error is thrown by a function.

> y <- sqrt(z)
Error: object 'z' not found
> y
Error: object 'y' not found

You can wrap expressions inside try() in which case you get either the exception or the object.

syclik commented 7 years ago

That isn't how R works. That's how R works when the object can't be found before it gets to the function. The function still returns.

Example on how it throws when the object can't be found:

> z
Error: object 'z' not found

Example on how it still returns when the input is passed in:

> z <- -1
> y <- sqrt(z)
Warning message:
In sqrt(z) : NaNs produced
> y
[1] NaN

The doc for the function states that it would return a named list.

bgoodri commented 7 years ago

On Sat, Oct 15, 2016 at 12:36 PM, Daniel Lee notifications@github.com wrote:

Example on how it still returns when the input is passed in:

z <- -1> y <- sqrt(z)Warning message:In sqrt(z) : NaNs produced> y [1] NaN

That code doesn't throw an error. If there is an error, execution ordinarily stops before there is a return.

sakrejda commented 7 years ago

In R you usually do this programmatically by writing something like (from memory, I think it's a "simpleError" not "simple-error" or "simple_error"):

r <- try(expr=rstan::stanc(model_code = "foo"), error= function(e) return(e))
if (class(r) == 'simpleError') 
   ... handle error
else 
  ...  proceed normally

A better interface would be to return something that indicates the error as Daniel suggests without needing the wrapper.

sakrejda commented 7 years ago

I guess you can also install error handlers properly for a given class of errors rather than doing them per call as above but... it's... uncommon.

syclik commented 7 years ago

I'm not gonna argue against R's idioms.

If that's the intended behavior, I'll request that the doc be clarified for error vs normal function.

I guess I don't understand the purpose of the status variable in the return type if that can only ever be TRUE. It looks like it was designed to return either TRUE or FALSE depending on the result.

On Oct 15, 2016, at 12:47 PM, Krzysztof Sakrejda notifications@github.com wrote:

I guess you can also install error handlers properly for a given class of errors rather than doing them per call as above but... it's... uncommon.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

dhicks commented 6 years ago

I found this thread searching for a possibly related problem: stanc() can fail without returning an object and also without raising an exception.

test.stan:

data {
    real[10] X;
}

R:

parsed = stanc(file = 'test.stan', verbose = TRUE)
## TRANSLATING MODEL 'test' FROM Stan CODE TO C++ CODE NOW.

The Stan code doesn't parse (real should be vector), but stanc() doesn't raise an exception. It fails silently. This is particularly problematic if I previously assigned some parsed Stan code to parsed, just made changes to test.stan that introduced parsing errors, and then reran the stanc() call. I'm given no warning that parsing failed and yet parsed has a value.

bgoodri commented 6 years ago

I get

  -------------------------------------------------
     1: data {
     2:     real[10] X;
                ^
     3: }
  -------------------------------------------------

PARSER EXPECTED: <identifier>

Are you using the latest version of rstan? And with what OS?

dhicks commented 6 years ago

Stan 2.17.0 rstan 2.17.3 R 3.4.3 OSX 10.13.4

bgoodri commented 6 years ago

And which compiler version?

On Sat, May 26, 2018 at 4:28 PM, Dan Hicks notifications@github.com wrote:

Stan 2.17.0 rstan 2.17.3 R 3.4.3 OSX 10.13.4

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/stan-dev/rstan/issues/342#issuecomment-392286218, or mute the thread https://github.com/notifications/unsubscribe-auth/ADOrqjL5hj4CUzhj1jAZKKwPUrqH_Kyfks5t2brZgaJpZM4KXtYz .

dhicks commented 6 years ago

I'm less sure how to check that. Through my bash shell, clang -v returns clang version 6.0.0 (tags/RELEASE_600/final).

But that's in bash, and I'm not sure how to tell whether Stan uses that clang or some other version.

bgoodri commented 6 years ago

You can do

readLines("~/.R/Makevars")

but it sounds as if @jgabry will have to help you figure out why the exception is not being thrown.

On Sat, May 26, 2018 at 5:18 PM, Dan Hicks notifications@github.com wrote:

I'm less sure how to check that. Through my bash shell, clang -v returns clang version 6.0.0 (tags/RELEASE_600/final).

But that's in bash, and I'm not sure how to tell whether Stan uses that clang or some other version.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/stan-dev/rstan/issues/342#issuecomment-392288706, or mute the thread https://github.com/notifications/unsubscribe-auth/ADOrqv_0U-RfudS3U5lVN1ijdB54J-Q_ks5t2caRgaJpZM4KXtYz .

dhicks commented 6 years ago
> readLines("~/.R/Makevars")
[1] "CXXFLAGS=-mtune=native -march=native -Wno-unused-variable -Wno-unused-function"
[2] "CC=clang"                                                                      
[3] "CXX=clang++ -arch x86_64 -ftemplate-depth-256"                                 
[4] "CXXFLAGS += -Wno-ignored-attributes -Wno-deprecated-declarations"   
jgabry commented 6 years ago

@dhicks sorry for the delay. Nothing jumps out at me as obviously wrong with your setup. @bgoodri is there anything that needs to go in Makevars specific to clang 6?