dideod98
dideod98

Reputation: 111

how to return variable from proc

I try to convert script from perl to tcl. perl script is working well... but tcl is not. I think because of pointer. I don't know how to use pointer in tcl. Can you update script to return variable properly..?

In tcl script, If I puts $sofar, it is working well. but If I want to return $sofar as $output like perl script, it isn't working well..

please help me ...

#perl script
my @test = &find( 0, [], [], $target, @input );

foreach my $test (@test) {
    print "@{$test}\n";
}

sub find
  {
  my ($sum, $sofar, $output, $want, @numbers ) = @_;
#   print "$sum //// @{$sofar} /// @numbers\n";
  if( $sum == $want )
    {
   # print "@{$sofar}\n";
    push @{$output},$sofar;
    }
  elsif( $sum < $want and @numbers and $numbers[0] > 0 )
    {
    find( $sum + $numbers[0], [ @{$sofar}, $numbers[0] ], $output, $want, @numbers );
    find( $sum, $sofar, $output, $want, @numbers[1..$#numbers] );
    }
    return @{$output};
  }
#tcl script
proc combinationSum {sum sofar want numbers } {
    if { $sum == $want } {
        puts $sofar
        #lappend output $sofar
                         }
    if { ( $sum < $want ) && ( [lindex $numbers 0] > 0 ) && ( [llength $numbers] > 0 ) } {
        combinationSum [expr $sum + [lindex $numbers 0]] [concat $sofar [lindex $numbers 0]] $want $numbers
        combinationSum $sum $sofar $want [lrange $numbers 1 end]
        puts YYY,$sum,$sofar
                                                                                        }
        #return $output
}

set test_input [list 2 3 4 7 8  ]
set test_target 10
set test_output  [ combinationSum 0 [] $test_target $test_input]
puts $test_output

Upvotes: 1

Views: 247

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137567

To return a list (or any other value), just do something like:

# Returns the contents of a variable; this is cheap as it just does reference shuffling
return $sofar

or:

# A command that produces a list can have that list be returned immediately
return [concat $this $that]

The returned list is possibly a copy; Tcl's values use copy-on-write semantics under the covers for efficiency. This means that at the script level, the semantics are read-only without paying the penalty for making ridiculous numbers of copies. What there isn't is action-at-a-distance: if you want to change something, you have to have it right there or work via a variable.


Which brings us to variables. You can modify a variable in the caller; that requires bringing the caller's variable into scope using upvar:

upvar 1 $callersName myName
set myName [thing-to-do-the-update $myName]

By convention, you should not assume the name in the caller, and should instead always explicitly pass the variable name as an argument to the procedure. It's not required that you do that, but it makes it so much easier to work with the code that if you don't it is a sign of bad code problems to come.

Upvotes: 2

Related Questions