#' Horizontally Stack Data Frames with Different # of Observations
#'
#' @param ... vectors, matrices or data frames
#' @param simplify = 0 not to convert the result to a matrix if possible.
#'
#' @details
#' Using the data frames in the example section, the core part is:\cr
#' \code{ res <- merge( data.frame(A1m,id=1:nrow(df1m))
#'                , data.frame(A2m,id=(1:nrow(df2m))), by="id" ,all=1) }\cr
#'
#' \cr
#' If simplify=1 is give, if possible, the result will be converted to
#' a matrix.
#'
#' @examples
#' # no overlapping col names
#' merge_df( x=1:2, y=1:5, z=1 )
#'
#' # overlapping col names
#' A <- demomat(5,4,3,cnroot="V")
#' A1 <- A[,,1]; A2 <- A[,,2]; A3 <- A[,,3]
#' A1m <- A1[1:3,1,drop=0]; A2m <- A2[1:2,1:2]; A3m <- A3[1:3,1:3];
#' merge_df( A1m, A2m, A3m )
#'
#' @return
#' A data frame or matrix
#'
#' @export
#'

merge_df <- function( ..., simplify=1 ){
 # horizontally merge objects of unequal # of rows
 # Shin-ichi Mayekawa
 # 20171111
 # all() added to |||: 20190605
 #

 # analyze three dots
 temp=analyze_three_dots( ... )
 name=temp$name
 val=temp$val
 n=length(name)


 # make them a data frame
 if( !is.data.frame(val[[1]]) ){
  val[[1]]=as.data.frame(val[[1]], stringsAsFactors=0, optional=1)
  if( is.null(colnames(val[[1]]))  || all(colnames(val[[1]])=="val[[1]]") )
   colnames(val[[1]])=name[[1]]
 }
 res=data.frame( val[[1]], key___key______=1:nrow(val[[1]])
                 , stringsAsFactors=0, check.names=0 )
 cname=colnames(val[[1]])
 if( n >= 2 ){
  for( i in 2:n ){
   if( !is.data.frame(val[[i]]) ){
    val[[i]]=as.data.frame(val[[i]], stringsAsFactors=0, optional=1)
    if( is.null(colnames(val[[i]])) || all(colnames(val[[i]])=="val[[i]]") )
     colnames(val[[i]])=name[[i]]
   }
   val[[i]]=data.frame( val[[i]], key___key______=(1:nrow(val[[i]]))
                        , stringsAsFactors=0, check.names=0 )
   # Print(i,res,val[[i]])
   res=merge( res, val[[i]], by="key___key______", all=1 )
   cname=unique( c(cname,colnames(val[[i]])) )
  }
 }

 res=res[colnames(res)!="key___key______"]

 # make the result matrix
 if( simplify ){
  vt=vartype(res)
  if( all(vt==vt[1]) ) res=as.matrix(res)
 }

 return( res )

} # merge_df

