.packageName <- "scope"
"probe" <-
function(x,this,FUN='max',that=this,scope=NULL, ...){
#check input
if (!is.data.frame(x)) stop("'x' is not a dataframe")
len <- dim(x)[[1]]
if (len < 1) stop("'x' has no rows")
if (!this %in% names(x)) stop("'this' is not a column in 'x'")
if (!that %in% names(x)) stop("'that' is not a column in 'x'")
if (is.null(scope)) scope <- vector("list",len)
if (length(scope)!= len) stop("'scope' and 'x' not same length")
#prepare aggregate
skim <- skim(x,this,FUN,scope,...)
#try to probe cells for row with aggregate value 
scope <- scope(x,this,that=skim,scope=scope)
#test for selectivity of probe
if(any(score(scope) != 1)) warning("Some scopes not atomic")
#assign
return(scoop(x,that,scope))
}

"scoop" <-
function(x,this,scope=NULL){
#check input
if (!is.data.frame(x)) stop("'x' is not a dataframe")
len <- dim(x)[[1]]
if (len < 1) stop("'x' has no rows")
if (!this %in% names(x)) stop("'this' is not a column in 'x'")
this <- as.vector(this)
if (is.null(scope)) return(x[[this]])
if (length(scope)!= len) stop("'scope' and 'x' not same length")
#prepare
out <- vector("character",length=len)
#assign
for (i in 1:len){
rows <- length(scope[[i]])
if(rows != 1) out[[i]] <- NA
if(rows == 1) out[[i]] <- scope[[i]][[1]]
}
ref <- array(x[[this]],dimnames=list(row.names(x)))
return(as.vector(ref[dimnames=out]))
}

"scope" <-
function(x,this,FUN='==',that=x[[this]],scope=NULL){
#check input
if (!is.data.frame(x)) stop("'x' is not a dataframe")
len <- dim(x)[[1]]
if (len < 1) stop("'x' has no rows")
if (!this %in% names(x)) stop("'this' is not a column in 'x'")
if (length(that)==1 && that %in% names(x)) that <- x[[that]]
if (length(that)==1) that <- rep(that, len)
if (length(that) != len) stop("'that' is not a column in 'x' and wrong length")
if (is.null(scope)) scope <- vector("list",len)
if (length(scope)!= len) stop("'scope' and 'x' not same length")
if (!is.element('scope',class(scope))) class(scope) <- c('scope',class(scope))
#prepare
FUN <- match.fun(FUN)
#assign
for (i in 1:len){
if (is.null(scope[[i]])) scope[[i]] <- row.names(x)
rows <- row.names(x)[FUN(x[[this]],that[i])]#range of 'this', but only one of 'that'
scope[[i]] <- intersect(scope[[i]], rows)
}
return(scope)
}

"score" <-
function(scope){
#check input
len <- length(scope)
if (len < 1) stop("'scope' has zero length")
#prepare
out <- vector('numeric', length=len)
#assign
for(i in 1:len) out[[i]] <- length(scope[[i]])
return(out)
}

"skim" <-
function(x,this,FUN='max',scope=NULL,...){
#check input
if (!is.data.frame(x)) stop("'x' is not a dataframe")
len <- dim(x)[[1]]
if (len < 1) stop("'x' has no rows")
if (!this %in% names(x)) stop("'this' is not a column in 'x'")
if (is.null(scope)) scope <- vector("list",len)
if (length(scope)!= len) stop("'scope' and 'x' not same length")
#prepare
FUN <- match.fun(FUN)
out <- vector("numeric",length=len)
#assign
for (i in 1:len){
if (is.null(scope[[i]])) scope[[i]] <- row.names(x)
out[[i]] <- FUN(x[[this]][row.names(x) %in% scope[[i]] ],...)
}
return(out)
}

