OK, so explaining the passive aggressive style with monadic exceptions in a language that already has exceptions does not work. Back to regular exceptions in style 23. I left the monadic version as an academically interesting variation. In the process of returning to basic exceptions, I needed to clarify the tantrum style a little better too.

This commit is contained in:
Crista Lopes
2013-11-30 19:05:07 -08:00
parent 76f7ccb1d3
commit 9a9c525326
5 changed files with 122 additions and 41 deletions

View File

@@ -1,13 +1,15 @@
Style #21
Style #22
==============================
Constraints:
- Every single procedure and function checks the sanity of its
arguments and refuses to work when the arguments are unreasonable
arguments and refuses to continue when the arguments are
unreasonable, throwing an exception
- All code blocks check for all possible errors and refuse to continue
when things go wrong
- All code blocks check for all possible errors, print out
context-specific messages when errors occur, and pass the exceptions
up the function call chain
Possible names:

View File

@@ -59,15 +59,23 @@ def sort(word_freq):
assert(type(word_freq) is dict), "I need a dictionary! I quit!"
assert(word_freq <> {}), "I need a non-empty dictionary! I quit!"
return sorted(word_freq.iteritems(), key=operator.itemgetter(1), reverse=True)
try:
return sorted(word_freq.iteritems(), key=operator.itemgetter(1), reverse=True)
except Exception as e:
print "Sorted threw {0}: {1}".format(e)
raise e
#
# The main function
#
assert(len(sys.argv) > 1), "You idiot! I need an input file! I quit!"
word_freqs = sort(frequencies(extract_words(sys.argv[1])))
assert(len(word_freqs) > 25), "OMG! Less than 25 words! I QUIT!"
for tf in word_freqs[0:25]:
print tf[0], ' - ', tf[1]
try:
assert(len(sys.argv) > 1), "You idiot! I need an input file! I quit!"
word_freqs = sort(frequencies(extract_words(sys.argv[1])))
assert(type(word_freqs) is list), "OMG! This is not a list! I quit!"
assert(len(word_freqs) > 25), "SRSLY? Less than 25 words! I QUIT!"
for tf in word_freqs[0:25]:
print tf[0], ' - ', tf[1]
except Exception as e:
print "Something wrong: {0}".format(e)

View File

@@ -3,15 +3,16 @@ Style #23
Constraints:
- A sequence of functions should not proceed if preconditions aren't
met or if errors occur
- Every single procedure and function checks the sanity of its
arguments and refuses to continue when the arguments are
unreasonable, throwing an exception
- Core program functions have no exception handling, not even the main function
- When calling out other functions, core program functions don't check for errors
- The final result of the function chain should show the failure, if one occurred
- Exception handling occurs only at the top level of a function call chain
Possible names:
- Passive aggressive
- Monadic Exceptions

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python
import sys, re, operator, string
#
# The PassiveAggressive class for this example
#
class TFPassiveAggressive:
def __init__(self, v):
self._e = None
self._offending_func = None
self._value = v
def bind(self, func):
if self._e == None:
try:
self._value = func(self._value)
except Exception as e:
self._e = e
self._offending_func = func
return self
def printme(self):
if self._e == None:
print self._value
else:
print self._e, " in ", self._offending_func.__name__
#
# The functions
#
def get_input(arg):
assert(len(sys.argv) > 1), "You idiot! I need an input file! I quit!"
return sys.argv[1]
def extract_words(path_to_file):
assert(type(path_to_file) is str), "I need a string! I quit!"
assert(path_to_file), "I need a non-empty string! I quit!"
with open(path_to_file) as f:
data = f.read()
pattern = re.compile('[\W_]+')
word_list = pattern.sub(' ', data).lower().split()
return word_list
def remove_stop_words(word_list):
assert(type(word_list) is list), "I need a list! I quit!"
with open('../stop_words.txt') as f:
stop_words = f.read().split(',')
# add single-letter words
stop_words.extend(list(string.ascii_lowercase))
return [w for w in word_list if not w in stop_words]
def frequencies(word_list):
assert(type(word_list) is list), "I need a list! I quit!"
assert(word_list <> []), "I need a non-empty list! I quit!"
word_freqs = {}
for w in word_list:
if w in word_freqs:
word_freqs[w] += 1
else:
word_freqs[w] = 1
return word_freqs
def sort(word_freqs):
assert(type(word_freqs) is dict), "I need a dictionary! I quit!"
assert(word_freqs <> {}), "I need a non-empty dictionary! I quit!"
return sorted(word_freqs.iteritems(), key=operator.itemgetter(1), reverse=True)
def top25_freqs(word_freqs):
assert(type(word_freqs) is list), "I need a list! I quit!"
assert(word_freqs <> {}), "I need a non-empty dictionary! I quit!"
top25 = ""
for tf in word_freqs[0:25]:
top25 += str(tf[0]) + ' - ' + str(tf[1]) + '\n'
return top25
#
# The main function
#
TFPassiveAggressive(None).bind(get_input).bind(extract_words).bind(remove_stop_words).bind(frequencies).bind(sort).bind(top25_freqs).printme()

View File

@@ -1,30 +1,6 @@
#!/usr/bin/env python
import sys, re, operator, string
#
# The PassiveAggressive class for this example
#
class TFPassiveAggressive:
def __init__(self, v):
self._e = None
self._offending_func = None
self._value = v
def bind(self, func):
if self._e == None:
try:
self._value = func(self._value)
except Exception as e:
self._e = e
self._offending_func = func
return self
def printme(self):
if self._e == None:
print self._value
else:
print self._e, " in ", self._offending_func.__name__
#
# The functions
#
@@ -81,5 +57,14 @@ def top25_freqs(word_freqs):
#
# The main function
#
TFPassiveAggressive(None).bind(get_input).bind(extract_words).bind(remove_stop_words).bind(frequencies).bind(sort).bind(top25_freqs).printme()
try:
assert(len(sys.argv) > 1), "You idiot! I need an input file! I quit!"
word_freqs = sort(frequencies(extract_words(sys.argv[1])))
assert(len(word_freqs) > 25), "OMG! Less than 25 words! I QUIT!"
for tf in word_freqs[0:25]:
print tf[0], ' - ', tf[1]
except Exception as e:
print "Something wrong: {0}".format(e)