Tcl Library Source Code

Check-in [a5597ab71e]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Ticket [6002105722]. struct, struct::list - Fixed scoping errors in 'filter' and 'split' commands. Bumped version to 1.8.3. Extended testsuite. Thanks to Adrian Medrano Calvo for report and fix (including tests).
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a5597ab71eed689e30067fd3a6acd48d9c43719f
User & Date: andreask 2014-02-04 22:03:24
References
2014-02-04
22:05 Closed ticket [6002105722]: struct::list filter does not evaluate cmdprefix in caller's scope plus 7 other changes artifact: 49cf303776 user: aku
Context
2014-02-11
19:04
Tcllib 1.16 Release. check-in: 2847321e30 user: aku tags: trunk, release, tcllib-1-16
2014-02-04
22:17
Merged latest trunk fixes to RC, updated the associated docs and README. check-in: 9cb9bdee5a user: aku tags: tcllib-1-16-rc
22:03
Ticket [6002105722]. struct, struct::list - Fixed scoping errors in 'filter' and 'split' commands. Bumped version to 1.8.3. Extended testsuite. Thanks to Adrian Medrano Calvo for report and fix (including tests). check-in: a5597ab71e user: andreask tags: trunk
21:16
Followup on [ea88434604]. Restrict to 32bits. check-in: cfd881b6f8 user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to modules/struct/list.tcl.

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
...
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
....
1821
1822
1823
1824
1825
1826
1827
1828
#
# Side effects:
#       None of its own, but the command prefix can perform arbitrary actions.

proc ::struct::list::Lfilter {sequence cmdprefix} {
    # Shortcut when nothing is to be done.
    if {[::llength $sequence] == 0} {return $sequence}
    return [Lfold $sequence {} [::list ::struct::list::FTest $cmdprefix]]
}

proc ::struct::list::FTest {cmdprefix result item} {
    set pass [uplevel 1 [::linsert $cmdprefix end $item]]
    if {$pass} {::lappend result $item}
    return $result
}
................................................................................
	foreach {pv fv} $args break
	upvar 1 $pv pass $fv fail
	if {[::llength $sequence] == 0} {
	    set pass {}
	    set fail {}
	    return {0 0}
	}
	foreach {pass fail} [Lfold $sequence {} [::list ::struct::list::PFTest $cmdprefix]] break
	return [::list [llength $pass] [llength $fail]]
    } else {
	return -code error \
		"wrong#args: should be \"::struct::list::Lsplit sequence cmdprefix ?passVar failVar?"
    }
}

................................................................................
## Ready

namespace eval ::struct {
    # Get 'list::list' into the general structure namespace.
    namespace import -force list::list
    namespace export list
}
package provide struct::list 1.8.2






|







 







|







 







|
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
...
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
....
1821
1822
1823
1824
1825
1826
1827
1828
#
# Side effects:
#       None of its own, but the command prefix can perform arbitrary actions.

proc ::struct::list::Lfilter {sequence cmdprefix} {
    # Shortcut when nothing is to be done.
    if {[::llength $sequence] == 0} {return $sequence}
    return [uplevel 1 [::list ::struct::list::Lfold $sequence {} [::list ::struct::list::FTest $cmdprefix]]]
}

proc ::struct::list::FTest {cmdprefix result item} {
    set pass [uplevel 1 [::linsert $cmdprefix end $item]]
    if {$pass} {::lappend result $item}
    return $result
}
................................................................................
	foreach {pv fv} $args break
	upvar 1 $pv pass $fv fail
	if {[::llength $sequence] == 0} {
	    set pass {}
	    set fail {}
	    return {0 0}
	}
	foreach {pass fail} [uplevel 1 [::list ::struct::list::Lfold $sequence {} [::list ::struct::list::PFTest $cmdprefix]]] break
	return [::list [llength $pass] [llength $fail]]
    } else {
	return -code error \
		"wrong#args: should be \"::struct::list::Lsplit sequence cmdprefix ?passVar failVar?"
    }
}

................................................................................
## Ready

namespace eval ::struct {
    # Get 'list::list' into the general structure namespace.
    namespace import -force list::list
    namespace export list
}
package provide struct::list 1.8.3

Changes to modules/struct/list.test.

495
496
497
498
499
500
501




















502
503
504
505
506
507
508
...
554
555
556
557
558
559
560











561
562
563
564
565
566
567
test filter-4.3 {filter command} {
    filter {3 5 7} even
} {}

test filter-4.4 {filter command} {
    filter {2 4 6} even
} {2 4 6}





















#----------------------------------------------------------------------

interp alias {} filterfor {} ::struct::list::list filterfor

test filterfor-4.1 {filterfor command} {
    filterfor i {1 2 3 4 5 6 7 8} {($i % 2) == 0}
................................................................................
    list [lsplit {3 5 7} even pass fail] $pass $fail
} {{0 3} {} {3 5 7}}

test split-4.8 {split command} {
    list [lsplit {2 4 6} even pass fail] $pass $fail
} {{3 0} {2 4 6} {}}












#----------------------------------------------------------------------

interp alias {} shift {} ::struct::list::list shift

test shift-4.1 {shift command} {
    set v {1 2 3 4 5 6 7 8}
    list [shift v] $v






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







 







>
>
>
>
>
>
>
>
>
>
>







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
test filter-4.3 {filter command} {
    filter {3 5 7} even
} {}

test filter-4.4 {filter command} {
    filter {2 4 6} even
} {2 4 6}

# Alternate which elements are filtered by using a global variable
# flag. Used to test that the `cmdprefix' is evaluated in the caller's
# scope.
#
# The flag variable should be set on the -setup phase.

proc alternating {_} {
    upvar 1 flag flag;
    set flag [expr {!($flag)}];
    return $flag;
}

test filter-4.5 {filter evaluates cmdprefix on outer scope} -setup {
    set flag 1
} -body {
    filter {1 2 3 4 5 6} alternating
} -cleanup {
    unset flag
} -result {2 4 6}

#----------------------------------------------------------------------

interp alias {} filterfor {} ::struct::list::list filterfor

test filterfor-4.1 {filterfor command} {
    filterfor i {1 2 3 4 5 6 7 8} {($i % 2) == 0}
................................................................................
    list [lsplit {3 5 7} even pass fail] $pass $fail
} {{0 3} {} {3 5 7}}

test split-4.8 {split command} {
    list [lsplit {2 4 6} even pass fail] $pass $fail
} {{3 0} {2 4 6} {}}


# See test filter-4.5 for explanations.

test split-4.9 {split evaluates cmdprefix on outer scope} -setup {
    set flag 1
} -body {
    list [lsplit {1 2 3 4 5 6 7 8} alternating pass fail] $pass $fail
} -cleanup {
    unset flag
} -result {{4 4} {2 4 6 8} {1 3 5 7}}

#----------------------------------------------------------------------

interp alias {} shift {} ::struct::list::list shift

test shift-4.1 {shift command} {
    set v {1 2 3 4 5 6 7 8}
    list [shift v] $v

Changes to modules/struct/pkgIndex.tcl.

14
15
16
17
18
19
20
21
22
23
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.2  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4    [list source [file join $dir graph.tcl]]
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]






|


14
15
16
17
18
19
20
21
22
23
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.3  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4    [list source [file join $dir graph.tcl]]
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]

Changes to modules/struct/struct_list.man.

1
2

3
4
5
6
7
8
9
10
..
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
[comment {-*- tcl -*- doctools manpage}]
[comment {$Id: struct_list.man,v 1.24 2010/10/05 21:47:25 andreas_kupries Exp $}]

[manpage_begin struct::list n 1.8.2]
[keywords assign]
[keywords common]
[keywords comparison]
[keywords diff]
[keywords differential]
[keywords equal]
[keywords equality]
................................................................................
[keywords swapping]
[copyright {2003-2005 by Kevin B. Kenny. All rights reserved}]
[copyright {2003-2012 Andreas Kupries <[email protected]>}]
[moddesc {Tcl Data Structures}]
[titledesc {Procedures for manipulating lists}]
[category  {Data structures}]
[require Tcl 8.4]
[require struct::list [opt 1.8.2]]
[description]

[para]

The [cmd ::struct::list] namespace contains several useful commands
for processing Tcl lists. Generally speaking, they implement
algorithms more complex or specialized than the ones provided by Tcl

>
|







 







|







1
2
3
4
5
6
7
8
9
10
11
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[comment {-*- tcl -*- doctools manpage}]
[comment {$Id: struct_list.man,v 1.24 2010/10/05 21:47:25 andreas_kupries Exp $}]
[vset LIST_VERSION 1.8.3]
[manpage_begin struct::list n [vset LIST_VERSION]]
[keywords assign]
[keywords common]
[keywords comparison]
[keywords diff]
[keywords differential]
[keywords equal]
[keywords equality]
................................................................................
[keywords swapping]
[copyright {2003-2005 by Kevin B. Kenny. All rights reserved}]
[copyright {2003-2012 Andreas Kupries <[email protected]>}]
[moddesc {Tcl Data Structures}]
[titledesc {Procedures for manipulating lists}]
[category  {Data structures}]
[require Tcl 8.4]
[require struct::list [opt [vset LIST_VERSION]]]
[description]

[para]

The [cmd ::struct::list] namespace contains several useful commands
for processing Tcl lists. Generally speaking, they implement
algorithms more complex or specialized than the ones provided by Tcl