Open bennlich opened 3 years ago
Won't this lead to a huge amount of error checking everywhere? I realize we've decided on a different audience than initially (I.e. JS programmer to novice), but I'd like to minimize the disruption.
We could use defaults for more method arguments, so something like forward(d = 1). Probably should use distance rather than d.
Math.sin('dog') returns NaN for example. It doesn't throw an error, alas, but then STEM folks may not know about try/catch.
If we do want to have special things for the novice user, I think I'd like to take the approach of creating a NL "app" which doesn't use MV split or radians or ... See the list I posted in AS channel on how to get to degrees & headings.
Here's what I did that made me run into that error: 1) Click run forever on one of the blocks that moves turtles 2) Try changing forward(1) to forward(10). All good. 3) Now try changing to forward(5). When you get to forward(), the turtles positions become NaN, and you can't restore them without resetting the model.
Math.sin('dog') returns NaN for example.
I think returning NaN
is fine behavior. But letting the turtle's internal state become NaN is bad because then you can never get out.
Won't this lead to a huge amount of error checking everywhere?
That's a good question. It looks like this also happens with turtle.rotate()
. Maybe we can survey and see how many places this would show up.
Check out the slack chat: https://redfishgroup.slack.com/archives/C033X4FF8/p1614118299077300
It could be that we solve error checking depending on how we resolve JS <> NL geometry.
Part of me thinks we should leave AS as a JS geometry with simple utils,js helper functions dealing with conversions such as radians<>degrees & euclidean<>compas geometry. If so, it would be easy for these helpers to also do error checking.
Similarly, I'm looking into a transform approach of the 40 functions that need it. They would pass all angles, relative or absolute, thru the utils.js helpers, thus also being able to check them.
But that doesn't solve the positions. But setxy & setxyz could just multiply all their args and if a NaN pops out, we throw an Error.
But I completely agree, it would be great to have deeper error checking. And you get to find most of them with your fresh eyes! Thanks!
Check out the slack at https://redfishgroup.slack.com/archives/C033X4FF8/p1614118299077300
@backspaces I did a little user-testing of the homepage tutorial, and this came up again. I think we should figure out a solution before launching the new site.
This problem shows up specifically in a live-update situation, where a snippet of code is getting constantly re-evaluated while being edited.
My specific desire is: prevent turtle x, y from ever becoming NaN
due to a call to e.g. turtle.forward()
or turtle.rotate()
with no args.
The more general way to say it is: prevent the model from ever entering a "bad state" due to an improper function call. A "bad state" is one that can't be recovered from without rebuilding the whole model. But for launch, I think we should just solve the specific case of the turtle NaNs.
setxy & setxyz could just multiply all their args and if a NaN pops out, we throw an Error.
Does this still seem like a reasonable way to go?
Agreed, wouldn't hurt. Time for AS to grow up!
Does TypeScript handle errors for you?
@cody points out TS type checks at compile time so isn't that useful unless the modeler uses TS and we supply type info. Even then, it probably isn't what we want, which is inherently runtime checking.
I guess a set of type utilities may be useful, but because JS pretty much sucks at that (no Integers, too primitive in general)
If you're worried about performance hits, maybe we could have only a dev build that does these checks?
Yes I hear the concern over adding a ton of error checking code, what a PITA. But I agree that given the audience we are targeting (novice) we want to protect them.
I think this calls for a type sanity check--as we are mostly expecting numbers as arguments we could start with just ensuring that the arguments are number like values (Number(arg) !== NaN)
, throwing an error for a try/catch would be the cleanest dev friendly approach. A user friendly approach might be a noop and emitting a warning to the log.
if (Number(arg) !== NaN) {
console.warn('argument passed was not a number. Got this instead: ', arg);
return;
}
It does add some overhead, I'd be interested in how much.
I'm monkey-patching Turtle3D in the IDE and tutorial for now:
import Turtle3D from '/agentscript/src/Turtle3D.js'
let check = (d) => {
if (typeof d !== 'number') {
throw new Error(`Function expected a number, got ${d}`)
}
}
Turtle3D.prototype._forward = Turtle3D.prototype.forward
Turtle3D.prototype.forward = function(d) {
check(d)
this._forward(d)
}
Ditto for right, left, and rotate.
This is a Good Thing!
Sorry for my getting behind. And I wasn't clear where the most important issues are for you: docs, one-pagers refactoring, etc.
I take it that error checking is the most important? It makes sense due to the IDE being interactive. And I like the check function approach.
Are you mainly concerned about Turtle2D? Maybe 3D?
I'm fine dropping my current stuff to get back into helping.
OK, I committed and npm published a first pass of error checking.
Let me know if it works. I'll look at Turtle2D to see if it needs checking too, Turtle3D subclasses it.
Right now
turtle.forward('dogs')
or justturtle.forward(undefined)
leavesturtle
in a broken state, stranded at NaN, NaN. Instead,turtle.forward('dogs')
should raise a ValueError.I noticed this when editing running code in the landing page tutorial.