What is the correct way to handle pointer structs in loops in Go? - pointers

In this example on the go playground, you can see that looping over a list of objects and putting them into an array of pointer structs ends up putting the same entry into the array multiple times.
http://play.golang.org/p/rICA21kFWL
One possible solution to the issue is to make a new string and sprint the string out of the looped string into the new string. This seems silly though.
What is the idiomatically correct way to handle this problem?

In case I understood correctly and you simply want an array of pointers pointing to the respective string in the original array, you can always do this
# choose correct size from beginning to avoid costly resize
o := make([]*string, len(f))
# iterate only over index
for i := range f {
o[i] = &f[i].username
}
Here's your go playground with the changes sketched out above.

Related

Extending a Variable's Lifetime

To be fair, I cannot be entirely sure the title correctly describes the problem I am having, as it merely mirrors my current understanding of Ada as it is.
The Problem
I have a function:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
This function is supposed to create a new menu option for the user, that may in turn be inserted into a menu (one that you might see in a terminal-based environment). You are all probably sighing, as quite evidently, the O variable would be deallocated at the end of this function (from my current understanding). As such, using the Unrestricted_Access here is just plain stupidity, but it mirrors the result of what it is I am trying to accomplish (as this code indeed does compile successfully).
The Access_Option is defined as following:
type Access_Option is access all Option;
The idea is that with an access to the option, which in turn is a discriminated record, is that we can store it within an array-like structure (as the object itself varies in size).
Beyond doubt, it would be nice if we could instead use the Access attribute for this, as the compiler would then make sure the lifetime is long enough of the O variable we are referencing, but as the lifetime as a matter of fact only exists til the end of the Make_Option function, we are presented with the following:
non-local pointer cannot point to local object
What I am then asking, is: how would I go about having a function to create Access_Options for me? Is such a thing even possible, or am I doing it all wrong? To clarify, what I am trying to do is create a neat way for filling an array with references to discriminated records, that I can then dereference and use.
Thought Process
I personally have not tried too many things, more than think about solutions that may be plausible for the problem. And, frankly, rather than going crazy of working makeshift solutions, it would be nice to have a solution that works for large-scale applications too, without messing up the code base to bad.
Would you perhaps have some sort of object queue to handle it? Does Ada even deallocate resources automatically in the first place? Gah. I am confused.
Would it, in fact, be possible to somehow place the O variable outside of the scope for deallocation to then manually deallocate it later?
Given the example you show above a much simpler approach is to simply make an array of Unbounded_String:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
Don't try that.
There are two alternative options:
1) Use Ada.Containers.Indefinite_Vectors instead of a plain array.
2) Give your record discriminant a default value. Then you can store it in a plain array.
You seem to be reinventing the bounded string. Alternatives include
Using an instantiation of Ada.Strings.Bounded.Generic_Bounded_Length
Using Ada.Strings.Unbounded
Using an indefinite container (Ada.Containers.Indefinite_*) to hold type String

Why is fmt.Println not consistent when printing pointers?

