I'm not quite sure how variable scope works in Io. The docs say it has closures, but I don't seem to be able to see idx from within the next and prev methods. Parent visibility is the key premise of closures, so how can they work?
List iterator := method(
idx := 0
itr := Object clone
itr next := method(
idx = idx + 1
return self at(idx)
)
itr prev := method(
idx = idx - 1
return self at(idx)
)
return itr
)
How should this be achieved?
So you're fundamentally misunderstanding how methods and blocks work, but that's ok. Let's go over the basics:
Methods are blocks who activate when you call them by name, and whose scope is set to nil. When we talk about scope.
Blocks have their scope set to the context in which they're created.
context means a locals object, basically a stack frame. Scope means who will be the "sender" of the block activation when the block/method is invoked. You can access this by the call sender object inside the context of a method or block.
Now, let's look at your code. It's almost perfect, there's only one thing missing, and it's non-obvious.
Since methods have dynamic scope, their scope message returns nil. This signifies to the evaluator that whichever object received that message, should be passed in as the sending context. We don't want that behaviour, we want to capture some scope, specifically the locals of the iter method we've defined. Let's look at a corrected example:
List iterator := method(
idx := 0
itr := Object clone
itr next := method(
idx = idx + 1
at(idx)
) setScope(thisContext)
itr prev := method(
idx = idx - 1
at(idx)
) setScope(thisContext)
itr
)
I've simplified the bodies, but they haven't changed in terms of functionality (apart from a few less message sends). The important thing is the setScope call passed to the method before assignment to next/prev. I could have chose to rewrite this as:
iter prev := block(
idx = idx - 1
at(idx)
) setIsActivatable(true)
but I'd have then had to make the block activatable, since blocks are not activatable by default. The code above, and the corrected itr prev using method() are functionally equivalent.
Methods are not closures, blocks are. A block is simply a method whose scope is non-nil, they are the same object.
Related
This is my simple groovy script;
def fourtify(String str) {
def clsr = {
str*4
}
return clsr
}
def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...
All I'm trying to do here is being able to access the free variable "str" using the closure instance to understand how closure works behind the scenes a bit more better. Like, perhaps, Python's locals() method.
Is there a way to do this?
The closure you have defined does not store anything in binding object - it simply returns String passed as str variable, repeated 4 times.
This binding object stores all variables that were defined without specifying their types or using def keyword. It is done via Groovy metaprogramming feature (getProperty and setProperty methods to be more specific). So when you define a variable s like:
def clsr = {
s = str*4
return s
}
then this closure will create a binding with key s and value evaluated from expression str * 4. This binding object is nothing else than a map that is accessed via getProperty and setProperty method. So when Groovy executes s = str * 4 it calls setProperty('s', str * 4) because variable/property s is not defined. If we make a slightly simple change like:
def clsr = {
def s = str*4 // or String s = str * 4
return s
}
then binding s won't be created, because setProperty method does not get executed.
Another comment to your example. If you want to see anything in binding object, you need to call returned closure. In example you have shown above the closure gets returned, but it never gets called. If you do:
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
then your closure gets called and binding object will contain bindings (if any set). Now, if you modify your example to something like this:
def fourtify(String str) {
def clsr = {
def n = 4 // it does not get stored as binding
s = str * n
return s
}
return clsr
}
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
you will see following output in return:
binding variables: [args:[], s:aaaaaaaa]
Hope it helps.
in your example str is a parameter of the method/function fortify
however maybe following example will give you better Closure understanding:
def c={ String s,int x-> return s*x }
println( c.getClass().getSuperclass() ) // groovy.lang.Closure
println( c.getMaximumNumberOfParameters() ) // 2
println( c.getParameterTypes() ) // [class java.lang.String, int]
the locals() Python's function better matches groovy.lang.Script.getBinding()
and here is a simple example with script:
Script scr = new GroovyShell().parse('''
println this.getBinding().getVariables() // print "s" and "x"
z = s*(x+1) // declare a new script-level var "z"
println this.getBinding().getVariables() // print "s", "x", and "z"
return s*x
''')
scr.setBinding( new Binding([
"s":"ab",
"x":4
]) )
println scr.run() // abababab
println scr.getBinding().getVariables() // print "s", "x", and "z"
This short method in go's source code has a comment which implies that it's not allocating memory in an optimal way.
... could do better allocation-wise here ...
This is the source code for the Join method.
What exactly is inefficiently allocated here? I don't see a way around allocating the source string slice and the destination byte slice. The source being the slice of keys. The destination being the slice of bytes.
The code referenced by the comment is memory efficient as written. Any allocations are in strings.Join which is written to minimize memory allocations.
I suspect that the comment was accidentally copied and pasted from this code in the net/http package:
// TODO: could do better allocation-wise here, but trailers are rare,
// so being lazy for now.
if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
return err
}
This snippet has the following possible allocations:
[]byte created in strings.Join for constructing the result
string conversion result returned by strings.Join
string result for expression "Trailer: "+strings.Join(keys, ",")+"\r\n"
The []byte conversion result used in io.WriteString
A more memory efficient approach is to allocate a single []byte for the data to be written.
n := len("Trailer: ") + len("\r\n")
for _, s := range keys {
n += len(s) + 1
}
p := make([]byte, 0, n-1) // subtract 1 for len(keys) - 1 commas
p = append(p, "Trailer: "...)
for i, s := range keys {
if i > 0 {
p = append(p, ',')
}
p = append(p, s...)
}
p = append(p, "\r\n"...)
w.Write(p)
I know there is strings.Index and strings.LastIndex, but they just find the first and last. Is there any function I can use, where I can specify the start index? Something like the last line in my example.
Example:
s := "go gopher, go"
fmt.Println(strings.Index(s, "go")) // Position 0
fmt.Println(strings.LastIndex(s, "go")) // Postion 11
fmt.Println(strings.Index(s, "go", 1)) // Position 3 - Start looking for "go" begining at index 1
It's an annoying oversight, you have to create your own function.
Something like:
func indexAt(s, sep string, n int) int {
idx := strings.Index(s[n:], sep)
if idx > -1 {
idx += n
}
return idx
}
No, but it might be simpler to apply strings.Index on a slice of the string
strings.Index(s[1:], "go")+1
strings.Index(s[n:], "go")+n
See example (for the case where the string isn't found, see OneOfOne's answer), but, as commented by Dewy Broto, one can simply test it with a 'if' statement including a simple statement:
(also called 'if' with an initialization statement)
if i := strings.Index(s[n:], sep) + n; i >= n {
...
}
I am writing a program that calculates a Riemann sum based on user input. The program will split the function into 1000 rectangles (yes I know I haven't gotten that math in there yet) and sum them up and return the answer. I am using go routines to compute the 1000 rectangles but am getting an
fatal error: all go routines are asleep - deadlock!
What is the correct way to handle multiple go routines? I have been looking around and haven't seen an example that resembles my case? I'm new and want to adhere to standards. Here is my code (it is runnable if you'd like to see what a typical use case of this is - however it does break)
package main
import "fmt"
import "time"
//Data type to hold 'part' of function; ie. "4x^2"
type Pair struct {
coef, exp int
}
//Calculates the y-value of a 'part' of the function and writes this to the channel
func calc(c *chan float32, p Pair, x float32) {
val := x
//Raise our x value to the power, contained in 'p'
for i := 1; i < p.exp; i++ {
val = val * val
}
//Read existing answer from channel
ans := <-*c
//Write new value to the channel
*c <- float32(ans + (val * float32(p.coef)))
}
var c chan float32 //Channel
var m map[string]Pair //Map to hold function 'parts'
func main() {
c = make(chan float32, 1001) //Buffered at 1001
m = make(map[string]Pair)
var counter int
var temp_coef, temp_exp int
var check string
var up_bound, low_bound float32
var delta float32
counter = 1
check = "default"
//Loop through as long as we have no more function 'parts'
for check != "n" {
fmt.Print("Enter the coefficient for term ", counter, ": ")
fmt.Scanln(&temp_coef)
fmt.Print("Enter the exponent for term ", counter, ": ")
fmt.Scanln(&temp_exp)
fmt.Print("Do you have more terms to enter (y or n): ")
fmt.Scanln(&check)
fmt.Println("")
//Put data into our map
m[string(counter)] = Pair{temp_coef, temp_exp}
counter++
}
fmt.Print("Enter the lower bound: ")
fmt.Scanln(&low_bound)
fmt.Print("Enter the upper bound: ")
fmt.Scanln(&up_bound)
//Calculate the delta; ie. our x delta for the riemann sum
delta = (float32(up_bound) - float32(low_bound)) / float32(1000)
//Make our go routines here to add
for i := low_bound; i < up_bound; i = i + delta {
//'counter' is indicative of the number of function 'parts' we have
for j := 1; j < counter; j++ {
//Go routines made here
go calc(&c, m[string(j)], i)
}
}
//Wait for the go routines to finish
time.Sleep(5000 * time.Millisecond)
//Read the result?
ans := <-c
fmt.Print("Answer: ", ans)
}
It dead locks because both the calc() and the main() function reads from the channel before anyone gets to write to it.
So you will end up having every (non-main) go routine blocking at:
ans := <-*c
waiting for someone other go routine to enter a value into the channel. There fore none of them gets to the next line where they actually write to the channel. And the main() routine will block at:
ans := <-c
Everyone is waiting = deadlock
Using buffered channels
Your solution should have the calc() function only writing to the channel, while the main() could read from it in a for-range loop, suming up the values coming from the go-routines.
You will also need to add a way for main() to know when there will be no more values arriving, perhaps by using a sync.WaitGroup (maybe not the best, since main isn't suppose to wait but rather sum things up) or an ordinary counter.
Using shared memory
Sometimes it is not necessarily a channel you need. Having a shared value that you update with the sync/atomic package (atomic add doesn't work on floats) lock with a sync.Mutex works fine too.
I'd like to call a closure with a delegate parameter to override or shadow the calling context. But the following example prints prints "outside" where I expect "inside".
What am I doing wrong?
def f(String a){
def v = { return a }
v.delegate = [a:"inside"]
// Makes no difference:
// v.resolveStrategy = Closure.DELEGATE_FIRST
println(v.call())
}
f("outside")
I believe the issue is that when the closure is declared inside the function, it 'closes' round the known values in the method (a), so that value becomes effectively hard-coded into the closure (it never hits the delegate to find the unknown value as it is known to the Closure).
If you move the closure v definition outside of the function f, then it works:
v = { return a }
def f(String a){
v.delegate = [a:"inside"]
println(v.call())
}
f("outside")
Other option is to use getProperty('a') instead of directly using a as this forces the use of the delegate to retrieve the value of a.
Can also be done by referring the delegate in the closure. For v as a closure, a does not make any sense (equivalent to use of ExpandoMetaClass)
def f(String a){
def v = { delegate.a }
v.delegate = [a:"inside"]
println v()
}
f("outside")