[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bug?



The problem lies in this definition of while, from initial.es:

fn-while = $&noreturn @ cond body {
	catch @ e value {
		if {!~ $e break} {
			throw $e $value
		}
		result $value
	} {
		let (result = <=true)
			forever {
				if {!$cond} {
					throw break $result
				} {
					result = <=$body
				}
			}
	}
}

If $body executes {return something}, that is {throw return something},
then that is caught in the catcher procedure which then, seeing that
return is not break, executes {throw return something}.  However the
catcher procedure is *not* protected by $&noreturn, and so something is
returned as the value of the catcher -- and hence of the while construct.

Maybe the protection of $&noreturn should be extended to all lexically
enclosed procedures.  Or, maybe that doesn't make any sense.

Apparently, the following slightly more obfuscated version of while fixes
the problem.

fn-while = $&noreturn @ cond body {
	<={ catch @ e value {
			if {~ $e return} {return {return $value}}
			if {!~ $e break} {
				throw $e $value
			}
			result {result $value}
		} {
			let (result = <=true)
				forever {
					if {!$cond} {
						throw break $result
					} {
						result = <=$body
					}
				}
		}
	}
}

- Harald