Nim for loop index cannot evaluate at compile time - nim-lang

Why does the following code throw Error: cannot evaluate at compile time: i when trying to compile:
import std/strutils
const s = "a"
for i in 1..10:
const ss = s.repeat(i)
echo ss
I tried without the loop
import std/strutils
const s = "a"
const ss = s.repeat(10)
echo ss
and it works as expected.

The issue is that for loops store their iteration variable as a var or let depending on the iterator. So even if the range you give is static the iterator variable won't be. You can get around this by putting the entire loop in a static: block or a {.compileTime.} proc, or of course if you just want an immutable ss then you can use let instead of const.

Related

Overwriting a variable in another file using nodejs

I have a business scenario which is equivalent to below tricky situation. Hence putting this problem across in a simple way as below.
File1.ts
import * from 'something';
export const var1="value of var1";
//lets say we have a variable 'x' and this needs to be exported too. However value of x is still unknown.
export const x;
File2.ts
import * from 'something';
//set the value of 'x' in File1.ts as 5
File3.ts
import * from 'something'
//I should be able to get the value of 'x' from File1.ts. But it should be equal to the value set by File2.ts which is 5
As mentioned above, I should be able to set the value of x from somewhere (in this case, File2.ts) and everytime I use 'x' from File1.ts, be it in File3.ts or any other file, the value of 'x' should be 5 (set from File2.ts)
File1.ts
var x = 99 //some unknow value
function setValueOfX(value){
x = value
}
function getValueOfX(){
return x
}
module.exports = {
setValueOfX,
getValueOfX,
}
File2.ts
const File1 = require('./File1.ts')
File1.setValueOfX(5) /// you can set the value of x using the function
File3.ts
const File1 = require('./File1.ts')
console.log(File1.getValueOfX()) /// you can get value of x by using .getValueOfX function

Why does this loop repeatedly log the last pair in the array instead of all the pairs?

I am using Node v16.15.1 and TypeScript v4.7.4
I want to split an object into multiple objects, and then insert each object as a value in another object.
i.e.
{key1:"value1", key2:"value2"}
-> {key1:"value1"} and {key2:"value2"}
-> {key3:"value3", key4:"value4", key5:{key1:"value1"}} and {key3:"value3", key4:"value4", key5:{key2:"value2"}}
Below is the code I am using:
let a:any = {}
let entries = Object.entries({key1:"value1", key2:"value2"});
for(const el of entries) {
let b = a;
b.key = Object.fromEntries(new Map([el]));
console.log(b.key);
console.log(b)
}
However, the output I get is this.
{key2:"value2"} is in both objects, instead of just the second one.
If I use the following code, however, I get the correct result:
let entries = Object.entries({key1:"value1", key2:"value2"});
for(const el of entries) {
let b:any = {};
b.key = Object.fromEntries(new Map([el]));
console.log(b.key);
console.log(b)
}
The problem with this is that I am not inserting into a blank object, and am passing it as a parameter in a function.
Why does this happen?
How would I be able to fix this?
TIA
In javascript, when you do let a:any = {}; and then let b = a; you are assigning to b the references of a (not the value). So if you update b, you are actually updating a because both variable are the same.
If you want b to be a copy of a you should do something like : let b = {...a}.

Rust: How to concatenate bytes together

I have already read the following link but still get some errors with my current attempt:
let data = &[37u8, 42u8];
let data_two = &[0x34u8, 0x32u8];
let res:Vec<u8> = [data, data_two].concat();
Also, ideally I would like to avoid concatenation, and write an array of u8 to a buffer, where I reserve the first two bytes for storing length and index like:
let nb:u8 = get_chunks_nb();
let index:u8 = get_chunk_index();
let header = &[nb, index];
// this kind of things in C:
memcpy(&buffer, header, 2);
memcpy(&buffer[2], chunk, chunk_len);
Thank you for your help!
I took a shot at it, but I'm not 100% sure as to why, I'm still new to Rust.
It looks like the compiler is seeing data and data_two as arrays, and so [data, data_two] is then an array of array and not an array of slice. Which is probably why it couldn't find the concat method on it.
By explicitely saying that data is a slice, everything seems to fall into place:
let data:&[u8] = &[37u8, 42u8];
let data_two = &[0x34u8, 0x32u8];
let mut res:Vec<u8> = [data, data_two].concat();

How can I dynamically create a variable dynamically in the current scope in node.js?

