ethereum/solidity

Optional function parameters

VoR0220 opened this issue ยท 54 comments

Not too dissimilar to Python, but basically parameters that default to a certain value should they not be filled. Would make for flexibility in contracts.

I fear this rather has to be not too dissimilar to C++, as we have to generate a fixed signature for every function.

I'm not sure I'm understanding the fears here. Can you elaborate as to what this would mean in the grand scheme of the VM/Gas/etc?

Ok, I probably did not use the right words. I think this is a good feature, and it will be more similar to how it is in C++ than how it is in Python.
There will be distinct functions (as far as the ABI is concerned) for each number of given arguments.
It might be difficult to implement that for external functions because we cannot write to CALLDATA.

okay. Cool. :)

axic commented

@VoR0220 do you think we should close this in favour of #240 which has more details?

I dont think so personally.

Well...maybe. Idk. Definitely would need to change the title of the old issue i think.

axic commented

Yes, the title should be changed.

Definitely in favor of including optional parameters with optional defaults in the language. Especially useful as an alternative to constructor overloading.

+1

+1

+1

iluxa commented

+1

I understand that default parameter can be easier to use, but it's unnecessary:

contract Donations {
    event Donated(uint256 value, address donator, string name);
    
    function donate(string _name) public payable {
        emit Donated(msg.value, msg.sender, _name);
    }
    
    function donate() public payable {
        donate("Anonymous");
    }
}

Let's keep Solidity simple.

+1

I believe @MichalZalecki 's solution works as long as there's only one optional parameter

Could this work like C++ does? As far as I am aware, C++ generates one function and just adds the missing ones to a call when a caller doesn't include all arguments.

Added to 0.5.1.

ะก++-inspired solution makes it impossible to implement things like:

function myFunc(uint i = 1)
function myFunc(string s = "")

... which is, probably, force better code design.

@chriseth does your comment mean it's now available? If so, what would the syntax be? or where could I find the documentation?

No, it is not implemented yet. We used "0.5.1" as a codeword for "after 0.5.0", which grew too large after some time and was renamed to "backlog non-breaking".

Whats the status on this piece?

Status is "Neither fully specified nor planned".

Just to make it explicit: do the mentions of C++ mean variadic/vararg-style functions?
Seeing that the abi.encode() functions are variadic made me think that the functionality HAD to be supported, so maybe mentioning that it is not would be helpful.

Variadic functions are a different category, so they are out of scope for this issue. I also think that it is much easier to get something wrong than it is already with default arguments.

I agree that it is easier to get something wrong, and yet lack of variadic functions forces boilerplate and code repetition, which also causes its own problems.

This issue has been stale for quite some time, but I feel like the discussion should be kept relevant.
Answeing to what @MichalZalecki said
Although what he suggested works, it does not work for constructors. If I'd like to have optional parameters in the constructor, I'd have to duplicate my constructur, one with the parameters and one without them, and would get an error while compiling saying that I already have a constructor defined elasewhere.

axic commented

Changing the way the constructor works would be a breaking change beyond the compiler/language, but every web3 tool would need to be changed. The reason is the "function signature" is not transmitted for constructor parameters, so there's no way to tell them apart.

Under what circumstances is it important to have different constructors? Why not just create different contracts, inheriting from the same, with different constructors:

contract A {
  constructor(uint a) public { }
}

contract DefaultA is A {
  constructor() A(1) public { }
}

@axic One scenario would be where you have a really flexible agreement. For example you might have a weekly agreement and a monthly agreement. It'd be handy from a dApp point of view to only have to deploy and manage one type of smart contract, then be able to initialise it by just calling different constructors instead of having to deploy a specific type of agreement and manage multiple ones on the app side.

You could absolutely do what you're suggesting and just deploy different contracts for the various types of agreements, it's just really heavy in some cases if the differences are small. Most programming languages I know of support this type of polymorphic constructor, so it's a useful pattern to have available, but there is absolutely a workaround that works as you say.

ะก++-inspired solution makes it impossible to implement things like:

function myFunc(uint i = 1)
function myFunc(string s = "")

... which is, probably, force better code design.

Same as c#, Java, Python etc.

Any update on this feature?

s3hMC commented

How about now?

axic commented

That status is still the same as in #232 (comment):

Status is "Neither fully specified nor planned".

s3hMC commented

That status is still the same as in #232 (comment):

Status is "Neither fully specified nor planned".

That's unfortunate.

i'm working with a constructor that accepts either an existing address if an external contract is known, or it deploys a new contract based on config for that contract if needed

doing this 2-3 times shows why the "why don't you just use inheritance" argument is limited, and function overloading too, because it ends up needing every combination of present/not-present arguments specified

if you have 3 arguments that are optional you need to specify 2^3 contracts/overloads, and so on...

Another use case is testing functions when running dapptools. It would be nice to have functions used for some tests to have optional parameters

alternatively, an Option or Maybe type would work fine by lifting the issue up to the struct level as optional field values would be equivalently expressive

There's an ongoing discussion related to default parameters on the forum: Reducing Calldata Size with Optional/Default Function Parameters. Anyone wants to chime in?

Any update to optional params yet?

@thedavidmeister yes Maybe Monad at struct level would be good to have if Union types are supported.


// syntax could be like
// define Union
Union Optional<address>  { Nothing, Something<address> }

// declare union variable
Optional<address> owner;

// assign union variable
owner = Something(0x0000000000000000000000000000000000001010)

personally i've mostly moved away from using structs like this because the support for it is pretty bad

This issue has been marked as stale due to inactivity for the last 90 days.
It will be automatically closed in 7 days.

Is there a better place to propose Solidity features?

Is there a better place to propose Solidity features?

We're trying to reserve the github bug tracker mostly for near-future planning of features that we're already clear about that we will want to implement - for broader discussions these days we recommend opening a post in https://forum.soliditylang.org/ - if a feature request gets traction there, we will consider including it in our planning.

Is there a better place to propose Solidity features?

It's complicated. To give a bit more context to what @ekpyron already said, we have tons of feature requests in the bug tracker and, in all honesty, we won't ever manage to implement all of that, even if we wanted to. And in many cases we may not even necessarily want to, but until recently our general approach was that if it's not 100% clear we don't and the answer is not "absolutely not", we let it stay and wait for its turn. This is not tenable anymore and we're now trying to more actively prune the issues and limit what's in the tracker to actually actionable issues, aligned with our roadmap.

This does not mean you cannot request features here. But it means that if it's something we won't put on our roadmap, we'll just close it and ask you to discuss it in the Forum instead, especially when the idea is vague. There is a lot of value in people being able to post their opinions and refine the design, and we'll participate in that too, but we want to make it clear that it's not really on track to being implemented. The feature request has been brought to our attention and noted and we'll keep it in mind, but it passively sitting in the issue tracker would not really bring it any closer to being implemented, as proven by the the mass of old issues still sitting here.

If that's not enough and you think the feature is badly needed even though we're not convinced, the best way is to just talk to us. You can do that on the Forum but feel free to also come to the Matrix chat, tweet at us or come to one of the team calls and talk with us in person. We're always open to suggestions and we'll actually change our minds if you can show us compelling use cases. We often have limited data on how particular changes will affect contracts in the wild so bringing some well-reasoned arguments and examples to design discussions can go a long way.

@cameel, understood. Every project ends up with a backlog of stuff somewhere that never gets implemented. The devs always want to just close everything, while the stakeholders want things logged, so this tension isn't unusual, I'm just wondering where that is for Solidity. Usually there's a big list somewhere and the thing the devs actually look at is a different board.

I don't think a forum post will bring this any closer to reality, and it's not a task list, so it'll just fall off into darkness there too.

Does this feature request exist on the roadmap? It sounds like if not, we should close this issue and accept it's not coming, then point people here when they ask about it in the future.

This is our current roadmap: https://github.com/orgs/ethereum/projects/26. It only contains high-level issues for ~1 year ahead.

We do track bugs and smaller features in issues. We have a set of labels to show how the issue fits into our roadmap: must have (in 1.0), must have eventually (in 2.0), should have, nice to have. This is basically that big list you mentioned and the boards we have are just a view into it (we're all devs here :)). Anything else is not decided. Either not decided yet (we don't have 100% issues labeled with this) or does not seem compelling enough.

I don't think a forum post will bring this any closer to reality, and it's not a task list, so it'll just fall off into darkness there too.

It's not meant to be one. We specifically want things to be discussed there, but not automatically become TODO items for the team just by the virtue of being discussed.

Does this feature request exist on the roadmap? It sounds like if not, we should close this issue and accept it's not coming, then point people here when they ask about it in the future.

It does not and we'll probably end up closing it. In this case it's more the case of not being enough of a priority to go on the roadmap. I don't think there are very strong arguments against it so it might return in some form in the future if there's demand.

We have enabled the stale bot now so these issues will get closed off gradually, but we're also taking note of which ones are important enough to people that they comment. This one is one of the few still being asked about so it shows that there is some demand.

Yup, got it.

So what should we do for next steps here, just keep bumping when the stale bot chimes in, or?

This discussion is better suited for our Forum. @cameel provided a thorough explanation of our strategy regarding these issues, as such we're closing it for now.

Still +1 :)