Default Argument values?

I'm attempting to implement parameter parsing for a project of mine and I can't seem to get default values for arguments working. For instance:

struct Dragonfly: ParsableCommand {
    @Argument() var enableLogging: Bool
    
    func run() throws {
        DragonflyServer.run(enableLogging: enableLogging)
    }
}

Dragonfly.main()

This always requires a value to always be passed. Is this not the intended use for @Argument? I see that @Option can take a default, so is that what I should use?

Additionally, it seems that @Argument() is required instead of @Argument, is that just a byproduct of the wrapper implementation? Is it something that can be fixed?

I’m not entirely sure what you’re trying to do, but you might want to use @Flag var enableLogging: Bool instead of @Argument.

2 Likes

There are 2 ways you could do it @Option and @Flag

@Flag - for Bool defaults to false
@Option- you can specify the default value
Example below shows them and both of them can be omitted and will result in default values.

    //When using Flag, defaults to false
    //If user specifies --enableLogging, then it will be true, if user ignore it will be false
    //This can be omitted
    //Usage: [--enableLogging]
    @Flag()
    var enableLogging: Bool
    
    //When using Option, you can specify the default value
    //This can be omitted
    //Usage: [--flag2 <flag2>]
    @Option(default: true)
    var flag2: Bool

Generally, if the wrapper provides init() we can remove (). It doesn't seem to work with one with default values like what Argument provides: init(help: = default). Not sure if we should add init(), or add support to property wrapper.

You can drop the parens (i.e. just do @Foo) if the property wrapper has an init() or init(...) where all arguments have default values.

@Option does what I needed. I think I was confused about @Argument vs. @Option vs. @Flag. Still seems like @Argument should support default values.

It doesn't work. It is treated as not having default value. Which, for ParsableCommand, it forces me to write init() myself.


This fails to compile, Main.init() is missing.

import ArgumentParser

// Error: Type 'Main' does not conform to protocol 'ParsableArguments'
struct Main: ParsableCommand {
    @Argument var i: Int

    func run() throws {
        print(i)
    }
}

Main.main(["33"])

This works

import ArgumentParser

struct Main: ParsableCommand {
    @Argument() var i: Int

    func run() throws {
        print(i)
    }
}

Main.main(["33"])

I haven't looked at the code for this library, so I am not sure what's going on, but this works:

@propertyWrapper 
struct Foo {
  init(wrappedValue value: Int = 0) {
    self.wrappedValue = value
  }

  var wrappedValue: Int
}

struct Bar {
  @Foo var value: Int
}

let bar = Bar()
print(bar.value) // 0

To clarify, I was just talking in general that initialisers with all default args in property wrappers are supported now as of Swift 5.2 (I implemented them here), which allows you to do @Foo without the need to add parens.

I see what's going on now, current non-beta Xcode (11.3.1) still uses Swift 5.1.3. Ah well, I can wait :hugs:. Thanks for the fix btw :partying_face:.

1 Like

Since v0.0.3, it is now possible to define a default value for the @Argument.