Reducing local variable duplication

I have a series of unit tests like this,
test_volume1 :: Assertion test_volume1 = assertEqual "volume is correct" True (vol ~= (-1/3)) where p0 = (0, -0.5, 0) p1 = (0, 0.5, 0) p2 = (2, 0, 0) p3 = (1, 0, 1) ...
test_volume2 :: Assertion test_volume2 = assertEqual "volume is correct" True (vol ~= (1/3)) where p0 = (0, -0.5, 0) p1 = (2, 0, 0) p2 = (0, 0.5, 0) p3 = (1, 0, 1) ...
I would like to de-duplicate some of the values in the 'where' clause. Furthermore, I don't want to declare e.g. p0 and p3 at the top level, since later tests may need different values of p0,p3. What I would really like is something like the following. Is it possible?
let p0 = (0, -0.5, 0) p3 = (1, 0, 1) in test_volume1 :: Assertion test_volume1 = assertEqual "volume is correct" True (vol ~= (-1/3)) where p1 = (0, 0.5, 0) p2 = (2, 0, 0) ...
test_volume2 :: Assertion test_volume2 = assertEqual "volume is correct" True (vol ~= (1/3)) where p1 = (2, 0, 0) p2 = (0, 0.5, 0) ...

The where block takes precedence over the global scope so if these points
are generally reused for most tests and only deviate in a few, you could
define them globally to the file and then modify individual ones in the
where blocks of code that needs different values.
Hope that helps
On Mon, Aug 29, 2011 at 8:35 AM, Michael Orlitzky
I have a series of unit tests like this,
test_volume1 :: Assertion test_volume1 = assertEqual "volume is correct" True (vol ~= (-1/3)) where p0 = (0, -0.5, 0) p1 = (0, 0.5, 0) p2 = (2, 0, 0) p3 = (1, 0, 1) ...
test_volume2 :: Assertion test_volume2 = assertEqual "volume is correct" True (vol ~= (1/3)) where p0 = (0, -0.5, 0) p1 = (2, 0, 0) p2 = (0, 0.5, 0) p3 = (1, 0, 1) ...
I would like to de-duplicate some of the values in the 'where' clause. Furthermore, I don't want to declare e.g. p0 and p3 at the top level, since later tests may need different values of p0,p3. What I would really like is something like the following. Is it possible?
let p0 = (0, -0.5, 0) p3 = (1, 0, 1) in test_volume1 :: Assertion test_volume1 = assertEqual "volume is correct" True (vol ~= (-1/3)) where p1 = (0, 0.5, 0) p2 = (2, 0, 0) ...
test_volume2 :: Assertion test_volume2 = assertEqual "volume is correct" True (vol ~= (1/3)) where p1 = (2, 0, 0) p2 = (0, 0.5, 0) ...
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Michael Xavier http://www.michaelxavier.net LinkedIn http://www.linkedin.com/pub/michael-xavier/13/b02/a26

On Mon, Aug 29, 2011 at 11:35:50AM -0400, Michael Orlitzky wrote:
since later tests may need different values of p0,p3. What I would really like is something like the following. Is it possible?
let p0 = (0, -0.5, 0) p3 = (1, 0, 1) in test_volume1 :: Assertion test_volume1 = assertEqual "volume is correct" True (vol ~= (-1/3)) where p1 = (0, 0.5, 0) p2 = (2, 0, 0) ...
test_volume2 :: Assertion test_volume2 = assertEqual "volume is correct" True (vol ~= (1/3)) where p1 = (2, 0, 0) p2 = (0, 0.5, 0) ...
No, this is not possible directly. You have several options. As someone else already suggested, one option is to declare p0, p3 in the global scope and then shadow them in any local scopes where you would like them to have different values. Another option might be to do something like this: [test_volume1, test_volume2] = [ let p1 = (0, 0.5, 0) p2 = (2, 0, 0) in assertEqual "volume is correct" True (vol ~= (-1/3)) , assertEqual "volume is correct" True (vol ~= (1/3)) ... ] where p0 = ... p3 = ... However, this is a bit brittle if you ever want to reorder the tests or insert new tests, since you have to update the list of names and list of test bodies to stay in sync. Also, am I correct in assuming the above is actually a stripped-down version of the real code? p0, p1, p2... etc. do not actually show up in the tests you have written at all. -Brent

