ycl

Check-in [0b8c3fdd98]
Login

Check-in [0b8c3fdd98]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:list new routines list complement subset
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0b8c3fdd986366b8b2189468e425ed956095e4a7
User & Date: pooryorick 2019-09-22 21:36:23.280
Context
2019-09-22
21:38
tcl merged [armour] into [string printable] check-in: fd979799af user: pooryorick tags: trunk
21:36
list new routines list complement subset check-in: 0b8c3fdd98 user: pooryorick tags: trunk
21:34
ns fix bug in dupcmds check-in: a898b66be5 user: pooryorick tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to packages/list/lib/list.tcl.
1
2
3
4
5
6
7
8
9
10

11
12

13
14
15
16
17
18
19
#! /bin/env tclsh

namespace import ::tcl::mathop::!
namespace import ::tcl::mathop::-
namespace import ::tcl::mathfunc::abs
namespace import ::tcl::mathfunc::max

package require {ycl proc}
[yclprefix]::proc alias [yclprefix]::proc::alias
alias [yclprefix]::proc::argsswitch

alias [yclprefix]::proc::checkargs
alias [yclprefix]::proc::optswitch

package require {ycl parse tcl commands}
alias [yclprefix]::parse::tcl::commands::commands
#package require struct::list
#namespace import ::struct::list::list

package require {ycl sugar}
alias [yclprefix]::sugar::block










>


>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /bin/env tclsh

namespace import ::tcl::mathop::!
namespace import ::tcl::mathop::-
namespace import ::tcl::mathfunc::abs
namespace import ::tcl::mathfunc::max

package require {ycl proc}
[yclprefix]::proc alias [yclprefix]::proc::alias
alias [yclprefix]::proc::argsswitch
alias [yclprefix]::proc::block
alias [yclprefix]::proc::checkargs
alias [yclprefix]::proc::optswitch
alias [yclprefix]::proc::stub
package require {ycl parse tcl commands}
alias [yclprefix]::parse::tcl::commands::commands
#package require struct::list
#namespace import ::struct::list::list

package require {ycl sugar}
alias [yclprefix]::sugar::block
161
162
163
164
165
166
167



















168
169
170
171
172
173
174
			break
		}
		incr i
	}
	return $res
}





















proc cut {listname args} {
	upvar $listname list
	::foreach arg $args[set args 0] {
		lassign $args first last
		if {$last eq {}} {
			set last $first







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
			break
		}
		incr i
	}
	return $res
}

block {
	foreach op {complement subset} {
		try [string map [list @op@ $op] {
			stub @op@ {list1name list2name} {
				package require {ycl list list}
				package require {ycl set}
				alias yset [yclprefix]::set
			} {
				upvar $list1name list1 $list2name list2
				set cmd1 [[list .spawn [info cmdcount]_list] .init list $list1]
				set cmd2 [[list .spawn [info cmdcount]_list] .init list $list2]
				set res [yset @op@ $cmd1 $cmd2]
				rename $cmd1 {}
				rename $cmd2 {}
				return $res
			}
		}]
	}
}