I'm trying to dynamically create node.js variables that point to objects.
I know I can create a variable dynamically in scope using eval:
var vars = ['a','b']
for(var n=0; n<vars.length; n++) {
eval('var '+vars[n]+' = '+n)
}
console.log(b) // prints 1
The above dynamically creates variables and gives them a value of whatever their index is inside the vars list.
But what if I want to set these dynamic variables to an object reference? Something like the following:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k) // create the variable dynamically
new Function('value', k+' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b) // undefined : (
I know why the above doesn't work - the function created by new Function can't see the current scope, and so can't set the value. Is there a way to do what I'm trying to do, such that console.log(vars.a.b) would print "5" rather than "undefined"?
UPDATE:
Hmm, I was wrong that new Function can't see or modify variables in the local scope, since this works:
var obj = {}
eval('var x')
new Function('value', 'x = value')(obj)
obj.a = 5
console.log(x.a) // prints 5
So now I'm pretty confused why my loop above doesn't seem to work..
UPDATE 2:
I just realized that my code actually does work in chrome's console. But its not working in node.js...
UPDATE JUST FOR PHIL:
Here's my situation. I'm using Parsimmon to build a parser combinator. This is how that's done:
var L = Parsimmon.createLanguage({
combinator1: function() {
return Parsimmon.string('hi')
},
combinator2: function() {
return L.combinator1.many()
}
})
I'd like to eliminate the need to write L. before every parser combinator I write. I could do this:
var combinator2 = L.combinator2
But that would require me to add an additional line like that for every combinator I write. As you can see, I can't use with since L is created after I'd be able to write with(L) and if I define my functions below then use them in the object, I'm back to duplicating those function names every time i write a new combinator.
So to summarize, I'd like to loop through L and put all the generated parser combinators into a nice clean variable in scope so I can write combinator1 instead of L.combinator1 (etc).
IIUC, whether or not there are better ways to achieve your goal, if you just remove 'var ' on the dynamic Function, it will operate on the outer (global) scope.
Change:
new Function('value', k+' = value')(vars[k])
to:
new Function('value', k+' = value')(vars[k])
So:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k) // create the variable dynamically
new Function('value', k+' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b)
You don't want to declare a new variable with local scope inside the function, you want to operate on the outer scope.
Update to address new question
Your first loop does work. Try introspecting on a or b; they are as should be expected, 0 and 1, respectively.
Update 2 based on info this is for Node.js
Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function , Function always works on the global scope. In Node, this is on global and var variables are not the global scope but are the module's scope. To fix this for Node, you can do the following and omit your eval var declaration (which was overriding for the module the global scope which you have access to inside Function):
var vars = {a: {}, b:{}}
for(var k in vars) {
new Function('value', k +' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b) // 5
In other words, the inner function sets variables which automatically become accessible via global, so your module code, in the absence of any module-scoped var declarations of a overwriting the global, you can set the global a properties as with the line a.b = 5.
Update 3
Since I had just been addressing your issue in understanding Function, I gave the above information. As per your follow-up comment (and again, without speaking to its suitability for your specific use case), you can operate on the object via eval as follows:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k+' = vars["'+k+'"]')
}
a.b = 5
console.log(vars.a.b) // 5
But to reiterate the warnings made by others--using eval is generally not a good idea and can be dangerous when the variables referenced include arbitrary user data...
change this line :
from :
a.b = 5
to
vars.a.b = 5
because a is undefined in your case that's why it is now allowing to create a new property
vars.a will return you a object not only a as a is vars property.

Swift 3 references

When creating an instance of an object, I'm having trouble setting its properties if I assign the property to another variable.
Eg. For an object containing nested objects, I want to assign one of the children to a temporary var to make it easier to work with.
Instead of doing this (which works):
myObj.myChildObject[0].someOtherChild[0].property = "something"
I'm trying to do:
var t = myObj.myChildObject[0].someOtherChild[0]
t.property = "something"
// this doesn't throw an error but doesn't change the value of myObj
What gives?
Edit>
Here's a contrived example to illustrate:
class Car { var name: String = "" }
var merc = Car()
var obj = merc.name
merc.name = "C63 AMG"
obj = "E300"
print("merc.name: \(merc.name)") // prints merc.name: C63 AMG
print("obj.name: \(obj)") // prints obj.name: E300
var ob2 = merc
ob2.name = "Toyota"
print("ob2.name: \(ob2.name)") // prints ob2.name: Toyota
print("merc.name: \(merc.name)") // prints merc.name: Toyota
So assigning the class instance to a var creates a reference. But assigning a property of that object to another var creates a copy?
I read through https://developer.apple.com/swift/blog/?id=10 and still don't get it :(
In the above, 'obj' is not a struct, enum or tuple, so shouldn't it be a reference type?
If myObj.myChildObject[0].someOtherChild[0] is a value type (I.e. a strict, direct enum or tuple), it's being copied upon assignment to t. Subsequent mutations on t only mutate that copy, and the original instance are unchanged.
You would have to reassign t back in:
var t = myObj.myChildObject[0].someOtherChild[0]
t.property = "something"
myObj.myChildObject[0].someOtherChild[0] = t
This is discussed in the Swift language guide.

Resources