On 08/29/2011 03:58 PM, Brent Yorgey wrote:
No, this is not possible directly. You have several options. As someone else already suggested, one option is to declare p0, p3 in the global scope and then shadow them in any local scopes where you would like them to have different values. Another option might be to do something like this:
[test_volume1, test_volume2] = [ let p1 = (0, 0.5, 0) p2 = (2, 0, 0) in assertEqual "volume is correct" True (vol ~= (-1/3))
, assertEqual "volume is correct" True (vol ~= (1/3))
...
] where p0 = ... p3 = ...
However, this is a bit brittle if you ever want to reorder the tests or insert new tests, since you have to update the list of names and list of test bodies to stay in sync.
Also, am I correct in assuming the above is actually a stripped-down version of the real code? p0, p1, p2... etc. do not actually show up in the tests you have written at all.
Correct, these are trivial cases. There is one expensive function that I would like to avoid recomputing, but no simple examples I could give of it. This is actually the solution that kmc gave me on #haskell, but my home connection has been hurricaned and I haven't been able to reply. I wouldn't mind the list/tuple solution otherwise; but, this is the best I could come up with haddock-wise:
-- | Check the value of c0030 for tetrahedron0 belonging to the cube -- centered on (1,1,1) with a grid constructed from the trilinear -- values. See example one in the paper. test_trilinear_c0030 :: Assertion test_trilinear_c0030 = test_trilinear_c0030'
[test_trilinear_c0030'] = [test_trilinear_c0030''] where g = make_grid 1 trilinear cube = cube_at g 1 1 1 t = tetrahedron0 cube
test_trilinear_c0030'' :: Assertion test_trilinear_c0030'' = assertAlmostEqual "c0030 is correct" (c t 0 0 3 0) (17/8)
It /works/, but gives me that "what the hell is he doing.." feeling when re-reading my own code.

On 08/30/11 08:15, Michael Orlitzky wrote:
It /works/, but gives me that "what the hell is he doing.." feeling when re-reading my own code.
For what it's worth, this is the most sane thing I could devise that
still allows me to use Haddock:
trilinear_c0_t0_tests :: Test.Framework.Test
trilinear_c0_t0_tests =
testGroup "trilinear c0 t0"
[testGroup "coefficients"
[testCase "c0030 is correct" test_trilinear_c0030,
testCase "c0003 is correct" test_trilinear_c0003,
testCase "c0021 is correct" test_trilinear_c0021,
testCase "c0012 is correct" test_trilinear_c0012,
testCase "c0120 is correct" test_trilinear_c0120,
testCase "c0102 is correct" test_trilinear_c0102,
testCase "c0111 is correct" test_trilinear_c0111,
testCase "c0210 is correct" test_trilinear_c0210,
testCase "c0201 is correct" test_trilinear_c0201,
testCase "c0300 is correct" test_trilinear_c0300,
testCase "c1020 is correct" test_trilinear_c1020,
testCase "c1002 is correct" test_trilinear_c1002,
testCase "c1011 is correct" test_trilinear_c1011,
testCase "c1110 is correct" test_trilinear_c1110,
testCase "c1101 is correct" test_trilinear_c1101,
testCase "c1200 is correct" test_trilinear_c1200,
testCase "c2010 is correct" test_trilinear_c2010,
testCase "c2001 is correct" test_trilinear_c2001,
testCase "c2100 is correct" test_trilinear_c2100,
testCase "c3000 is correct" test_trilinear_c3000],
testGroup "face0 vertices"
[testCase "v0 is correct" test_trilinear_f0_t0_v0,
testCase "v1 is correct" test_trilinear_f0_t0_v1,
testCase "v2 is correct" test_trilinear_f0_t0_v2,
testCase "v3 is correct" test_trilinear_f0_t0_v3]
]
where
g = make_grid 1 trilinear
cube = cube_at g 1 1 1
t = tetrahedron0 cube
test_trilinear_c0030 :: Assertion
test_trilinear_c0030 =
assertAlmostEqual "c0030 is correct" (c t 0 0 3 0) (17/8)
...
participants (3)
-
Brent Yorgey
-
Michael Orlitzky
-
Michael Xavier