-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discuss the design of flags #29
Comments
Okay, first impressions:
NB. Meaning blocks receive the match as 1st argument and whatever's passed to
NB. That version doesn't make all flags mandatory; what it does require is that all flags have a value even when omitted, which you ensure by defining both the
Now I'm aware it's a little verbose, but at least it's clear. We can think of convenience accessors, maybe a collective way of accessing values like |
About automatically evaluating flags, again, I see flags as parameters. With messages, you don't expect parameters to be executed so that they modify the callee context. Instead, the callee uses whichever parameter it needs at that point. But to enable effectful flags, I think I would favor some explicit iteration in the main block, like Declaration order is under developer control, but I don't think it matches well with evaluation order. Conversely, the user has control over command-line order and will expect it to have meaning, at least in some cases: usually, later flags override or compliment earlier ones. Then you have to consider what object should be affected ( myBuilder := MyBuilder new.
ClapCommand new
add: ((ClapFlag id: #x) meaning: [ myBuilder withX ]);
… The command specification is something that wants to be static, but it closes over the builder which is dynamic (specific to the command execution, or at least to the image session in the current state of things). Of course we have a flexible notion of static in Pharo, but still… I'd like to see a motivating example that relies on building the command specification depending on the context… For me the builder should be instanciated in the command's meaning block, so flags cannot be evaluated before that, but they have to be before the block returns because that means the command has finished running and the image must quit. |
Discussion started at pillar-markup/pillar#440
@cdlm:
If flags have side-effects then their order of execution must be clear; however there is no obvious order that would be valid in all situations. Sometimes the order of declaration in the specification makes sense, sometimes it's the order of invocation on the command line, and it could also be some arbitrary order depending on the application. Some flags can also be repeated.
I didn't want to assume how and when an app should use its flags. So they are best seen as optional parameters that you use when you need their value, instead of an imperative API to a stateful builder. The meaning blocks are there to lift the string passed on the command line into an object value that's useful to the app. We tried a version where the block had a side-effect, but then in the meaning block it looked like
(args at: #all) value.
with no immediate indication of what effect this has.For commands the situation is different because each subcommand selects a narrower subset of the app's behavior. In the end you have one and only one most-specific subcommand, so that makes a convenient entry point.
@guillep:
Yes, and Clap could define an order :). Even more, it could have a default one "definition order" for example. And then accept other strategies like "invocation order", and each command could define the order of flags with a strategy, no?
I understand. But to me, we should take a stand and favour one usage over the other :).
And maybe give hooks to the user to override those decisions.
We will never make a choice that pleases everybody, I'd take that outside the table :P.
My heuristic here is that we should favour most common usages, and leave the freedom to do less common usages.
We are now using a full-grown framework to parse command line arguments, so we should extract the juice from it, no?
I'd like to discuss alternatives, tell me what you think:
=> But, as a side effect, all flags become mandatory, because they are arguments in the block.
In this version, what we have now IIUC, it's the user responsibility to have conditional code to check for the arguments, which I don't like...
I prefer solution 1. I think it is easy to understand and that defining a clear order of execution of flags can simplify the task of the developer (I think definition order is the best one because the developer can foresee what will happen more easily).
Solution 2 is too limiting, and solution 3 too verbose.
But please note that solutions 1 and 3 are somewhat compatible ;). We could use solution 1 and, those people wanting fine grained control could use solution 3.
I did not understand this. My point is that nobody should call
(args at: #all) value.
at all :). It seems superfluous. It should be called automatically.Otherwise, why should I do
value
?If the evaluation could be done automatically when accessing the argument:
or even simpler, because people do not need to understand the semantics of
meaning
:I don't know, tell me what you think about these ideas. I am really convinced that clap could do more :)
The text was updated successfully, but these errors were encountered: