-
Notifications
You must be signed in to change notification settings - Fork 2
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
reusing specified code as building blocks for other specs ? #1
Comments
Just to clarify, the idea is to run a specify(), let that solve and then register that as a building block for use in other specify() calls - preferably, without having to save anything to disk |
Looking at the docs, I think I am really asking about this:
|
@UniqueFool it's still in an experimental state and rough around the edges but I'm glad you like it :) You can see a lot of the features run through their paces in testSolves.i.js. To compose specs take a look at usages of the
Unfortunately I haven't implemented anything along these lines, but it's doable. |
thanks for getting back in touch, I have been looking exactly at the files you mentioned: buildingBlocks.js and testSolves - I think you mentioned that in one of the readmes. In fact, I also looked at the doubleIt specs specifically, because I ended up using the factorial as an example that I adapted. Named arguments would be "icing on the cake" - so mainly a matter of making the output more useful for human programmers. So if it is difficult, ignore that idea ;-) That being said, this is really cool, I just to find more examples that I can adapt to learn how everything works. For instance, I just spent 1 hour trying to figure out how to make it use a tryCatchFinally block in conjunction with a callback and an argument that may throw an exception, wanting it to return true/false. I specifically looked at your RegExp examples, and was trying to adapt those to come up with a spec that checks if a regex is valid or throws an exception, i.e. in the form of::
Any ideas ? Thanks again PS: A little explanation regarding the annotation syntax for those as() calls would be also nice to have |
I haven't been working on this much recently. The main outstanding item for me is that the type system needs to be refactored. I will add this to my todo list though.
Here is an example of using specify('add',
given(1, 2,
shouldReturn(3),
as('adding 1 and 2 should return 3')),
use('Number+')) The output would look like this:
We can use var stringToRegExp = express('stringToRegExp',
takes(String),
returns(RegExp),
as('RegExp(@String)'))
As a side note, var stringToRegExp = express('stringToRegExp',
takes(String),
returns(RegExp),
as(function() { /* RegExp(@String) */ })) The way this works is inductive.js calls toString on the function passed to To answer your question about // Name the function
specify('isValid',
// Since some of our test cases throw we have to tell inductive.js
// to ignore this. Normally inductive.js will stop searching if it
// encounters an error.
setOptions({ allowErrors: true }),
// This is an invalid RegExp so it should return false
given('[', shouldReturn(false)),
// This is valid so it should return true
given('abc', shouldReturn(true)),
use(
// We need the expression we created earlier
stringToRegExp,
// Use the `tryCatch` building block
'tryCatch',
// We are using constants for `true` and `false`:
value(true),
value(false),
// We are invoking the `RegExp` constructor for its side-effect.
// The comma operator lets us ignore the result of `RegExp`
// and return a boolean. In the generated function
// you will see something like `return (RegExp(arg0), true)`
',',
// The way I have set up the `tryCatch` building block is that it requires
// a function to handle the error in the `catch` clause.
// This building block, `functionExpressions()`, tells inductive.js
// to write function expressions out anywhere it runs into a building block
// that needs a function.
functionExpressions())) If we set the verbosity to 1 the output looks like this:
An explanation of the generated program: function isValid(arg0) {
return (function() {
try {
// Invoke RegExp for its side-effect then return true
return (RegExp(arg0), true)
} catch(err) {
if(typeof err !== 'object' || !(err instanceof Error))
err = new Error(err)
// The `tryCatch` building block uses the function expression here:
return (function fn(arg1) {
// arg1 is of `Error` type. We don't use it in this program however.
return false
})(err)
}
})()
// The reason `tryCatch` is wrapped in an IIFE is that this is my solution to make
// it act as an expression (with a return value), not a statement.
// All building blocks in inductive.js have to be expressions.
} For reference, this is how the express('tryCatch',
takes(typeParameter('a')),
takes(
functionType(
takes(Error),
returns(typeParameter('a'))), '@catchFn'),
returns(typeParameter('a')),
as(function() { /*
(function() {
try {
return @'a
} catch(err) {
if(typeof err !== 'object' || !(err instanceof Error))
err = new Error(err)
return (@catchFn)(err)
}
})()
*/ })) |
hey, thanks so much for taking the time to share all this - that will keep me busy for a while, I was actually thinking of the as syntax as some kind of templating mechanism, but it is good to have an actual explanation now. Besides, thanks also for specifically going into so much detail and covering my specific use-case, it's really appreciated ! |
Hi,
thanks for providing this, it's really awesome - I skimmed through the buildingBlocks.js and the tests and could not find an answer to my question: is there a way to reuse a spec as the building block for another spec, i.e. so that specs can be incrementally "solved" ?
Besides, is there a way let it use named arguments ?
Thanks
The text was updated successfully, but these errors were encountered: