NOTE: my question is array, not [ Array or GenericArray ]
this is my code:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7}) // HERE: WORKS FINE
// ERROR HERE:
// Array concatenation not supported for public array variables and parameters
h["a"].data += 4
struct Int
data: array of int
construct (a: array of int)
this.data = a
how to fix this?
Not really an answer, but an alternative way to express this:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7})
h["a"].append ({4})
struct Int
data: array of int
construct (a: array of int)
this.data = a
def append (a: array of int)
this.data = this.data + a
Now there is no mixing of "variables and parameters" going on anymore, which solves the compiler error your original code is triggering.
The problem is that this also results in a compiler error:
resize_array.gs:14.21-14.33: error: Incompatible operand
this.data = this.data + a
Which can be simplified to this code:
init
x: array of int = {1, 2, 3}
y: array of int = {4, 5, 6}
z: array of int = x + y
Which also produces the same compiler error.
resize_array.gs:21.23-21.27: error: Incompatible operand
z: array of int = x + y
I have added a new question based on this:
How to concatenate two arrays?
As it turns out concating arrays (it works for string though!) is not a trivial task in Vala/Genie.
See the other question for solutions on how to do this.
I'd personally use Gee containers for this (if I don't have to frequently call some C functions that need a plain array).
The solution using Array of int:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7})
h["a"].append ({4})
struct Int
data: Array of int
construct (a: array of int)
data = new Array of int;
append (a)
def append (a: array of int)
data.append_vals (a, a.length)
A bug of Genie? maybe?
I try that in Vala, Works fine.
The output:
1, 2, 3, 4, 55, 666,
struct Int {
int[] data;
Int(int[] a){
this.data = a;
}
}
void main(){
var h = new HashTable<string, Int?> (str_hash, str_equal);
h["a"] = Int({1, 2, 3});
h["b"] = Int({4, 5, 6});
h["a"].data += 4;
h["a"].data += 55;
h["a"].data += 666;
for (var i = 0; i < h["a"].data.length; i++) {
stdout.printf("%d, ", h["a"].data[i]);
}
}
Related
I'm working with llvm (frontend: C++) and trying to implement the struct type array (struct type pointer) in my language. My struct looks like this:
struct myStruct {
double const *myArray; //double type array
char const *myString; //string
};
And my code for struct type array implementation:
...
auto myString = Type::getInt8PtrTy(TheContext);
auto myArray = Type::getDoublePtrTy(TheContext);
auto myStruct = StructType::create(TheContext, "Struct");
myStruct->setBody({myString, myArray});
return PointerType::get(myStruct, 0);
I think that this way isn't correct because when I'm assigning data to the pointer and trying to print the array elements I got only first struct array element and only "myString" ("myArray" is always empty). I want to know what I'm doing wrong.
Additional code:
struct myStruct* getData(){
double const arr1[3] = { 10, 7, 9 }; double const* arraypnt1 = arr1; char const *str1 = "string1";
double const arr2[3] = { 1, 2, 4}; double const* arraypnt2 = arr2; char const *str2 = "string2";
struct myStruct p[2] = {{ arraypnt1, str1 }, { arraypnt2, str2 }};
struct myStruct* pairarr = p; // array of pairs
return pairarr;
}
//code generator
Value *ASTVarExpression::generateCode() {
Function *function = Builder.GetInsertBlock()->getParent();
Value *initValue = VariableValue->generateCode(); //this line creates call to function 'getData()'
if (!initValue) { return nullptr; }
AllocaInst *alloca = CreateFunctionEntryAlloca(function, VariableName, GetType(DeclaredType));
Builder.CreateStore(initValue, alloca); //store 'getData()' result in variable which type is 'myStructure* '
NamedValues[VariableName] = alloca;
return initValue;
}
static AllocaInst *CreateFunctionEntryAlloca(Function *function, StringRef variableName, Type* variableType) {
IRBuilder<> tempBlock(&function->getEntryBlock(), function->getEntryBlock().begin());
return tempBlock.CreateAlloca(variableType, 0, variableName);
}
Type *GetType(int expressionType){ //returns struct array type
auto myString = Type::getInt8PtrTy(TheContext);
auto myArray = Type::getDoublePtrTy(TheContext);
auto myStruct = StructType::create(TheContext, "Struct");
myStruct->setBody({myString, myArray});
return PointerType::get(myStruct, 0);
}
llvm IR code:
%varName = alloca %Struct.0*, align 8
%gencall = call %Struct* #getData()
store %Struct* %gencall, %Struct.0** %varName, align 8
ret %Struct* %gencall
In the "Writing R Extensions" manual it says
Protecting an R object automatically protects all the R objects pointed to in the
corresponding SEXPREC, for example all elements of a protected list are automatically
protected.
Does this mean that I do not need to protect individual SEXP elements of a VECSXP. For example consider the following which contains two methods that I hope illustrate where I need clarification:
#include <Rinternals.h>
#include <R.h>
SEXP copy_int_vec(int *x, int size) {
SEXP ans = allocVector(INTSXP, size);
PROTECT(ans);
int *pans = INTEGER(ans);
for (int i = 0; i < size; i ++) {
pans[i] = x[i];
}
UNPROTECT(1);
return ans;
}
// method 1 - protect VECSXP when allocated BUT NOT individual array entries
SEXP method_one() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
// method
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
for (int i = 0; i < N; i++){
SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
}
UNPROTECT(1);
return ans;
}
// method 2 - protect VECSXP when allocated AND ALSO individual array entries
SEXP method_two() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
// method 2
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
for (int i = 0; i < N; i++){
SEXP tmp = copy_int_vec(graph[i], neighbours[i]);
PROTECT(tmp);
SET_VECTOR_ELT(ans, i, tmp);
}
UNPROTECT(N + 1);
return ans;
}
I'm hoping the answer is the first method but would appreciate clarification.
I believe method_one is fine.
To do the analysis, you need to know every point in your code that does allocations, because an allocation might trigger garbage collection, and that will release any unprotected object.
So stepping through method_one:
SEXP method_one() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
None of the code above uses R's allocator; those allocations are all on the C stack, so they are safe.
// method
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
This does an R allocation, and then immediately protects it. A more common way to write this is
SEXP ans;
PROTECT(ans = allocVector(VECSXP, N));
which makes it harder to mess things up by inserting a statement in between the allocation and protection.
for (int i = 0; i < N; i++){
SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
}
The copy_int_vec does allocations, so garbage collection could occur in any step of this loop. However, the allocated object is immediately assigned into ans, so each one is protected and safe.
UNPROTECT(1);
Nothing is protected now; remember not to insert any code before the return.
return ans;
}
I tried many ways to build a map of struct and append values to it and I did not find any way to do it.
The keys of the map are strings. The struct is made of two parts: "x" integer and "y" a slice of strings.
The errors I face to build the map are (for m) :
main.go:11: syntax error: unexpected comma, expecting semicolon, newline, or }
When I try to add new keys and values to the map, the errors are:
go:33: syntax error: missing operand
package main
import "fmt"
type TEST struct {
x int
y []string
}
// none of these var gives the expected result
var m = map[string]*struct{x int, y []string}{"foo": {2, {"a", "b"}}, }
var m2 = map[string]struct{x int, y []string}{"foo": {2, {"a", "b"}}, }
var n = map[string]*struct{x int
y []string
}{"foo": {2, {"a", "b"}}, }
var o = map[string]*struct{
x int
y []string
}{"foo": {2, {"a", "b"}}, }
func main() {
m["foo"].x = 4
fmt.Println(m["foo"].x)
// how can I had a new key ?
m["toto"].x = 0
m["toto"] = {0, {"c", "d"}}
// and append the string "e" to {"c", "d"} ?
m["toto"].y = append(m["toto"].y, "e")
a := new(TEST)
a.x = 0
a.y = {"c", "d"}
m["toto"] = a
fmt.Println(m)
}
Here's a way to write it:
package main
import "fmt"
type TEST struct {
x int
y []string
}
var m = map[string]*TEST { "a": {2, []string{"a", "b"}} }
func main() {
a := new(TEST)
a.x = 0
a.y = []string{"c", "d"}
m["toto"] = a
fmt.Println(m)
}
Note: two types aren't the same just because their struct have identical fields.
Long story. If you for some reason prefer unnamed types you must be quite verbose in composite literal describing both types and values
var m = map[string]*struct {
x int
y []string
}{"foo": {2, []string{"a", "b"}}}
or with semicolons
var m = map[string]*struct {x int; y []string}{"foo": {2, []string{"a", "b"}}}
and without indirection
var m1 = map[string]struct {
x int
y []string
}{2, []string{"a", "b"}}}
To add new key
m["todo"] = &struct {
x int
y []string
}{0, []string{"c", "d"}}
You can also assign TEST struct but only without indirection because pointers *TEST and *youunnamedstruct are not assignable nevertheless structs having identical fields assignable themself
m1["todo"] = TEST{0, []string{"c", "d"}}
You can append only to indirect map struct field
m["todo"].y = append(m["todo"].y, "e")
because direct map struct fields are not addressable
How would I write the function below in Rust? Is there a way to write replace() safely or is the operation inherently unsafe? list does not have to be an array, a vector would work as well. It's the replacement operation that I'm interested in.
void replace(int *list[], int a, int b) {
*list[a] = *list[b];
}
I would like the following behavior:
int a = 1;
int b = 2;
int *list[] = { &a, &a, &b, &b };
*list[0] = 3; // list has pointers to values: [3, 3, 2, 2]
replace(list, 2, 0); // list has pointers to values: [3, 3, 3, 3]
*list[0] = 4; // list has pointers to values: [4, 4, 4, 4]
Answer for modified question
Rust does not allow you to have multiple mutable references (aliasing) to the same item. This means you'd never be able to run the equivalent of your third line:
fn main() {
let mut a = 1;
let vals = &[&mut a, &mut a];
}
This fails with:
cannot borrow `a` as mutable more than once at a time
What about using Rc and RefCell?
Rc doesn't let us mutate the value:
A reference-counted pointer type over an immutable value.
(Emphasis mine)
RefCell::borrow_mut won't allow multiple concurrent borrows:
Panics if the value is currently borrowed.
Answer for original question
It's basically the same. I picked a u8 cause it's easier to type. :-)
fn replace(v: &mut [&mut u8], a: usize, b: usize) {
*v[a] = *v[b]
}
fn main() {
let mut vals = vec![1,2,3,4];
{
let mut val_refs: Vec<&mut u8> = vals.iter_mut().collect();
replace(&mut val_refs, 0, 3);
}
println!("{:?}", vals);
}
(playpen link)
Rust does do boundary-checking, so if you call with an index bigger than the slice, the program will panic and you don't get memory corruption.
What is the most efficient way to insert one Vector into another at specific position?
For example:
var aa:Vector.<int> = Vector.<int>([1, 2, 3]);
var bb:Vector.<int> = Vector.<int>([9, 8, 7]);
This doesn't seems to work:
bb.splice(1, 0, aa);
The result is [9, 0, 8, 7].
For the moment there is no builtin function other than doing a loop over the Vector, here two methods (i have not timed them).
If bb can be a new Vector you can do for example:
var insertIndex:int = 1;
bb=bb.slice(0, insertIndex).concat(aa).concat(bb.slice(insertIndex));
If bb cannot be change you can do a splice but with preparing the elements to insert into a new Array:
var insertIndex:int = 1;
var parms:Array=[insertIndex, 0]; // prepare the arguments for the splice call
var j:int = 2; // length of the parms array
var len:int = aa.length;
for (var i:int = 0; i < len; i++, j++){
parms[j] = aa[i];
}
// call the splice with the new arguments
bb.splice.apply(bb, parms);
If you need to concat one after the other, as PatrickS mentionned bb.concat will do the job.
If you need to insert values in the middle you'll need something like
for each (var i : int in aa.reverse())
{
bb.splice(1,0,i);
}
or, more elegantly, this, if you cannot change aa
var insertingIndex : int = 2;
for each ( var i : int in aa )
{
bb.splice( insertingIndex, 0, i );
insertingIndex++;
}