multiple arguments specification

Issue #5 resolved
Dmytro Lituiev created an issue

Hi, I cannot figure out how the multi-values arguments are supposed to be fed in.

I try ` p <- add_argument(p,'--trait', short = "-i", nargs=Inf, help='trait (expression) file') ...

and feed -i file1 -i file2 but I am getting: Extra arguments supplied (--trait file2)

Can you please provide an example for this case? Thank you!

Comments (10)

  1. David Shih repo owner

    Hi Dmytro,

    Sorry for not having provided an example. I'll put one up soon. Your add_argument invocation looks right, but I have not implemented support for nargs=Inf yet (I thought I did when I wrote the documentation. Sorry.)

    So to make your code work right now, you will need to do:

    p <- add_argument(p, '--trait', short = '-i', nargs=2, help='two trait (expression) files')
    

    When I implemented support for multi-value arguments, I was hoping to simplify specification for a fixed number of arguments and possibly infer the number of arguments based on supplied default values. So, you can also do

    p <- add_argument(p, '--trait', short = '-i', help='two trait (expression) files',
      default=c('trait1.txt', 'trait2.txt'))
    

    When feed in the command line arguments, you should do the following instead:

    script -i file1 file2
    

    I'll look into supporting a unspecified number of values for an optional argument.

  2. Dmytro Lituiev reporter

    I need exactly indefinite number of arguments. Otherwise one can reserve another optional argument for the second file and this would solve the issue.

    Basically I want my script to do the same job on some number of files in order to reduce the loading overhead of R libraries. Running it (with nargs=Inf ) as you suggest script -i file1 file2 currently returns Extra arguments supplied (file2).

  3. David Shih repo owner

    Your code should now work as expected. If you have any positional arguments, be sure to insert another optional argument or flag (e.g. --) after the indefinite optional argument:

    script -i file1 file2 -- pos_argument_value
    
  4. Felix Kuehnl

    Hello, thanks for this useful fix. For me this too works well:

    parser <- arg_parser('args')
    parser <- add_argument( parser, arg = '--ifile', help = "Input file name",
                            nargs = Inf )
    args <- parse_args( 
        parser,
        argv =  c( "-i", "test1", "test2" ) 
    )
    

    However, it would be nice to have the same feature for positional arguments, too:

    parser <- arg_parser('args')
    parser <- add_argument( parser, arg = 'ifile', help = "Input file name",
                            nargs = Inf )
    args <- parse_args( 
        parser,
        argv =  c( "test1", "test2" ) 
    )   # ERROR: Extra arguments supplied (test1, test2)
    

    Would it be possible to add this feature, too? Thanks alot in advance!

  5. David Shih repo owner

    As previously discussed, it is not a good idea to allow positions arguments to have an indefinite number of arguments.

    One problem is in the case where there are multiple position arguments and at least one has an indefinite number of arguments. This results in ambiguity in assigning passed values to position arguments.

    The command line interface should be an ambiguous.

    I'll generate an error for this usage.

  6. Greg Minshall

    maybe i have the terminology wrong. my "positional argument" are things like after the last option, as in ls(1), e.g.,

    ls foo bar yet fubar
    

    i.e., the arguments not associated with any option (i guess most often, as in the ls example, filenames).

    (i may be missing something, but i don't see any ambiguity there.)

    is there support, or thoughts of support, for those?

    cheers.

  7. David Shih repo owner

    Position arguments are arguments specified by their position in the argument list. Optional arguments are those following argument labels (e.g. --args).

    In your ls example, there is only one positional argument, [FILE], as the man page indicates:

    ls [OPTION]... [FILE]...
    

    (The notation used for all optional arguments is simply summarized by [OPTION] here.)

    The [FILE] positional argument may take multiple values. Since there is only one positional argument, there is no ambiguity if it takes an infinite number of values.

    My concern with ambiguity only applies when there are multiple positional arguments, each taking possibly an infinite number of values.

    The situation where there is only one positional argument that may take infinite number of values, may be worth implementing, as along as following conditions are met:

    [1] Allow only one positional argument to take an infinite number of values.

    In the following example, how would you know whether <arg2> or <arg3> should consume the value banana?

    usage:

    program <arg1> <arg2>... <arg3>... <arg4>
    

    call:

    program apple orange banana pineapple cherry
    

    [2] If there are multiple optional arguments, correctly handle the consumption of values by each optional argument. For example,

    program <arg1> <arg2>... <arg3> <arg4>
    

    Here, <arg1>, <arg3>, and <arg4> each consume 1 value, and <arg2> consumes an unspecified number of values. <arg2> needs to consume all but the last two value.

    I do not immediately see a quick patch to implement this feature in the current code base. Pull requests that satisfy the above conditions are welcome.

    The current workaround is to use an optional argument that can take an infinite number of values. By using this approach, you can have multiple optional arguments that can each take an infinite number of values, which is far more flexible than allowing one and only one positional argument to take an infinite number of values.

  8. Greg Minshall

    David,

    i've been looking at the code a bit. one thing that occurs to me is that for flags/options (things that start with a dash "-" or two), nargs is how many things there are after the dash. whereas, my desire, really, for positional arguments is for nargs to be the number of "things" (since there is no indicator). maybe this is obvious from your definition of "positional".

    i would probably simplify things so that if a positional parameter is specified with nargs=Inf, then it must be the last positional parameter, and no options/flags can occur after it. more generally, if a variable number of nargs is allowed (i think only nargs=Inf is in the current spec), then that positional parameter must be the last one in the argument list. (also, it should be possible to allow the "arbitrary number" to be zero; it would probably be nice if it could be forced to be at least one, but maybe not at this time.)

    does that make sense/would that be acceptable to you? (i can imagine you might feel that a variable number of positional parameters should be able to be terminated by a "--" or other option/flag, as i notice in examples on the internet, python, etc., it seems oddly [to me] common.)

    i don't totally understand the code -- an understatement -- partly as evidenced i'm not sure how to make a positional parameter with nargs=2 work:

    > ap <- arg_parser("this")                                                                    
    > ap1 <- add_argument(ap, "file", "file we want", nargs=1)                                    
    > ap2 <- add_argument(ap1, "type", "type we want", nargs=1)                                   
    > parse_args(ap2, c("this", "that"))                                                          
    [[1]]
    [1] FALSE
    
    $help
    [1] FALSE
    
    $opts
    [1] NA
    
    $file
    [1] "this"
    
    $type
    [1] "that"
    
    > ap2 <- add_argument(ap1, "type", "type we want", nargs=2)                                   
    > parse_args(ap2, c("this", "that"))                                                          
    Error: !is.finite(nargs) || length(object) == nargs is not TRUE
    > parse_args(ap2, c("this", "that", "some"))
    usage: <script> [--] [--help] [--opts OPTS] file type
    
    this
    
    positional arguments:
      file                  file we want
      type                  type we want
    
    flags:
      -h, --help                    show this help message and exit
    
    optional arguments:
      -x, --opts OPTS                       RDS file containing argument values
    Error in parse_args(ap2, c("this", "that", "some")) : 
      Extra arguments supplied: expecting 2 values but got (this, that, some).
    > parse_args(ap2, c("this", "that some"))
    Error: !is.finite(nargs) || length(object) == nargs is not TRUE
    > 
    
  9. David Shih repo owner

    I just confirmed that this is a bug. Specifying nargs for a positional argument is currently broken.

    I initially added the nargs argument for allowing optional arguments to consume multiple values.

    I'll have to look into a fix for this.

  10. Log in to comment