diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3d2741..ca54cfe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 2.0.0 December 3, 2020
+
+Changed default behaviour of the `:r` modifier following discussion with
+@nfraprado at https://github.com/terrycojones/rpnpy/issues/6.
+
+*Note that this is a backwards-incompatible change!*
+
# 1.0.31 December 2, 2020
Added special `store` command to save stack values into a variable,
diff --git a/README.md b/README.md
index abb3283..411d60f 100644
--- a/README.md
+++ b/README.md
@@ -122,43 +122,21 @@ the iterable, then call `map` (`reduce`, `filter`, etc).
Like this:
```sh
-$ rpn.py 'str:! [6,7,8] map:i'
+$ rpn.py [6,7,8] 'str:! map:i'
['6', '7', '8']
```
-### Notes
-1. Here the `:!` modifier causes the `str` function to be pushed onto the
- stack instead of being run, and the `:i` modifier causes the result of
- `map` to be iterated before being added to the stack.
-1. When you run a function (like `map` or `apply`) that needs a callable
- (or a function like `join` that needs a string) and you don't specify a
- count (using `:3` for example), `rpn.py` will search the stack for a
- suitable item and use the first one it finds. It doesn't really have a
- choice in this case because it doesn't know how many arguments the
- function (once it is found) will be applied to. This should usually
- work just fine. You can always use an explicit count (like `:3`) if not.
- Note that this situation does not apply if you use the `:r` modifier
- (see below) because in that case the callable (or string, in the case of
- `join`) will be expected to be on the top of the stack (and its
- signature can then be examined to know how many arguments to pass it).
+Here the `:!` modifier causes the `str` function to be pushed onto the
+stack instead of being run, and the `:i` modifier causes the result of
+`map` to be iterated before being added to the stack.
-You might find it more natural to use `map` and friends the other way
-around. I.e., first push the iterable, then push the function to be
-applied, and then call `map`. In that case, you can use the `:r` modifier
-to tell the calculator to reverse the order of the arguments passed to a
-function. In the following, we push in the other order and then use
-`map:ir` (the `i` is just to iterate the `map` result to produce a list).
-
-```sh
-$ rpn.py '[6,7,8] str:! map:ir'
-['6', '7', '8']
-```
-Continuing on the map theme, you could instead simply reverse part of the
-stack before running a function:
+Continuing on the map theme, if you for some reason had the elements on the
+stack in the wrong order, you could reverse part of the stack before
+running a function:
```sh
-$ rpn.py '[6,7,8] str:! reverse map:i'
+$ rpn.py 'str:! [6,7,8] reverse map:i'
['6', '7', '8']
```
@@ -530,7 +508,8 @@ There are two kinds of commands: special and normal.
* `store`: Store the value on the top of the stack into a variable (whose name has
previously been pushed onto the stack). If given a numeric argument, that number
of items from the stack will be stored into the variable as a list.
-* `swap`: Swap the top two stack elements.
+* `swap`: Swap the top two stack elements (this is the same as calling
+ `reverse` with no arguments.
* `undo`: Undo the last stack-changing operation and variable settings.
* `variables`: Show all known variables and their values.
@@ -597,6 +576,27 @@ attrgetter Function(attrgetter (calls operator.attrgetter with 1 arg))
# 300+ lines deleted
```
+## Variables
+
+You can set variables and push them (or their values) onto the stack:
+
+```sh
+$ rpn.py --noSplit
+--> a = 4
+--> a
+--> f
+[4]
+--> a:!
+--> f
+[4, Variable(a, current value: 4)]
+--> a = 10
+--> f
+[4, Variable(a, current value: 10)]
+--> 20
+--> +:p
+30
+```
+
## Modifiers
Modifiers for a command are introduced with a colon, `:`. The modifiers are
@@ -632,22 +632,22 @@ The full list of modifiers is:
* `P`: Toggle automatic printing of all command results.
* `r`: When applied to a special command, reverses how the function (for
`map`, `apply`, `reduce`) or a string (for `join`) is looked for on the
- stack. Normally the function or string argument to one of those special
- functions has to be pushed onto the stack first. If `:r` is used, the
- function or string can be given last (i.e., can be on the top of the
- stack). In other contexts, causes all arguments given to a function to be
- reversed (i.e., to use a stack order opposite to the normal).
+ stack. If `:r` is used, the function or string argument to one of those special
+ functions has to be pushed onto the stack first. In other contexts, causes
+ all arguments given to a function to be reversed (i.e., to use a stack order
+ opposite to the normal):
```sh
- $ rpn.py '+:! 5 4 apply'
+ $ rpn.py '5 4 +:! apply'
9
- $ rpn.py '5 4 +:! apply:r'
+ $ rpn.py '+:! 5 4 apply:r'
9
$ rpn.py '5 4 -'
1
$ rpn.py '5 4 -:r'
-1
```
+ See below for more detail.
* `s`: Turn on line splitting on whitespace. Note that this will only go into
effect from the _next_ command on.
@@ -655,27 +655,33 @@ If a count is given, it is either interpreted as a number of times to push
something onto the stack or the number of arguments to act on, depending on
context (um, sorry about that - should be clearer).
-## Variables
+
+### Reversing argument ordering
-You can set variables and push them (or their values) onto the stack:
+You might find it more natural to use `map` and friends the other way
+around. I.e., first push the function, then push the iterable to be acted
+on, and then call `map`. In that case, you can use the `:r` modifier to
+tell the calculator to reverse the order of the arguments passed to a
+function. In the following, we push in the other order and then use
+`map:ir` (the `i` is just to iterate the `map` result to produce a list).
```sh
-$ rpn.py --noSplit
---> a = 4
---> a
---> f
-[4]
---> a:!
---> f
-[4, Variable(a, current value: 4)]
---> a = 10
---> f
-[4, Variable(a, current value: 10)]
---> 20
---> +:p
-30
+$ rpn.py 'str:! [6,7,8] map:ir'
+['6', '7', '8']
```
+Note that if you use the `:r` modifier to when running a function (like
+`map` or `apply`) that needs a callable (or a function like `join` that
+needs a string) and you don't specify a count (using `:3` for example),
+`rpn.py` will search the stack for a suitable item and use the first one it
+finds. It doesn't really have a choice in this case because it doesn't know
+how many arguments the function (once it is found) will be applied to.
+This should usually work just fine. You can always use an explicit count
+(like `:3`) if not.
+
+The argument ordering just described was the default in `rpn.py` prior to
+version `2.0.0`.
+
## Undo
The effect of commands on the stack and variables can be undone with the
diff --git a/rpnpy/__init__.py b/rpnpy/__init__.py
index 837a377..542f632 100644
--- a/rpnpy/__init__.py
+++ b/rpnpy/__init__.py
@@ -9,7 +9,7 @@
# will not be found by the version() function in ../setup.py
#
# Remember to update ../CHANGELOG.md describing what's new in each version.
-__version__ = '1.0.31'
+__version__ = '2.0.0'
# Keep Python linters quiet.
_ = Calculator
diff --git a/rpnpy/calculator.py b/rpnpy/calculator.py
index 8121fe1..93f3f7f 100644
--- a/rpnpy/calculator.py
+++ b/rpnpy/calculator.py
@@ -661,26 +661,6 @@ def _findWithArgs(self, command, description, predicate, defaultArgCount,
(command, stackLen, '' if stackLen == 1 else 's'))
if modifiers.reverse:
- item = self.stack[-1]
-
- if not predicate(item):
- raise StackError('Top stack item (%r) is not %s' %
- (item, description))
-
- if count is None:
- count = (stackLen - 1 if modifiers.all else
- defaultArgCount(item))
-
- nargsAvail = stackLen - 1
- if nargsAvail < count:
- raise StackError(
- 'Cannot run %r with %d argument%s '
- '(stack has only %d item%s available)' %
- (command, count, '' if count == 1 else 's',
- nargsAvail, '' if nargsAvail == 1 else 's'))
-
- args = self.stack[-(count + 1):-1]
- else:
if count is None:
if modifiers.all:
item = self.stack[0]
@@ -708,6 +688,26 @@ def _findWithArgs(self, command, description, predicate, defaultArgCount,
item, description))
args = self.stack[-count:]
+ else:
+ item = self.stack[-1]
+
+ if not predicate(item):
+ raise StackError('Top stack item (%r) is not %s' %
+ (item, description))
+
+ if count is None:
+ count = (stackLen - 1 if modifiers.all else
+ defaultArgCount(item))
+
+ nargsAvail = stackLen - 1
+ if nargsAvail < count:
+ raise StackError(
+ 'Cannot run %r with %d argument%s '
+ '(stack has only %d item%s available)' %
+ (command, count, '' if count == 1 else 's',
+ nargsAvail, '' if nargsAvail == 1 else 's'))
+
+ args = self.stack[-(count + 1):-1]
return item, self.convertStackArgs(args)
diff --git a/rpnpy/functions.py b/rpnpy/functions.py
index 71b4b7c..dc69f6c 100644
--- a/rpnpy/functions.py
+++ b/rpnpy/functions.py
@@ -374,7 +374,7 @@ def map_(calc, modifiers, count):
def addSpecialFunctions(calc):
- """Add functions defined above
+ """Add functions defined above.
@param calc: A C{Calculator} instance.
"""
diff --git a/test/test_calculator.py b/test/test_calculator.py
index 1d59c9e..55cff67 100644
--- a/test/test_calculator.py
+++ b/test/test_calculator.py
@@ -247,9 +247,9 @@ def testIterateString(self):
def testItemgetter(self):
"itemgetter must work correctly"
c = Calculator(splitLines=False)
+ c.execute('[[1, 2, 3], [4, 5, 6]]')
c.execute('1')
c.execute('itemgetter')
- c.execute('[[1, 2, 3], [4, 5, 6]]')
c.execute('map :i')
(result,) = c.stack
self.assertEqual([2, 5], result)
@@ -265,7 +265,6 @@ def testList2(self):
"Converting the top two items of the stack to a list must work"
c = Calculator()
c.execute('4 5 list:2')
- c.printStack()
(result,) = c.stack
self.assertEqual([4, 5], result)
@@ -273,7 +272,6 @@ def testListAll(self):
"Converting all items of the stack to a list must work"
c = Calculator()
c.execute('4 5 6 list:*')
- c.printStack()
(result,) = c.stack
self.assertEqual([4, 5, 6], result)
@@ -354,8 +352,8 @@ def testReverseSubtractionArgs(self):
def testMap(self):
"Call map with args reversed from their normal order"
c = Calculator()
- c.execute('[1,2,3]')
c.execute('str :!')
+ c.execute('[1,2,3]')
c.execute('map :ir')
(result,) = c.stack
self.assertEqual(['1', '2', '3'], result)
@@ -426,68 +424,68 @@ class TestJoin(TestCase):
def testEmptyString(self):
"Joining on an empty string must work"
c = Calculator()
- c.execute('"" ["4","5","6"] join')
+ c.execute('["4","5","6"] "" join')
(result,) = c.stack
self.assertEqual('456', result)
def testNonEmptyString(self):
"Joining on a non-empty string must work"
c = Calculator()
- c.execute('"-" ["4","5","6"] join')
+ c.execute('["4","5","6"] "-" join')
(result,) = c.stack
self.assertEqual('4-5-6', result)
def testNonStrings(self):
"Joining things that are not string must work"
c = Calculator()
- c.execute('"-" [4,5,6] join')
+ c.execute('[4,5,6] "-" join')
(result,) = c.stack
self.assertEqual('4-5-6', result)
def testWithCount(self):
"Joining several stack items must work"
c = Calculator()
- c.execute('3 "-" 4 5 6 join:3')
+ c.execute('3 4 5 6 "-" join:3')
self.assertEqual([3, '4-5-6'], c.stack)
def testAllStack(self):
"Joining the whole stack"
c = Calculator()
- c.execute('"-" 3 4 5 6 join:*')
+ c.execute('3 4 5 6 "-" join:*')
(result,) = c.stack
self.assertEqual('3-4-5-6', result)
def testEmptyStringReversed(self):
"Joining on an empty string must work"
c = Calculator()
- c.execute('["4","5","6"] "" join:r')
+ c.execute('"" ["4","5","6"] join:r')
(result,) = c.stack
self.assertEqual('456', result)
def testNonEmptyStringReversed(self):
"Joining on a non-empty string must work"
c = Calculator()
- c.execute('["4","5","6"] "-" join:r')
+ c.execute('"-" ["4","5","6"] join:r')
(result,) = c.stack
self.assertEqual('4-5-6', result)
def testNonStringsReversed(self):
"Joining things that are not string must work"
c = Calculator()
- c.execute('[4,5,6] "-" join:r')
+ c.execute('"-" [4,5,6] join:r')
(result,) = c.stack
self.assertEqual('4-5-6', result)
def testWithCountReversed(self):
"Joining several stack items must work"
c = Calculator()
- c.execute('3 4 5 6 "-" join:3r')
+ c.execute('3 "-" 4 5 6 join:3r')
self.assertEqual([3, '4-5-6'], c.stack)
def testAllStackReversed(self):
"Joining the whole stack"
c = Calculator()
- c.execute('3 4 5 6 "-" join:*r')
+ c.execute('"-" 3 4 5 6 join:*r')
(result,) = c.stack
self.assertEqual('3-4-5-6', result)
@@ -508,7 +506,7 @@ def testStackWithOneItem(self):
def testStackWithTwoItemsClearsStack(self):
"Calling store on a stack with two items must result in an empty stack"
c = Calculator()
- c.execute('"a" 4 store')
+ c.execute('4 "a" store')
self.assertEqual([], c.stack)
def testStackWithTwoItemsPreservingStack(self):
@@ -526,7 +524,7 @@ def testStackWithTwoItems(self):
being set as expected.
"""
c = Calculator()
- c.execute('"a" 4 store a')
+ c.execute('4 "a" store a')
(result,) = c.stack
self.assertEqual(4, result)
@@ -536,7 +534,7 @@ def testStackWithThreeItems(self):
result in the variable being set as expected.
"""
c = Calculator()
- c.execute('"a" 4 5 store:2 a')
+ c.execute('4 5 "a" store:2 a')
self.assertEqual([[4, 5]], c.stack)
def testStackWithThreeItemsReversed(self):
@@ -545,7 +543,7 @@ def testStackWithThreeItemsReversed(self):
the reverse modifier must result in the variable being set as expected.
"""
c = Calculator()
- c.execute('4 5 "a" store:r2 a')
+ c.execute('"a" 4 5 store:r2 a')
self.assertEqual([[4, 5]], c.stack)
def testStarModifier(self):
@@ -554,7 +552,7 @@ def testStarModifier(self):
result in the variable being set as expected.
"""
c = Calculator()
- c.execute('"a" 4 5 6 store:* a')
+ c.execute('4 5 6 "a" store:* a')
self.assertEqual([[4, 5, 6]], c.stack)
def testStarModifierReversed(self):
@@ -563,7 +561,7 @@ def testStarModifierReversed(self):
reverse modifier must result in the variable being set as expected.
"""
c = Calculator()
- c.execute('4 5 6 "a" store:r* a')
+ c.execute('"a" 4 5 6 store:r* a')
self.assertEqual([[4, 5, 6]], c.stack)
@@ -592,8 +590,8 @@ def testStackLengthTwoNoCount(self):
correctly. The number of stack items is obtained from the function
signature"""
c = Calculator()
- c.execute('log10 :!')
c.execute('4')
+ c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', Modifiers(), None)
self.assertIs(math.log10, func)
self.assertEqual([4], args)
@@ -602,31 +600,18 @@ def testStackLengthTwoWithCount(self):
"""Calling on a stack with two items and a count must return
correctly."""
c = Calculator()
- c.execute('log10 :!')
c.execute('4')
+ c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', Modifiers(), 1)
self.assertIs(math.log10, func)
self.assertEqual([4], args)
- def testStackLengthThreeWithCountError(self):
- """Calling on a stack with three items and a count that points to a
- non-callable must result in an error"""
- errfp = StringIO()
- c = Calculator(errfp=errfp)
- c.execute('log10 :!')
- c.execute('4')
- c.execute('5')
- error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is "
- r"not callable$")
- self.assertRaisesRegex(StackError, error, c.findCallableAndArgs,
- 'cmd', Modifiers(), 1)
-
def testStackLengthThree(self):
"Calling on a stack with three items (count=2) must return correctly"
c = Calculator()
- c.execute('log10 :!')
c.execute('4')
c.execute('5')
+ c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', Modifiers(), 2)
self.assertIs(math.log10, func)
self.assertEqual([4, 5], args)
@@ -634,10 +619,10 @@ def testStackLengthThree(self):
def testAllStack(self):
"Calling on all the stack must return correctly"
c = Calculator()
- c.execute('log10 :!')
c.execute('4')
c.execute('5')
c.execute('6')
+ c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', strToModifiers('*'), None)
self.assertIs(math.log10, func)
self.assertEqual([4, 5, 6], args)
@@ -666,8 +651,8 @@ def testStackLengthTwoNoCount(self):
correctly. The number of stack items is obtained from the function
signature"""
c = Calculator()
- c.execute('4')
c.execute('log10 :!')
+ c.execute('4')
func, args = c.findCallableAndArgs('cmd', strToModifiers('r'), None)
self.assertIs(math.log10, func)
self.assertEqual([4], args)
@@ -676,8 +661,8 @@ def testStackLengthTwoWithCount(self):
"""Calling on a stack with two items and a count must return
correctly."""
c = Calculator()
- c.execute('4')
c.execute('log10 :!')
+ c.execute('4')
func, args = c.findCallableAndArgs('cmd', strToModifiers('r'), 1)
self.assertIs(math.log10, func)
self.assertEqual([4], args)
@@ -685,20 +670,33 @@ def testStackLengthTwoWithCount(self):
def testStackLengthThree(self):
"Calling on a stack with three items (count=2) must return correctly"
c = Calculator()
+ c.execute('log10 :!')
c.execute('5')
c.execute('4')
- c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', strToModifiers('r'), 2)
self.assertIs(math.log10, func)
self.assertEqual([5, 4], args)
+ def testStackLengthThreeWithCountError(self):
+ """Calling on a stack with three items and a count that points to a
+ non-callable must result in an error"""
+ errfp = StringIO()
+ c = Calculator(errfp=errfp)
+ c.execute('log10 :!')
+ c.execute('4')
+ c.execute('5')
+ error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is "
+ r"not callable$")
+ self.assertRaisesRegex(StackError, error, c.findCallableAndArgs,
+ 'cmd', strToModifiers('r'), 1)
+
def testAllStack(self):
"Calling on all the stack must return correctly"
c = Calculator()
+ c.execute('log10 :!')
c.execute('4')
c.execute('5')
c.execute('6')
- c.execute('log10 :!')
func, args = c.findCallableAndArgs('cmd', strToModifiers('*r'), None)
self.assertIs(math.log10, func)
self.assertEqual([4, 5, 6], args)
@@ -727,8 +725,8 @@ def testStackLengthTwoNoCount(self):
correctly. The number of stack items is obtained from the function
signature"""
c = Calculator()
- c.execute("'string'")
c.execute('4')
+ c.execute("'string'")
string, args = c.findStringAndArgs('cmd', Modifiers(), None)
self.assertEqual('string', string)
self.assertEqual([4], args)
@@ -737,30 +735,18 @@ def testStackLengthTwoWithCount(self):
"""Calling on a stack with two items and a count must return
correctly."""
c = Calculator()
- c.execute("'string'")
c.execute('4')
+ c.execute("'string'")
string, args = c.findStringAndArgs('cmd', Modifiers(), 1)
self.assertEqual('string', string)
self.assertEqual([4], args)
- def testStackLengthThreeWithCountError(self):
- """Calling on a stack with three items and a count that points to a
- non-string must result in an error"""
- c = Calculator()
- c.execute("'string'")
- c.execute('4')
- c.execute('5')
- error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is "
- r"not a string$")
- self.assertRaisesRegex(StackError, error, c.findStringAndArgs,
- 'cmd', Modifiers(), 1)
-
def testStackLengthThree(self):
"Calling on a stack with three items (count=2) must return correctly"
c = Calculator()
- c.execute("'string'")
c.execute('4')
c.execute('5')
+ c.execute("'string'")
string, args = c.findStringAndArgs('cmd', Modifiers(), 2)
self.assertEqual('string', string)
self.assertEqual([4, 5], args)
@@ -768,10 +754,10 @@ def testStackLengthThree(self):
def testAllStack(self):
"Calling on all the stack must return correctly"
c = Calculator()
- c.execute("'string'")
c.execute('4')
c.execute('5')
c.execute('6')
+ c.execute("'string'")
string, args = c.findStringAndArgs('cmd', strToModifiers('*'), None)
self.assertEqual('string', string)
self.assertEqual([4, 5, 6], args)
@@ -800,8 +786,8 @@ def testStackLengthTwoNoCount(self):
correctly. The number of stack items is obtained from the function
signature"""
c = Calculator()
- c.execute('4')
c.execute("'string'")
+ c.execute('4')
string, args = c.findStringAndArgs('cmd', strToModifiers('r'), None)
self.assertEqual('string', string)
self.assertEqual([4], args)
@@ -810,8 +796,8 @@ def testStackLengthTwoWithCount(self):
"""Calling on a stack with two items and a count must return
correctly."""
c = Calculator()
- c.execute('4')
c.execute("'string'")
+ c.execute('4')
string, args = c.findStringAndArgs('cmd', strToModifiers('r'), 1)
self.assertEqual('string', string)
self.assertEqual([4], args)
@@ -819,20 +805,32 @@ def testStackLengthTwoWithCount(self):
def testStackLengthThree(self):
"Calling on a stack with three items (count=2) must return correctly"
c = Calculator()
+ c.execute("'string'")
c.execute('5')
c.execute('4')
- c.execute("'string'")
string, args = c.findStringAndArgs('cmd', strToModifiers('r'), 2)
self.assertEqual('string', string)
self.assertEqual([5, 4], args)
+ def testStackLengthThreeWithCountError(self):
+ """Calling on a stack with three items and a count that points to a
+ non-string must result in an error"""
+ c = Calculator()
+ c.execute("'string'")
+ c.execute('4')
+ c.execute('5')
+ error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is "
+ r"not a string$")
+ self.assertRaisesRegex(StackError, error, c.findStringAndArgs,
+ 'cmd', strToModifiers('r'), 1)
+
def testAllStack(self):
"Calling on all the stack must return correctly"
c = Calculator()
+ c.execute("'string'")
c.execute('4')
c.execute('5')
c.execute('6')
- c.execute("'string'")
string, args = c.findStringAndArgs('cmd', strToModifiers('*r'), None)
self.assertEqual('string', string)
self.assertEqual([4, 5, 6], args)
@@ -844,8 +842,8 @@ class TestApply(TestCase):
def testApplyNoCount(self):
"apply must work correctly when not given a count"
c = Calculator()
- c.execute('abs :!')
c.execute('-1')
+ c.execute('abs :!')
c.execute('apply')
(result,) = c.stack
self.assertEqual(1, result)
@@ -853,8 +851,8 @@ def testApplyNoCount(self):
def testApplyWithCount(self):
"apply must work correctly when given a count"
c = Calculator()
- c.execute('+ :!')
c.execute('3 5')
+ c.execute('+ :!')
c.execute('apply :2')
(result,) = c.stack
self.assertEqual(8, result)
@@ -863,9 +861,9 @@ def testApplyVariables(self):
"apply must work correctly when Variable instances are on the stack"
c = Calculator()
c.execute('a=4 b=5')
- c.execute('+ :!')
c.execute('a :!')
c.execute('b :!')
+ c.execute('+ :!')
c.execute('apply')
(result,) = c.stack
self.assertEqual(9, result)
@@ -877,10 +875,10 @@ class TestReduce(TestCase):
def testReduceAl(self):
"Reduce must work correctly when told to operate on the whole stack"
c = Calculator()
- c.execute('+ :!')
c.execute('5')
c.execute('6')
c.execute('7')
+ c.execute('+ :!')
c.execute('reduce :*')
(result,) = c.stack
self.assertEqual(18, result)
@@ -888,9 +886,9 @@ def testReduceAl(self):
def testReduceWithCount(self):
"Reduce must work correctly when given a count"
c = Calculator()
- c.execute('+ :!')
c.execute('5')
c.execute('6')
+ c.execute('+ :!')
c.execute('reduce :2')
(result,) = c.stack
self.assertEqual(11, result)
@@ -902,10 +900,10 @@ class TestReduceReversed(TestCase):
def testReduceAl(self):
"Reduce must work correctly when told to operate on the whole stack"
c = Calculator()
+ c.execute('+ :!')
c.execute('5')
c.execute('6')
c.execute('7')
- c.execute('+ :!')
c.execute('reduce :*r')
(result,) = c.stack
self.assertEqual(18, result)
@@ -914,9 +912,9 @@ def testReduceWithCount(self):
"Reduce must work correctly when given a count"
c = Calculator()
c.execute('4')
+ c.execute('+ :!')
c.execute('5')
c.execute('6')
- c.execute('+ :!')
c.execute('reduce :2r')
self.assertEqual([4, 11], c.stack)
@@ -962,7 +960,6 @@ def testPopForcedCommandWhenAVariableCalledPopExists(self):
c.execute('6')
c.execute('5')
c.execute('pop:c')
- print(c.stack)
(result,) = c.stack
self.assertEqual(6, result)
@@ -973,16 +970,16 @@ class TestMap(TestCase):
def testWithCount(self):
"map must work as expected when given a count"
c = Calculator()
- c.execute('str :!')
c.execute('1 2 3')
+ c.execute('str :!')
c.execute('map :3i')
self.assertEqual(['1', '2', '3'], c.stack)
def testIterateGenerator(self):
"The :i (iterate) modifier must work as expected on a map generator"
c = Calculator()
- c.execute('str :!')
c.execute('[1,2,3]')
+ c.execute('str :!')
c.execute('map :i')
(result,) = c.stack
self.assertEqual(['1', '2', '3'], result)