11from abc import ABCMeta , ABC , abstractmethod
22from functools import reduce
33from operator import length_hint
4- from collections import OrderedDict , UserString
54from itertools import chain , islice
6- from collections .abc import Iterator , Sequence , ItemsView , ByteString
5+ from collections import OrderedDict , UserString
6+ from collections .abc import Iterator , Sequence , ItemsView , ByteString , Mapping
77
88from multipledispatch import dispatch
99
10- from toolz import last , first
11-
12- # We can't use this because `islice` drops __length_hint__ info.
13- # from toolz.itertoolz import rest
10+ # This is the constructor/type used for `ConsNull` value `None`.
11+ default_ConsNull = list
1412
1513
1614class ConsError (ValueError ):
@@ -86,11 +84,7 @@ def __new__(cls, *parts):
8684 if len (parts ) > 2 :
8785 res = reduce (lambda x , y : ConsPair (y , x ), reversed (parts ))
8886 elif len (parts ) == 2 :
89- car_part = first (parts )
90- cdr_part = last (parts )
91-
92- if cdr_part is None :
93- cdr_part = []
87+ car_part , cdr_part = parts
9488
9589 if isinstance (
9690 cdr_part , (ConsNull , ConsPair , Iterator )
@@ -110,17 +104,22 @@ def __new__(cls, *parts):
110104 @classmethod
111105 def cons_merge (cls , car_part , cdr_part ):
112106
113- if isinstance ( cdr_part , OrderedDict ) :
114- cdr_part = cdr_part . items ()
107+ if cdr_part is None :
108+ cdr_part = default_ConsNull ()
115109
116- res = chain ((car_part ,), cdr_part )
110+ if isinstance (cdr_part , Mapping ):
111+ cdr_part = cdr_part .items ()
117112
118113 if isinstance (cdr_part , ItemsView ):
119- res = OrderedDict (res )
120- elif not isinstance (cdr_part , Iterator ):
121- res = type (cdr_part )(res )
122114
123- return res
115+ return OrderedDict (chain ((car_part ,), cdr_part ))
116+
117+ elif hasattr (cdr_part , "__add__" ) or hasattr (cdr_part , "__radd__" ):
118+ # TODO: What about adding `list.extend`? We're already
119+ # constructing an instance of the CDR type.
120+ return type (cdr_part )((car_part ,)) + cdr_part
121+
122+ return chain ((car_part ,), cdr_part )
124123
125124 def __hash__ (self ):
126125 return hash ([self .car , self .cdr ])
@@ -202,7 +201,7 @@ def car(z):
202201@dispatch (Sequence )
203202def _car (z ):
204203 try :
205- return first ( z )
204+ return next ( iter ( z ) )
206205 except StopIteration :
207206 raise ConsError ("Not a cons pair" )
208207
@@ -218,7 +217,7 @@ def _car_Iterator(z):
218217 """
219218 try :
220219 # z, _ = tee(z)
221- return first ( z )
220+ return next ( iter ( z ) )
222221 except StopIteration :
223222 raise ConsError ("Not a cons pair" )
224223
@@ -228,7 +227,7 @@ def _car_OrderedDict(z):
228227 if len (z ) == 0 :
229228 raise ConsError ("Not a cons pair" )
230229
231- return first ( z .items ())
230+ return next ( iter ( z .items () ))
232231
233232
234233@_car .register (NonCons )
0 commit comments