Comments (6)
The case you're bringing up is indeed a mistake that can be easily made with the amount of parentheses involved.
Yet I'm not sure what practical steps can be taken, especially on the library side.
The association of the decorator is whatever expression comes immediately before the .
; the challenge is parsing through the parentheses to figure out what exactly that expression is.
Similar pitfalls happen with mathematical order of operations, and API docs have nothing to do with it: it's a question of code readability.
The most helpful solution I've found is to indent blocks commands on the same level; this becomes easier with prefix syntax (= factories) but is possible also in infix/postfix syntax (= decorators).
Most editors/IDEs also have plugins that color matching parentheses; that might help too.
from allwpilib.
The association of the decorator is whatever expression comes immediately before the
.
Either I misunderstand what you mean or this is not correct - either are the problem I suggest fixing at least with more "inline" documentation (more words, examples) because I, too, can't think of a better syntax to mitigate the problem other than using sequence
instead of .andThen()
.
In my example e
the last .withTimeout(1.)
is "physically" attached to the immediately preceding
.andThen(run(()->System.out.println("command 3e " + Timer.getFPGATimestamp())))
BUT that is not the command that is modified. The command that receives the timeOut
is the first command that is far above - the
run(()->System.out.println("command 1e " + Timer.getFPGATimestamp()))
Yes, the correct placement of that last timeOut
for what I meant to do is to the left of one more )
such that it modifies the run
command instead of erroneously attempting to modify the andThen
which it cannot do but it looks like it should be doing.
from allwpilib.
In my example e the last .withTimeout(1.) is "physically" attached to the immediately preceding
.andThen(run(()->System.out.println("command 3e " + Timer.getFPGATimestamp())))
BUT that is not the command that is modified. The command that receives the timeOut is the first command that is far above - the
run(()->System.out.println("command 1e " + Timer.getFPGATimestamp()))
Note what's going on here:
run(()->System.out.println("command 1e " + Timer.getFPGATimestamp())).withTimeout(2.)
.andThen(run(()->System.out.println("command 2e " + Timer.getFPGATimestamp()))).withTimeout(2.)
.andThen(run(()->System.out.println("command 3e " + Timer.getFPGATimestamp()))).withTimeout(1.)
.schedule();
The expression in the lhs/receiver position of that third withTimeout(1.)
is the entire composition.
Each decorator wraps the receiver expression with a composition.
To mirror the math metaphor, the difference is similar to the difference between the following two expressions:
1 * 2 + 3
1 * (2 + 3)
Or in this case with commands:
// Sequence of a and b, with a timeout on the sequence.
a.andThen(b).withTimeout(s)
// Same as before, extract temp to a variable
tmp = a.andThen(b)
tmp.withTimeout(s)
// ---------
// b has a timeout and is added to a sequence after a
a.andThen(b.withTimeout(s))
// Same as previous, extract temp to variable
tmp = b.withTimeout(s)
a.andThen(tmp)
I hope this is clearer.
from allwpilib.
Yes, I like your example; this is exactly what I suggest is needed in the methods' Javadocs. Here's a proposed slight change to the existing wording of the withTimeout()
Javadoc starting at the "Note:" and includes your examples. I think this will go a long way toward understanding and ease of use for the students. I suggest essentially similar examples for other decorators like .deadlineWith()
and andThen()
.
Note: This decorator works by adding this decorating command to the previous command or composition and creating a new composition. The command composition returned from this method can be further decorated without issue.
// Sequence of a, b, and c with a timeout on the sequence.
a.andThen(b).andThen(c).withTimeout(s)
// same as
sequence(a, b, c).withtimeout(s)
// how it works: each decorator applies to the single previous composition and creates a new composition
tmp1 = a.andThen(b)
tmp2 = tmp1.andThen(c)
tmp3 = tmp2.withTimeout(s)
//-------
// To apply a timeout to only the third portion of the sequence
a.andThen(b).andThen(c.withTimeout(s))
// same as
sequence(a, b, c.withTimeout(s))
The command the decorator was called on cannot be scheduled independently or be added to a different composition (namely, decorators), unless it is manually cleared from the list of composed commands with CommandScheduler.removeComposedCommand(Command).
from allwpilib.
I'm still not seeing how this is an API docs issue - it's a readability and order-of-operations issue.
Adding the full content with an example etc to each decorator's docs would be too verbose, but can be added to an frc-docs page.
We can add a "take note of function call receiver association, see {docs link}" (but phrased better) to the API docs along with the double composition notice?
from allwpilib.
Example code in Javadocs is exceedingly rare but it has happened; maybe not this time, though.
Anything that can be done to better document and train users on a couple of idiosyncrasies of compositions is of benefit.
- This example of the surprising object of the decorator and
- the surprising case of the default command of a subsystem is not activated within a composition even if there is no currently active use of the subsystem
account for almost all the errors of command-based usage (once the correct command is selected for the problem).
from allwpilib.
Related Issues (20)
- SysId's units are confusing
- Add a fault management API
- Switch from Google Test to Catch2
- XRP Encoders not reporting Rate to WPILib HOT 1
- roboRIO Team Number Setter crashes while refreshing status
- Segfault when destroying AprilTag detector
- be able to use InterpolatingDoubleTreeMap.put().put()... inline HOT 9
- Upgrade to PMD 7.1.0 HOT 1
- Remove RuntimeLoader and RuntimeDetector
- C++ command based examples don't all use CommandPtr HOT 3
- Example of LTVUnicycleController with path following
- ElevatorExponentialProfile example HOT 1
- Add usage reporting ID for DataLogManager (and/or DataLog)
- CMake: macOS: glassnt Library Does Not Link HOT 10
- Add abseil-cpp as a 3rd party library HOT 2
- Add Example Command-Based Best-Practices
- Deprecate robotInit() HOT 2
- CommandRobot discussion HOT 3
- DifferentialDrivetrainSimTest doesn't converge (sometimes) because of LTVUnicycleController HOT 1
- Add `Twist2d ChassisSpeeds::ToTwist2d(units::second_t dt) const`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from allwpilib.