proc cut {listname args} {
	upvar $listname list
	::foreach arg $args[set args 0] {
		lassign $args first last
		if {$last eq {}} {
			set last $first
309
310
311
312
313
314
315
316

317
318
319
320
321
322

323
324
325
326
327
328
329
330


variable doc::filter {
	description {
		Filters items out of a list using another list as a mask.
	}
}
proc filter {list mask} {

	set res {}
	::foreach item $list i $mask {
		if {$i} {
			::lappend res $item
		}
	}

	return $res
}


variable doc::consume {
	description
		like [foreach]
			but accepts the names of lists







|
>






>
|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353


variable doc::filter {
	description {
		Filters items out of a list using another list as a mask.
	}
}
proc filter {listname mask} {
	upvar $listname list
	set res {}
	::foreach item $list i $mask {
		if {$i} {
			::lappend res $item
		}
	}
	set list $res[set res {}]
	return
}


variable doc::consume {
	description
		like [foreach]
			but accepts the names of lists
739
740
741
742
743
744
745

































746
747
748
749
750
751
752
		lindex item end
		set res $item
		lreplace list end end
		return $res
	}
}



































proc prepend {varname args} {
	upvar $varname var
	# create the variable if it doesn't exist
	lappend var
	linsert var 0 {*}$args
	return $var







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
		lindex item end
		set res $item
		lreplace list end end
		return $res
	}
}


variable doc::prefix {
	description
		determine whether the value in $list1var is a prefix of the value in
		$list2var

		if $list1var is omitted

			the name "prefix" is used
}
proc prefix {list1var args} {
	llength args
	if {$len} {
		set list2var $args[set args {}]
		lindex list2var 0
	} else {
		set list2var $list1var
		set list1var prefix
	}
	upvar $list1var list1 $list2var list2
	llength list1
	::foreach item1 $list1 item2 $list2 {
		if {$item1 ne $item2} {
			set list1 0
			return
		}
		if {[incr len -1] == 0} break
	}
	set list1 1
	return
}



proc prepend {varname args} {
	upvar $varname var
	# create the variable if it doesn't exist
	lappend var
	linsert var 0 {*}$args
	return $var
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
	description
		set the variable named $listname to the remaining items in a list after
		the items in $prefix

		if $listname is omitted
			the name "tail" is used
}


block {
	set body {
		llength args
		@argswitch@
		upvar $listname list
		llength prefix
		::foreach item1 $list item2 $prefix {







<
<







954
955
956
957
958
959
960


961
962
963
964
965
966
967
	description
		set the variable named $listname to the remaining items in a list after
		the items in $prefix

		if $listname is omitted
			the name "tail" is used
}


block {
	set body {
		llength args
		@argswitch@
		upvar $listname list
		llength prefix
		::foreach item1 $list item2 $prefix {
Changes to packages/list/lib/list.test.tcl.
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41

42
43
44
45
46
47
48
	interp alias {} [namespace current]::any {} [yclprefix] list any
	interp alias {} [namespace current]::all {} [yclprefix] list all 
	interp alias {} [namespace current]::are {} [yclprefix] list are 
	interp alias {} [namespace current]::which {} [yclprefix] list which 
	namespace import [yclprefix]::list::add
	namespace import [yclprefix]::list::addp
	namespace import [yclprefix]::list::compare

	namespace import [yclprefix]::list::consume
	namespace import [yclprefix]::list::dedent
	namespace import [yclprefix]::list::dedent_exact
	namespace import [yclprefix]::list::filter
	namespace import [yclprefix]::list::head
	namespace import [yclprefix]::list::join
	namespace import [yclprefix]::list::lappend
	namespace import [yclprefix]::list::lappend*
	namespace import [yclprefix]::list::lindex
	namespace import [yclprefix]::list::linsert
	namespace import [yclprefix]::list::llength
	namespace import [yclprefix]::list::lmap
	namespace import [yclprefix]::list::lrange
	namespace import [yclprefix]::list::lreplace
	namespace import [yclprefix]::list::lreverse
	namespace import [yclprefix]::list::lsort
	namespace import [yclprefix]::list::order
	namespace import [yclprefix]::list::pick
	namespace import [yclprefix]::list::pop

	namespace import [yclprefix]::list::prepend
	namespace import [yclprefix]::list::randindex
	namespace import [yclprefix]::list::rlindex
	namespace import [yclprefix]::list::sl
	namespace import [yclprefix]::list::slwild
	namespace import [yclprefix]::list::split

	namespace import [yclprefix]::list::tail
	namespace import [yclprefix]::list::take
	namespace import [yclprefix]::list::trim
	namespace import [yclprefix]::list::unique
	namespace import [yclprefix]::list::unpackvar
	namespace import [yclprefix]::list::unset
	namespace import [yclprefix]::list::zip







>



















>






>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	interp alias {} [namespace current]::any {} [yclprefix] list any
	interp alias {} [namespace current]::all {} [yclprefix] list all 
	interp alias {} [namespace current]::are {} [yclprefix] list are 
	interp alias {} [namespace current]::which {} [yclprefix] list which 
	namespace import [yclprefix]::list::add
	namespace import [yclprefix]::list::addp
	namespace import [yclprefix]::list::compare
	namespace import [yclprefix]::list::complement
	namespace import [yclprefix]::list::consume
	namespace import [yclprefix]::list::dedent
	namespace import [yclprefix]::list::dedent_exact
	namespace import [yclprefix]::list::filter
	namespace import [yclprefix]::list::head
	namespace import [yclprefix]::list::join
	namespace import [yclprefix]::list::lappend
	namespace import [yclprefix]::list::lappend*
	namespace import [yclprefix]::list::lindex
	namespace import [yclprefix]::list::linsert
	namespace import [yclprefix]::list::llength
	namespace import [yclprefix]::list::lmap
	namespace import [yclprefix]::list::lrange
	namespace import [yclprefix]::list::lreplace
	namespace import [yclprefix]::list::lreverse
	namespace import [yclprefix]::list::lsort
	namespace import [yclprefix]::list::order
	namespace import [yclprefix]::list::pick
	namespace import [yclprefix]::list::pop
	namespace import [yclprefix]::list::prefix
	namespace import [yclprefix]::list::prepend
	namespace import [yclprefix]::list::randindex
	namespace import [yclprefix]::list::rlindex
	namespace import [yclprefix]::list::sl
	namespace import [yclprefix]::list::slwild
	namespace import [yclprefix]::list::split
	namespace import [yclprefix]::list::subset
	namespace import [yclprefix]::list::tail
	namespace import [yclprefix]::list::take
	namespace import [yclprefix]::list::trim
	namespace import [yclprefix]::list::unique
	namespace import [yclprefix]::list::unpackvar
	namespace import [yclprefix]::list::unset
	namespace import [yclprefix]::list::zip
182
183
184
185
186
187
188
















189
190
191
192
193
194
195
			lappend res item
		}
		return $res
	} -cleanup [cleanup1] -result [sl {
		one break {two three} four five
	}]


















	test consume_break {} -body {
		set list {one {two three} four five}
		set res {}
		consume item list {
			if {$item eq {four}} break
			lappend res item







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
			lappend res item
		}
		return $res
	} -cleanup [cleanup1] -result [sl {
		one break {two three} four five
	}]


	test complement {} -setup $setup1 -body {
		set list2 $list1
		lreplace list2 3 3

		set complement [complement list2 list1] 
		lappend res complement

		set complement [complement list1 list2] 
		lappend res complement

		return $res
	} -cleanup [cleanup1] -result [sl {
		{} {\{\"\ }
	}]


	test consume_break {} -body {
		set list {one {two three} four five}
		set res {}
		consume item list {
			if {$item eq {four}} break
			lappend res item
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
		dedent res 
		expr {$res eq $original}
	} -cleanup [cleanup1] -result 1


	test filter {} -body {
		set list {banana cucumbers {star fruit} kiwi}
		filter $list [are $list in [data fruits]]

	} -cleanup [cleanup1] -result [sl {
		banana {star fruit} kiwi
	}]


	test head {} -setup $setup1 -body {
		head list1 {viis 001 01}







|
>







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
		dedent res 
		expr {$res eq $original}
	} -cleanup [cleanup1] -result 1


	test filter {} -body {
		set list {banana cucumbers {star fruit} kiwi}
		filter list [are $list in [data fruits]]
		return $list
	} -cleanup [cleanup1] -result [sl {
		banana {star fruit} kiwi
	}]


	test head {} -setup $setup1 -body {
		head list1 {viis 001 01}
559
560
561
562
563
564
565




























566
567
568
569
570
571
572
	test pop_notenough_vars {} -body {
		set list {one {two three} four five}
		pop list var1 var2 var3 var4 var5
	} -cleanup [cleanup1] -returnCodes 1 -result [sl {
		{not enough items in list}
	}]






























	test prepend {} -setup $setup1 -body {
		prepend list1 one {two three} four
		return $list1
	} -cleanup [cleanup1] -result [sl {
		one {two three} four
		üks {kaks kolm} 020 "\{\" " neli " \t\n " 20 010 10 viis







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
	test pop_notenough_vars {} -body {
		set list {one {two three} four five}
		pop list var1 var2 var3 var4 var5
	} -cleanup [cleanup1] -returnCodes 1 -result [sl {
		{not enough items in list}
	}]


	test prefix {} -setup $setup1 -body {
		set list2 $list1
		lrange list2 0 4
		set prefix $list2
		prefix prefix list1
		lappend res prefix

		set prefix $list1
		prefix prefix list2
		lappend res prefix

		set list2 $list1
		lrange list2 0 4
		set prefix $list2
		prefix list1
		lappend res prefix

		set prefix $list1
		prefix list2
		lappend res prefix


		return $res
	} -cleanup [cleanup1] -result [sl {
		1 0 1 0
	}]


	test prepend {} -setup $setup1 -body {
		prepend list1 one {two three} four
		return $list1
	} -cleanup [cleanup1] -result [sl {
		one {two three} four
		üks {kaks kolm} 020 "\{\" " neli " \t\n " 20 010 10 viis
612
613
614
615
616
617
618
















619
620
621
622
623
624
625
		set list {one,two,three,four}
		split list ,
		return $list
	} -cleanup [cleanup1] -result [sl {
		one two three four
	}]


















	test tail {} -body {
		set list {one {two three} four {five six}}
		tail list {one {two three}}
		return $list
	} -cleanup [cleanup1] -result [sl {
		four {five six}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
		set list {one,two,three,four}
		split list ,
		return $list
	} -cleanup [cleanup1] -result [sl {
		one two three four
	}]


	test subset {} -setup $setup1 -body {
		set list2 $list1
		lreplace list2 3 3

		set subset [subset list2 list1] 
		lappend res subset

		set subset [subset list1 list2] 
		lappend res subset

		return $res
	} -cleanup [cleanup1] -result [sl {
		1 0
	}]


	test tail {} -body {
		set list {one {two three} four {five six}}
		tail list {one {two three}}
		return $list
	} -cleanup [cleanup1] -result [sl {
		four {five six}
Changes to packages/list/lib/object.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32



33
































34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64












65
66
67
68
69
70
71
72
73
#! /usr/bin/tclsh


package require {ycl proc}
[yclprefix] proc alias [yclprefix]::proc::alias
alias [yclprefix]::proc::checkargs


variable doc::.init {
	args {
		_ {}
		list {
			description {
				the initial list value
			}
			default {
				::lindex {}
			}
			process {
				$_ $ list $list
			}
		}
	}
}
proc .init {_ args} {

	$_ .vars cursor
	checkargs ${doc::.init} {*}$args
	set cursor -1
	return $
}
.my .method .init






































proc has {_ item} {
	$_ .vars list
	set res [lsearch -exact $list $item]
	expr {$res >= 0}
}
.my .method has



proc move {_ index} {
	$_ .vars cursor list
	if {$index < 0 || $index > [::llength $list]} {
		error [list {index out of range} $index]
	}
	set cursor $index
	return
}
.my .method move


proc next {_} {
	$_ .vars cursor list
	incr cursor
	if {$cursor >= [::llength $list] } {
		return -code break
	}
	::lindex $list $cursor
}
.my .method next














proc value {_ args} {
	$_ .vars list
	lset len [::length $args]
	if {$len == 1} {
		set list $args
	} elseif {$len == 0} {
	} else {
		error [list {wrong # args}]
	}






>












|





>
|


|




>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|






<
<
<
<
<
<
<
<
<
<
<
<
|
|









>
>
>
>
>
>
>
>
>
>
>
>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78












79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#! /usr/bin/tclsh


package require {ycl proc}
[yclprefix] proc alias [yclprefix]::proc::alias
alias [yclprefix]::proc::checkargs


variable doc::.init {
	args {
		_ {}
		list {
			description {
				the initial list value
			}
			default {
				::lindex {}
			}
			process {
				$self $ list $list
			}
		}
	}
}
proc .init {_ args} {
	set self [$_ _]
	$self .vars cursor
	checkargs ${doc::.init} {*}$args
	set cursor -1
	return $self
}
.my .method .init


variable doc::advance {
	description
		advance the cursor value

}
proc advance {_ amount} {
	$_ . .vars cursor list
	set index [expr {$cursor + entier(amount)}]
	$_ .cursor $index
}
.my .method advance


variable doc::cursor {
	description
		provides the cursor value

		if $index is provided

			sets the cursor value to $index
		
}
proc cursor {_ args} {
	$_ . .vars cursor list
	if {[llength $args]} {
		lassign $args new
		if {$new < -1 || $new > [::llength $list]} {
			error [list {out of range} $new]
		}
		set cursor $new
	}
	return $cursor
}
.my .method cursor


proc has {_ item} {
	$_ . .vars list
	set res [lsearch -exact $list $item]
	expr {$res >= 0}
}
.my .method has














proc next _ {
	$_ . .vars cursor list
	incr cursor
	if {$cursor >= [::llength $list] } {
		return -code break
	}
	::lindex $list $cursor
}
.my .method next


proc peek _ {
	$_ . .vars cursor list
	set idx [expr {$cursor + 1}]
	if {$idx >= [::llength $list] } {
		error finished
	}
	::lindex $list $idx
}
.my .method peek



proc value {_ args} {
	$_ . .vars list
	lset len [::length $args]
	if {$len == 1} {
		set list $args
	} elseif {$len == 0} {
	} else {
		error [list {wrong # args}]
	}
Changes to packages/list/pkgIndex.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/env tclsh

package ifneeded {ycl list} 1.0 [list apply {{dir} {
	package require {ycl package}
	[yclprefix]::package::source list $dir/lib/list.tcl
	package provide {ycl list} 1.0
}} $dir]


package ifneeded {ycl list list} 1.0 [list apply {{dir} {
	package require {ycl package}
	package require {ycl shelf shelf}
	set name [yclprefix]::list::list


|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/env tclsh

package ifneeded {ycl list} 2.0 [list apply {{dir} {
	package require {ycl package}
	[yclprefix]::package::source list $dir/lib/list.tcl
	package provide {ycl list} 2.0
}} $dir]


package ifneeded {ycl list list} 1.0 [list apply {{dir} {
	package require {ycl package}
	package require {ycl shelf shelf}
	set name [yclprefix]::list::list