diff --git a/egison.cabal b/egison.cabal
--- a/egison.cabal
+++ b/egison.cabal
@@ -1,5 +1,5 @@
 Name:                egison
-Version:             3.3.11
+Version:             3.3.12
 Synopsis:            Programming language with non-linear pattern-matching against unfree data
 Description:
   An interpreter for Egison, the programming langugage that realized non-linear pattern-matching against unfree data types.
diff --git a/hs-src/Language/Egison/Primitives.hs b/hs-src/Language/Egison/Primitives.hs
--- a/hs-src/Language/Egison/Primitives.hs
+++ b/hs-src/Language/Egison/Primitives.hs
@@ -144,6 +144,7 @@
 
              , ("pack", pack)
              , ("unpack", unpack)
+             , ("uncons-string", unconsString)
              , ("length-string", lengthString)
              , ("append-string", appendString)
              , ("split-string", splitString)
@@ -391,6 +392,14 @@
 unpack = oneArg $ \val -> do
   case val of
     String str -> return $ toEgison (T.unpack str)
+    _ -> throwError $ TypeMismatch "string" (Value val)
+
+unconsString :: PrimitiveFunc
+unconsString = oneArg $ \val -> do
+  case val of
+    String str -> case T.uncons str of
+                    Just (c, rest) ->  return $ Tuple [Char c, String rest]
+                    Nothing -> throwError $ Default "Tried to unsnoc empty string"
     _ -> throwError $ TypeMismatch "string" (Value val)
 
 lengthString :: PrimitiveFunc
diff --git a/lib/core/collection.egi b/lib/core/collection.egi
--- a/lib/core/collection.egi
+++ b/lib/core/collection.egi
@@ -303,7 +303,9 @@
 
 (define $intersperse
   (lambda [$in $ws]
-    (foldl (lambda [$s1 $s2] {@s1 in s2}) {(car ws)} (cdr ws))))
+    (match ws (list something)
+      {[<nil> {}]
+       [<cons $w $rs> (foldl (lambda [$s1 $s2] {@s1 in s2}) {w} rs)]})))
 
 (define $intercalate (compose intersperse concat))
 
diff --git a/lib/string/string.egi b/lib/string/string.egi
--- a/lib/string/string.egi
+++ b/lib/string/string.egi
@@ -17,17 +17,20 @@
      [<cons $ $> [char string]
       {[$tgt (if (eq? "" tgt)
                {}
-               {(unsnoc-string tgt)})]}]
+               {(uncons-string tgt)})]}]
      [<join $ <cons ,$px $>> [string string]
-      {[$tgt (match-all (split (pack {px}) tgt) (list string)
-               [<join $xs $ys> [(S.append (car xs) (S.concat (map (S.append (pack {px}) $) (cdr xs))))
-                                (S.append (car ys) (S.concat (map (S.append (pack {px}) $) (cdr ys))))
+      {[$tgt (match-all (S.split (pack {px}) tgt) (list string)
+               [<join (& ^<nil> $xs) (& ^<nil> $ys)> [(S.intercalate (pack {px}) xs)
+                                (S.intercalate (pack {px}) ys)
                                 ]])]}]
      [<join $ <join ,$pxs $>> [string string]
-      {[$tgt (match-all (split-string tgt) (list string)
-               [<join $xs $ys> [(S.append (car xs) (S.concat (map (S.append px $) (cdr xs))))
-                                (S.append (car ys) (S.concat (map (S.append px $) (cdr ys))))
+      {[$tgt (match-all (S.split pxs tgt) (list string)
+               [<join (& ^<nil> $xs) (& ^<nil> $ys)> [(S.intercalate pxs xs)
+                                (S.intercalate pxs ys)
                                 ]])]}]
+     [<join $ $> [string string]
+      {[$tgt (match-all tgt string
+                 [(loop $i [1 $n] <cons $xa_i ...> $rs) [(pack (map (lambda [$i] xa_i) (between 1 n))) rs]])]}]
      [$ [something]
       {[$tgt {tgt}]}]
      }))
