Impure language features

I/Oや,set! 等の変数への破壊的代入が純関数的でないのは明らかだ.しかしそれらを一つも使わなくとも継続を使ったSchemeプログラムが純関数的でないという例があったような,なかったような... 見かけたのは確か

(define (foo) ... (call/cc (lambda (k) ...)) ...)  ; is this impure function?

(define (bar p q) ...)
(bar (foo) (foo))

(define (bar-1 p) (bar p p))
(bar-1 (foo))

みたいな例だったように覚えているが,set!を使わずにどうにかなるものか? (いや異なる2箇所での継続が異なるのは自明なんだが,分かりやすい例が書けるかってこと)

それと例外も純関数的でないのだっけ? まぁかなり外側へ脱出されてしまったら関数が値を「返した」と言えなくなるとは思うが... I/Oや破壊的代入なしでも何がどこまでまずいのかは,適当な教科書がないと分からないな.

int foo(int x) throws RuntimeException {
    if (x == 0) throw new RuntimeException("foo found that x == 0");
    return 100;
}

これを定数100と同一視できないのは明らかだが,えーと,外側に確実に(?)存在するcatchまで含めて解析すれば問題なくない? (CPS変換でコンパイルするなら自明だよね?)それともこれは単純過ぎで,もう少し複雑な例だと破綻が明らかになるのだっけか?