2016-03-23 6 views
6

ながら。私は、トラブル動作するように<code>while(TRUE)</code>ループを得ることを抱えているサブ環境でTRUE +ブレーク

l <- list(x = 5) 

while (TRUE){ 
    with(l, if (x > 100) break else l$x <<- x + 5) 
} 

エラーで実行されます:私は思う。この例では、問題の核心になる不思議な

Error in eval(expr, envir, enclos) :

no loop for break/next, jumping to top level

whileループが正常に実行されているように表示されます。

l 
# $x 
# [1] 105 

それ次のエラーが予想どおりに機能するので、サブ環境でbreakステートメントを送信している問題が表示されます。

x = 5 

while(TRUE){ 
    if (x > 100) break else x <<- x+5 
} 

それだけで環境問題の考え方、私も無駄に、eval(break, parent.env())eval(break, parent.frame())breakを交換してみました。

このエラーをどのようにして止めることができますか?


私はsessionInfo()が関連する可能性があるとします

R version 3.2.4 (2016-03-10) 
Platform: x86_64-pc-linux-gnu (64-bit) 
Running under: Ubuntu 14.04.3 LTS 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    LC_TIME=en_US.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8  LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] readxl_0.1.0.9000 data.table_1.9.6 haven_0.2.0  

loaded via a namespace (and not attached): 
[1] rsconnect_0.4.1.11 tools_3.2.4  Rcpp_0.12.1  chron_2.3-47  
+0

'with'を使用する理由はありますか?どうして 'if(l $ x> 100)else else $ x <-l $ x + 100'を破るのはなぜですか? – nicola

+0

@nicola問題のコンテキストは少し異なります。私は本質的なものと信じているものを複製するためにこれを選択しました。つまり、私の実際の使用法では、 '' .data.table'の呼び出しの中で '' break ''が送られます。 – MichaelChirico

+0

ここでコンテキストが分かりやすくなっているので、 l、break) 'は同じエラーを生成します。どうやら 'with'はRが'中断することを期待していない環境を作り出しているようです。 – nicola

答えて

3

のバリアントを@ Vongoの提案は、評価が行われる環境をenvironment()で取得し、次にevalq()を使用してbreakは正しい場所で評価されます。

l <- list(x = 5) 
while (TRUE){ 
    env <- environment() 
    with(l, if (x > 100) evalq(break, env) else l$x <<- x + 5) 
} 

これにより、テキスト文字列の解析が回避され、その理由でハッキリではないようです。キャプチャされた環境で評価すると、envは、ループが.GlobalEnvだけでなく、Rコードのどのレベルにあっても許可します。これは非ローカルジャンプ(別名GOTO)に似ているため、コードについての理由を考えるのが難しくなります。

+0

も ​​'evalq(break、parent.env(environment()))'です。 'break'が間違った環境に送られた場合、なぜ元のコードが無限ループでなかったのかまだ分かりません。何らかの理由? – MichaelChirico

+0

@MichaelChiricoは、プログラマーが誤って呼び出しスタックを変更する可能性があるため、検出のために呼び出しスタックの順序に頼るのではなく、env =を明示する方が良いです。元のコードでエラーが発生し、エラーの結果としてループが終了しました。 –

+0

オハイオ州は完璧な意味を持っています。 – MichaelChirico

1

たぶん私は、問題のすべての利害関係を理解し​​ていないが、あなたは試みることができる:

l <- list(x = 5) 
while (TRUE){ 
    with(l, if (x > 100) eval(parse(text="break"), envir=.GlobalEnv) else l$x <<- x + 5) 
} 
+0

'break'を評価するために場所を正確に把握していた申し訳ありませんが、ちょうど戻ってきます。私は@Martin Morganがこのアプローチを説明し、それを改善したと思います。名誉! – Vongo

関連する問題

 関連する問題