I have the following code and it prints the same value of variable c in the inner loop.
global c
proc one { a c } {
for {set i $a} {$i < 10} {incr i} {
two $c
}
}
proc two { c } {
incr c
puts "Value of c is $c"
}
When I run it with the following inputs:
two 0 3
it prints 10 times "Value of c is 4" instead of keeping increasing the value of c inside the loop from 4 to 13.
The problem is the value of c from proc two is not passing up again to the for loop and it takes the same value from proc one parser c as 3. How can I get the desired output?
It sounds like you want to pass the variable c from proc one to proc two by reference so that changes to the value of the variable are reflected back in the caller.
One way to accomplish this in tcl is to pass the name of the variable, and use the upvar command, as follows:
proc one { a c } {
for {set i $a} {$i < 10} {incr i} {
two c ;# <= note: passing 'c' by name, not by value
}
}
proc two { c_name } {
upvar $c_name c ;# <= note: c in this proc is using callers variable
incr c
puts "Value of c is $c"
}
one 0 3
The above produces the following output:
Value of c is 4
Value of c is 5
Value of c is 6
Value of c is 7
Value of c is 8
Value of c is 9
Value of c is 10
Value of c is 11
Value of c is 12
Value of c is 13
I am aware that the following does not reflect the OP's actual question, this is more like a suggestion for re-considering the design. Why use "by reference" parameter passing to begin with, here?
Why not simply stick with a functional style using return and continuously updating the proc-local variable c within the loop body's script?
proc one { a c } {
for {set i $a} {$i < 10} {incr i} {
set c [two $c] ;# <= note: passing 'c' by value
puts "Value of c is $c"
}
}
proc two { c_value } {
incr c_value
return $c_value
}
one 0 3
This will make two re-usable in different contexts, by different callers. Also:
It can be easily extended to multiple return values, variable updates using lassign in the caller's context (one).
Related
i want to execute this code but it is not waorking , the tcl script is as follows:
set i 0
foreach pattern { tiger cat horse dog} {
set pat$i abc
puts "pat$i=${pat$i}"
set i [expr {$i + 1}]
}
the desired result i want in every loop is :
pat0=abc
pat1=abc
pat2=abc
pat3=abc
Please help me to find my mistake
You can read a variable with a computed name with the one-argument form of set:
set i 0
foreach pattern { tiger cat horse dog} {
set pat$i abc
puts "pat$i=[set pat$i]"
set i [expr {$i + 1}]
}
The $... syntax can be considered shorthand for that (except with different, more limited parsing rules that make it more convenient to write).
Alternatively, you can use upvar 0 to make a variable alias with a simple name:
set i 0
foreach pattern { tiger cat horse dog} {
upvar 0 pat$i p
set p abc
puts "pat$i=$p"
set i [expr {$i + 1}]
}
That is much more favoured in a procedure.
HOWEVER, are you sure you need the variable to be called that? Can you use an associative array instead? That's often just as convenient.
set i 0
foreach pattern { tiger cat horse dog} {
set pat($i) abc
puts "pat$i=$pat($i)"
incr i; # The incr command is *right there*
}
I have a situation where I have a recurring piece of music with only slight variations. I want to lay down a base piece as a variable. Then reuse it multiple times, each time altering it by replacing a few notes or measures. Here's a simplified example
base = { c4 c c c }
% pseudo function \replace MUSIC FROM TO ORIG
% FROM and To are pairs of numbers COUNT DURATION
from = #'(1 2)
to = #'(3 4)
var1 = \replace { d4 } \from \to \base
% this means replace
% from "after 1 half note into the music"
% to "after 3 quarter notes into the music"
% that is replace the third beat with { d4 }
% this will be equivalent to
var1 = { c4 c d c }
How do I do this?
A LilyPond solution to this is \tag. I haven't found a built-in functionality for altering a music expression on the fly. However, for the variations usecase, tags serve this purpose. The above example would be this
base = { c4 c \tag #'base c \tag #'var1 d c }
var1 = \keepWithTag #'var1 \base
Here's the problem in which I encountered this issue:
The function should compare the value at each index position and score a point if the value for that position is higher. No point if they are the same. Given a = [1, 1, 1] b = [1, 0, 0] output should be [2, 0]
fun compareArrays(a: Array<Int>, b: Array<Int>): Array<Int> {
var aRetVal:Int = 0
var bRetVal:Int = 0
for(i in 0..2){
when {
a[i] > b[i] -> aRetVal + 1 // This does not add 1 to the variable
b[i] > a[i] -> bRetVal++ // This does...
}
}
return arrayOf(aRetVal, bRetVal)
}
The IDE even says that aRetVal is unmodified and should be declared as a val
What others said is true, but in Kotlin there's more. ++ is just syntactic sugar and under the hood it will call inc() on that variable. The same applies to --, which causes dec() to be invoked (see documentation). In other words a++ is equivalent to a.inc() (for Int or other primitive types that gets optimised by the compiler and increment happens without any method call) followed by a reassignment of a to the incremented value.
As a bonus, consider the following code:
fun main() {
var i = 0
val x = when {
i < 5 -> i++
else -> -1
}
println(x) // prints 0
println(i) // prints 1
val y = when {
i < 5 -> ++i
else -> -1
}
println(y) // prints 2
println(i) // prints 2
}
The explanation for that comes from the documentation I linked above:
The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:
Store the initial value of a to a temporary storage a0;
Assign the result of a.inc() to a;
Return a0 as a result of the expression.
...
For the prefix forms ++a and --a resolution works the same way, and the effect is:
Assign the result of a.inc() to a;
Return the new value of a as a result of the expression.
Because
variable++ is shortcut for variable = variable + 1 (i.e. with assignment)
and
variable + 1 is "shortcut" for variable + 1 (i.e. without assignment, and actually not a shortcut at all).
That is because what notation a++ does is actually a=a+1, not just a+1. As you can see, a+1 will return a value that is bigger by one than a, but not overwrite a itself.
Hope this helps. Cheers!
The equivalent to a++ is a = a + 1, you have to do a reassignment which the inc operator does as well.
This is not related to Kotlin but a thing you'll find in pretty much any other language
I'm trying to wrap my head around Tcl variable scopes, but I'm stuck on what I thought would be a simple concept: how can I access a variable that I've defined outside of my proc, but that I do not explicitly pass to the proc?
I'm trying to avoid setting a bunch of global variables, and only access variables that I define within a particular namespace. What do I need to add to my code below so that the proc can access the variable a, which is obviously not in the scope of the proc?
set a apples
proc myList {b c} {
puts [concat $a $b $c]
}
You can use upvar:
set a apples
proc myList {b c} {
upvar a a
puts [concat $a $b $c]
}
Or, expanding the example a bit to show the "source" variable does not have to exist in the global scope:
proc p1 {} { set a 10; p2 }
proc p2 {} { upvar 1 a b; puts "in p2, value is $b" }
p1
outputs
in p2, value is 10
If a was defined in a namespace, you can use variable:
namespace eval foo {
set a apples
# OR
# variable a apples
}
proc foo::myList {b c} {
variable a
puts [concat $a $b $c]
}
Or if a was created in the global scope, you can still access it without the global function, using :: (I'll reference this SO question for this one):
proc myList {b c} {
puts [concat $::a $b $c]
}
This shows how to have a static variable inside an object or context:
http://www.mail-archive.com/list#rebol.com/msg04764.html
But the scope is too large for some needs, is it possible to have a static variable inside an object function ?
Or you can use FUNCTION/WITH. This makes the function generator take a third parameter, which defines a persistent object that is used as the "self":
accumulate: function/with [value /reset] [
accumulator: either reset [
value
] [
accumulator + value
]
] [
accumulator: 0
]
To use it:
>> accumulate 10
== 10
>> accumulate 20
== 30
>> accumulate/reset 0
== 0
>> accumulate 3
== 3
>> accumulate 4
== 7
You may also want to look at my FUNCS function.
In Rebol 3, use a closure (or CLOS) rather than a function (or FUNC).
In Rebol 2, fake it by having a block that contains your static values, eg :
f: func [
/local sb
][
;; define and initialise the static block
sb: [] if 0 = length? sb [append sb 0]
;; demonstate its value persists across calls
sb/1: sb/1 + 1
print sb
]
;; sample code to demonstrate function
loop 5 [f]
== 1
== 2
== 3
== 4
== 5