on master help sign in
Merge pull request #173 from betaveros/add-unsnoc
b42b0ddBryan O'Sullivan
Data/Text.hs+12
@@ -60,6 +60,7 @@ module Data.Text
60 , snoc
60 , snoc
61 , append
61 , append
62 , uncons
62 , uncons
63+ , unsnoc
63 , head
64 , head
64 , last
65 , last
65 , tail
66 , tail
@@ -545,6 +546,17 @@ init (Text arr off len) | len <= 0 = emptyError "init"
545 unstream (S.init (stream t)) = init t
546 unstream (S.init (stream t)) = init t
546 #-}
547 #-}
547
548
549+-- | /O(1)/ Returns all but the last character and the last character of a
550+-- 'Text', or 'Nothing' if empty.
551+unsnoc :: Text -> Maybe (Text, Char)
552+unsnoc (Text arr off len)
553+ | len <= 0 = Nothing
554+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
555+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
556+ where n = A.unsafeIndex arr (off+len-1)
557+ n0 = A.unsafeIndex arr (off+len-2)
558+{-# INLINE [1] unsnoc #-}
559+
548-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
560-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
549-- fusion.
561-- fusion.
550null :: Text -> Bool
562null :: Text -> Bool
Data/Text/Lazy.hs+10
@@ -68,6 +68,7 @@ module Data.Text.Lazy
68 , snoc
68 , snoc
69 , append
69 , append
70 , uncons
70 , uncons
71+ , unsnoc
71 , head
72 , head
72 , last
73 , last
73 , tail
74 , tail
@@ -559,6 +560,15 @@ init Empty = emptyError "init"
559 unstream (S.init (stream t)) = init t
560 unstream (S.init (stream t)) = init t
560 #-}
561 #-}
561
562
563+-- | /O(n\/c)/ Returns the 'init' and 'last' of a 'Text', or 'Nothing' if
564+-- empty.
565+--
566+-- * It is no faster than using 'init' and 'last'.
567+unsnoc :: Text -> Maybe (Text, Char)
568+unsnoc Empty = Nothing
569+unsnoc ts@(Chunk _ _) = Just (init ts, last ts)
570+{-# INLINE unsnoc #-}
571+
562-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
572-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
563-- fusion.
573-- fusion.
564null :: Text -> Bool
574null :: Text -> Bool
tests/Tests/Properties.hs+10−1
@@ -9,7 +9,7 @@ module Tests.Properties
9 ) where
9 ) where
10
10
11import Control.Applicative ((<$>), (<*>))
11import Control.Applicative ((<$>), (<*>))
12−import Control.Arrow ((***), second)
12+import Control.Arrow ((***), first, second)
13import Data.Bits ((.&.))
13import Data.Bits ((.&.))
14import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isLetter, isUpper, ord)
14import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isLetter, isUpper, ord)
15import Data.Int (Int8, Int16, Int32, Int64)
15import Data.Int (Int8, Int16, Int32, Int64)
@@ -232,6 +232,13 @@ sf_uncons p = (uncons . L.filter p) `eqP`
232 (fmap (second unpackS) . S.uncons . S.filter p)
232 (fmap (second unpackS) . S.uncons . S.filter p)
233t_uncons = uncons `eqP` (fmap (second unpackS) . T.uncons)
233t_uncons = uncons `eqP` (fmap (second unpackS) . T.uncons)
234tl_uncons = uncons `eqP` (fmap (second unpackS) . TL.uncons)
234tl_uncons = uncons `eqP` (fmap (second unpackS) . TL.uncons)
235+
236+unsnoc xs@(_:_) = Just (init xs, last xs)
237+unsnoc [] = Nothing
238+
239+t_unsnoc = unsnoc `eqP` (fmap (first unpackS) . T.unsnoc)
240+tl_unsnoc = unsnoc `eqP` (fmap (first unpackS) . TL.unsnoc)
241+
235s_head = head `eqP` S.head
242s_head = head `eqP` S.head
236sf_head p = (head . L.filter p) `eqP` (S.head . S.filter p)
243sf_head p = (head . L.filter p) `eqP` (S.head . S.filter p)
237t_head = head `eqP` T.head
244t_head = head `eqP` T.head
@@ -996,6 +1003,8 @@ tests =
996 testProperty "sf_uncons" sf_uncons,
1003 testProperty "sf_uncons" sf_uncons,
997 testProperty "t_uncons" t_uncons,
1004 testProperty "t_uncons" t_uncons,
998 testProperty "tl_uncons" tl_uncons,
1005 testProperty "tl_uncons" tl_uncons,
1006+ testProperty "t_unsnoc" t_unsnoc,
1007+ testProperty "tl_unsnoc" tl_unsnoc,
999 testProperty "s_head" s_head,
1008 testProperty "s_head" s_head,
1000 testProperty "sf_head" sf_head,
1009 testProperty "sf_head" sf_head,
1001 testProperty "t_head" t_head,
1010 testProperty "t_head" t_head,