@@ -4,9 +4,15 @@ use std::rc::Rc;
4
4
5
5
use crate :: error_message;
6
6
use crate :: type_tag:: TypeTag ;
7
+ use crate :: persistent_list:: ToPersistentListIter ;
8
+ use crate :: persistent_vector:: ToPersistentVectorIter ;
9
+ use itertools:: Itertools ;
10
+ use crate :: persistent_list:: PersistentList :: Cons ;
7
11
8
- /// clojure.string/reverse ; reverses a string
9
- /// (defn print-string [string] .. prints single string .. )
12
+ /// clojure.string/join ; joins a coll of items together as a string
13
+ /// (join
14
+ /// [coll]
15
+ /// [separator coll])
10
16
#[ derive( Debug , Clone ) ]
11
17
pub struct JoinFn { }
12
18
impl ToValue for JoinFn {
@@ -16,15 +22,42 @@ impl ToValue for JoinFn {
16
22
}
17
23
impl IFn for JoinFn {
18
24
fn invoke ( & self , args : Vec < Rc < Value > > ) -> Value {
19
- if args. len ( ) == 1 {
20
- match args. get ( 0 ) . unwrap ( ) . to_value ( ) {
21
- Value :: Iseq ( s) => Value :: String ( s. chars ( ) . rev ( ) . collect ( ) ) ,
22
- _a => error_message:: type_mismatch ( TypeTag :: String , & _a. to_value ( ) )
25
+ if args. len ( ) == 1 || args. len ( ) == 2 {
26
+ let separator = if args. len ( ) == 2 {
27
+ args. get ( 0 ) . unwrap ( ) . to_string ( )
28
+ } else { String :: from ( "" ) } ;
29
+ let coll = if args. len ( ) == 1 { args. get ( 0 ) } else { args. get ( 1 ) } ;
30
+ match coll. unwrap ( ) . to_value ( ) {
31
+ Value :: PersistentList ( Cons ( head, tail, count) ) => {
32
+ return if count == 0 {
33
+ Value :: String ( String :: from ( "" ) )
34
+ } else if count == 1 {
35
+ Value :: String ( head. to_string ( ) )
36
+ } else {
37
+ Value :: String (
38
+ String :: from (
39
+ head. to_string ( ) ) + separator. as_str ( ) +
40
+ tail. iter ( )
41
+ . map ( |x| x. to_string ( ) )
42
+ . collect :: < Vec < std:: string:: String > > ( )
43
+ . join ( & separator) . as_str ( ) )
44
+ }
45
+ } ,
46
+ Value :: PersistentVector ( pvec) => {
47
+ return if pvec. vals . len ( ) == 0 {
48
+ Value :: String ( String :: from ( "" ) )
49
+ } else {
50
+ Value :: String ( String :: from (
51
+ pvec. vals . iter ( )
52
+ . map ( |x| x. to_string ( ) )
53
+ . collect :: < Vec < std:: string:: String > > ( )
54
+ . join ( & separator) . as_str ( ) ) )
55
+ }
56
+ }
57
+ _ => Value :: String ( String :: from ( "" ) )
23
58
}
24
-
25
59
} else {
26
- return error_message:: wrong_arg_count ( 2 , args. len ( ) ) ;
27
-
60
+ return error_message:: wrong_varg_count ( & [ 1 , 2 ] , args. len ( ) ) ;
28
61
}
29
62
}
30
63
}
@@ -34,15 +67,63 @@ mod tests {
34
67
mod reverse_tests {
35
68
use crate :: value:: Value ;
36
69
use std:: rc:: Rc ;
37
- use crate :: clojure_string:: reverse :: JoinFn ;
70
+ use crate :: clojure_string:: join :: JoinFn ;
38
71
use crate :: ifn:: IFn ;
72
+ use crate :: persistent_list:: PersistentList ;
73
+ use crate :: persistent_vector:: PersistentVector ;
74
+
75
+ #[ test]
76
+ fn join_empty_collection_to_empty_string ( ) {
77
+ let join = JoinFn { } ;
78
+ let args = vec ! [ Rc :: new( Value :: PersistentList ( vec![ ] . into_iter( ) . collect:: <PersistentList >( ) ) ) ] ;
79
+ assert_eq ! ( Value :: String ( String :: from( "" ) ) , join. invoke( args) ) ;
80
+ }
81
+
82
+ #[ test]
83
+ fn join_one_item_collection_to_string ( ) {
84
+ let join = JoinFn { } ;
85
+ let s = "hello" ;
86
+ let args = vec ! [ Rc :: new( Value :: PersistentList (
87
+ vec![ Rc :: new( Value :: String ( String :: from( s) ) ) ] . into_iter( ) . collect:: <PersistentList >( ) ) ) ] ;
88
+ assert_eq ! ( Value :: String ( String :: from( "hello" ) ) , join. invoke( args) ) ;
89
+ }
90
+
91
+ #[ test]
92
+ fn join_multiple_items_in_collection_to_string ( ) {
93
+ let join = JoinFn { } ;
94
+ let s = "hello" ;
95
+ let args = vec ! [ Rc :: new( Value :: PersistentList (
96
+ vec![ Rc :: new( Value :: String ( String :: from( s) ) ) ,
97
+ Rc :: new( Value :: I32 ( 5 ) ) ,
98
+ Rc :: new( Value :: String ( String :: from( s) ) ) ]
99
+ . into_iter( ) . collect:: <PersistentList >( ) ) ) ] ;
100
+ assert_eq ! ( Value :: String ( String :: from( "hello5hello" ) ) , join. invoke( args) ) ;
101
+ }
102
+
103
+ #[ test]
104
+ fn join_multiple_items_in_collection_with_separator_to_string ( ) {
105
+ let join = JoinFn { } ;
106
+ let s = "hello" ;
107
+ let args = vec ! [ Rc :: new( Value :: String ( String :: from( ", " ) ) ) ,
108
+ Rc :: new( Value :: PersistentList (
109
+ vec![ Rc :: new( Value :: String ( String :: from( s) ) ) ,
110
+ Rc :: new( Value :: I32 ( 5 ) ) ,
111
+ Rc :: new( Value :: String ( String :: from( s) ) ) ]
112
+ . into_iter( ) . collect:: <PersistentList >( ) ) ) ] ;
113
+ assert_eq ! ( Value :: String ( String :: from( "hello, 5, hello" ) ) , join. invoke( args) ) ;
114
+ }
39
115
40
116
#[ test]
41
- fn reverse_string ( ) {
42
- let reverse = JoinFn { } ;
117
+ fn join_multiple_items_in_pvec_collection_with_separator_to_string ( ) {
118
+ let join = JoinFn { } ;
43
119
let s = "hello" ;
44
- let args = vec ! [ Rc :: new( Value :: String ( String :: from( s) ) ) ] ;
45
- assert_eq ! ( Value :: String ( String :: from( "olleh" ) ) , reverse. invoke( args) ) ;
120
+ let args = vec ! [ Rc :: new( Value :: String ( String :: from( ", " ) ) ) ,
121
+ Rc :: new( Value :: PersistentVector (
122
+ vec![ Rc :: new( Value :: String ( String :: from( s) ) ) ,
123
+ Rc :: new( Value :: I32 ( 5 ) ) ,
124
+ Rc :: new( Value :: String ( String :: from( s) ) ) ]
125
+ . into_iter( ) . collect:: <PersistentVector >( ) ) ) ] ;
126
+ assert_eq ! ( Value :: String ( String :: from( "hello, 5, hello" ) ) , join. invoke( args) ) ;
46
127
}
47
128
}
48
129
}
0 commit comments