I'm an experienced programmer but have never before touched Go in my life.
I just started playing around with it and I found that fmt.Println() will actually print the values of pointers prefixed by &, which is neat.
However, it doesn't do this with all types. I'm pretty sure it is because the types it does not work with are primitives (or at least, Java would call them that, does Go?).
Does anyone know why this inconsistent behaviour exists in the Go fmt library? I can easily retrieve the value by using *p, but for some reason Println doesn't do this.
Example:
package main
import "fmt"
type X struct {
S string
}
func main() {
x := X{"Hello World"}
fmt.Println(&x) // &{Hello World} <-- displays the pointed-to value prefixed with &
fmt.Println(*(&x)) // {Hello World}
i := int(1)
fmt.Println(&i) // 0x10410028 <-- instead of &1 ?
fmt.Println(*(&i)) // 1
}
The "technical" answer to your question can be found here:
https://golang.org/src/fmt/print.go?#L839
As you can see, when printing pointers to Array, Slice, Struct or Map types, the special rule of printing "&" + value applies, but in all other cases the address is printed.
As for why they decided to only apply the rule for those, it seems the authors considered that for "compound" objects you'd be interested in always seeing the values (even when using a pointer), but for other simple values this was not the case.
You can see that reasoning here, where they added the rule for the Map type which was not there before:
https://github.com/golang/go/commit/a0c5adc35cbfe071786b6115d63abc7ad90578a9#diff-ebda2980233a5fb8194307ce437dd60a
I would guess this had to do with the fact that it is very common to use for example pointers to Struct to pass them around (so many times you'd just forget to de-reference the pointer when wanting to print the value), but no so common to use pointers to int or string to pass those around (so if you were printing the pointer you were probably interested in seeing the actual address).

In Golang, can I customise key comparison, if I am taking struct as key?

How does map in Golang compare keys? For some reason, I need to have a struct as a key, which has 2 values inside. I want map to compare by only first value, not second. Second is for my usage. Like in java, I can customise equals method, so map will take only logically equal keys within. Is there any way to do that?
Edit: Looks like there is no way to do that. So I am now putting down my problem here. Please help me to think in 'Go-way'.
So, I want to implement a 'timed map', which tracks the key insertion time. In other words, there is a map which accepts and processes the values. Now, if the data in map is older than some specific time-interval, then I should clear it out.
So, I thought of having a key struct which has id and timestamp. When a new key comes, map takes it with id and currentTimeInMillis. After sometime, if a key comes which already exists, then map should preserve the first insertion time and only updates the value array.
To process, I will have a looping over map and check if any particular key is inside for more than threshold limit, then I clear it out. I can have this timestamp in value array, but that also has a timestamp of its own, so putting one more might confuse someone else.
Please suggest something.
Put the time on your value. Here's some example of how to structure your data.
type DataObj struct {
Id int
Updated time.Date
// other fields
}
m := map[int]DataObj{}
m[d.Id] = d // assign using the id as your key
for k, v := range m {
if time.Since(v.Updated) > duration {
delete(m, k) // remove the stale item
}
}
// some logic like this for adding/overwriting
v, ok := m[newObj.Id]
if ok { // an element with this id existed
if time.Since(v.Updated) > duration {
m[v.Id] = newObj // assign new value over old one
}
}
I can't provide anything much more specific because you don't have any code with which to work. It seems like you'd probably like some of this (like the remove bits) to run on a timer. To do that, invoke the function as a goroutine and use a timer so every X seconds it unblocks and removes items from the map. If you're doing this you also need to use a mutex so the calling scope doesn't access the map while the remove function running the background is filtering out old items.
The overwrite bit is really straight forward, just test if the item is in the map, check it's time stamp, if it's beyond the threshold assign the new value, if not do nothing.
The main thing to take away here is to not use a struct for your key... There is no reason to do object equality, your object has an id, us it as your key. Everything else you care about can be held on the value (even the key itself is). As someone pointed out this isn't Java and even if it were, equality overrides in C# and Java are literally a fucking nightmare.

What is the difference between Vec<struct> and &[struct]?

I often find myself getting an error like this:
mismatched types: expected `collections::vec::Vec<u8>`, found `&[u8]` (expected struct collections::vec::Vec, found &-ptr)
As far as I know, one is mutable and one isn't but I've no idea how to go between the types, i.e. take a &[u8] and make it a Vec<u8> or vice versa.
What's the different between them? Is it the same as String and &str?
Is it the same as String and &str?
Yes. A Vec<T> is the owned variant of a &[T]. &[T] is a reference to a set of Ts laid out sequentially in memory (a.k.a. a slice). It represents a pointer to the beginning of the items and the number of items. A reference refers to something that you don't own, so the set of actions you can do with it are limited. There is a mutable variant (&mut [T]), which allows you to mutate the items in the slice. You can't change how many are in the slice though. Said another way, you can't mutate the slice itself.
take a &[u8] and make it a Vec
For this specific case:
let s: &[u8]; // Set this somewhere
Vec::from(s);
However, this has to allocate memory not on the stack, then copy each value into that memory. It's more expensive than the other way, but might be the correct thing for a given situation.
or vice versa
let v = vec![1u8, 2, 3];
let s = v.as_slice();
This is basically "free" as v still owns the data, we are just handing out a reference to it. That's why many APIs try to take slices when it makes sense.

Deleting items in foreach

Should you be allowed to delete an item from the collection you are currently iterating in a foreach loop?
If so, what should be the correct behavior?
I can take quite a sophisticated Collection to support enumerators that track changes to the collection to keep position info correct. Even if it does some compromisation or assumptions need to be made. For that reason most libraries simply outlaw such a thing or mutter about unexpected behaviour in their docs.
Hence the safest approach is to loop. Collect references to things that need deleting and subsequently use the collected references to delete items from the original collection.
It really depends on the language. Some just hammer through an array and explode when you change that array. Some use arrays and don't explode. Some call iterators (which are wholly more robust) and carry on just fine.
Generally, modifying a collection in a foreach loop is a bad idea, because your intention is unknown to the program. Did you mean to loop through all items before the change, or do you want it to just go with the new configuration? What about the items that have already been looped through?
Instead, if you want to modify the collection, either make a predefined list of items to loop through, or use indexed looping.
Some collections such as hash tables and dictionaries have no notion of "position" and the order of iteration is generally not guaranteed. Therefore it would be quite difficult to allow deletion of items while iterating.
You have to understand the concept of the foreach first, and actually it depends on the programming language. But as a general answer you should avoid changing your collections inside foreach
Just use a standard for loop, iterate through the item collection backwards and you should have no problem deleting items as you go.
iterate in reverse direction and delete item one by one... That should proper solution.
No, you should not. The correct behaviour should be to signal that a potential concurrency problem has been encountered, however that is done in your language of choice (throw exception, return error code, raise() a signal).
If you modify a data structure while iterating over its elements, the iterator might no longer be valid, which means that you risk working on objects that are no longer part of the collection. If you want to filter elements based on some more complex notation, you could do something like this (in Java):
List<T> toFilter = ...;
List<T> shadow;
for ( T element : toFilter )
if ( keep(element) )
shadow.add(element);
/* If you'll work with toFilter in the same context as the filter */
toFilter = shadow;
/* Alternatively, if you want to modify toFilter in place, for instance if it's
* been given as a method parameter
*/
toFilter.clear();
toFilter.addAll(shadow);
The best way to remove an item from a collection you are iterating over it to use the iterator explitly. For example.
List<String> myList = ArrayList<String>();
Iterator<String> myIt = myList.iterator();
while (myIt.hasNext()) {
myIt.remove();
}

Resources