Last active
December 12, 2015 00:48
-
-
Save bradmontgomery/4685762 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FListImmutableError(Exception): | |
def __init__(self, msg='Can\'t modify FList members'): | |
self.message = msg | |
def __str__(self): | |
return self.message | |
def f_tl(l): | |
return FList() if len(l) < 2 else l[1:] | |
def f_hd(l): | |
return l[0] if len(l) > 0 else FList() | |
class FList: | |
def __init__(self, l=[]): | |
if not type(l) == list: | |
l = [l] | |
self.internal = l | |
try: | |
self.check_list_type() | |
except TypeError, e: | |
print e.message | |
def __getitem__(self, key): | |
if type(key) == int or type(key) == slice: | |
try: | |
value = self.internal[key] | |
if type(key) == slice: | |
value = FList(value) | |
return value | |
except IndexError, e: | |
raise type(e)('index out of range') | |
else: | |
raise TypeError('argument must be integer or slice') | |
def __setitem__(self, key, value): | |
# lists are immutable! | |
raise FListImmutableError() | |
def __len__(self): | |
return len(self.internal) | |
def __repr__(self): | |
return 'FList(' + ', '.join(str(x) for x in self.internal) + ')' | |
def __add__(self, other): | |
return self.cons(other) | |
def hd(self): | |
return None if len(self) == 0 else self[0] | |
def tl(self): | |
return FList() if len(self) < 2 else self[1:] | |
def cons(self, l): | |
if not l.__class__ == FList: | |
l = FList(l) | |
t1 = self.get_list_type() | |
t2 = l.get_list_type() | |
if not (t1 is None or t2 is None or t1 == t2): | |
raise TypeError( | |
'attempting to join list of type %s with list of type %s' | |
% (t1, t2)) | |
return FList(self.internal + l.internal) | |
def check_list_type(self): | |
if len(self) > 1: | |
compare = lambda x: type(x) == type(self.internal[0]) | |
if not all(map(compare, self.internal)): | |
raise TypeError('item values must be of the same type') | |
def get_list_type(self): | |
return type(self[0]) if len(self) > 0 else None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from nose.tools import eq_, raises | |
from flist import FList, f_hd, f_tl, FListImmutableError | |
from random import randint | |
def _randchar(mixed_case=True): | |
letter = chr(randint(ord('a'), ord('z'))) | |
if mixed_case and randint(0, 1) == 0: | |
letter = letter.upper() | |
return letter | |
def generate_password(l=FList(), z=12): | |
if len(l) == z: | |
return ''.join(l[:]) | |
else: | |
return generate_password(l.cons(_randchar()), z) | |
def test_flist(): | |
# create a new FList | |
l = FList(range(10)) | |
# get an item | |
eq_(l[2], 2) | |
# get a slice | |
eq_(len(l[4:7]), 3) | |
eq_(l[4:7].__class__, FList) # Slices are FLists! | |
# head | |
eq_(l.hd(), 0) | |
# tail | |
eq_(len(l.tl()), 9) | |
# chaining | |
eq_(l.tl().tl().hd(), 2) | |
# nesting | |
eq_(f_hd(f_tl(f_tl(l))), 2) | |
# cons | |
eq_( | |
len(FList(list('good')).cons(FList(list('morning')))), | |
len(list('goodmorning')) | |
) | |
# recursion | |
eq_(len(generate_password()), 12) | |
# Exceptions | |
# ---------- | |
@raises(FListImmutableError) | |
def test_immutable(): | |
l = FList(range(10)) | |
l[0] = 1069 | |
@raises(IndexError) | |
def test_access_bounds(): | |
l = FList([0]) | |
l[5] | |
@raises(TypeError) | |
def test_homogeneous(): | |
l = FList([1, 'a', True, None]) | |
@raises(TypeError) | |
def test_homogeneous_cons(): | |
FList(list('foo')).cons(FList(range(100))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment