This question already exists:
JavaScript - use eval to get value in code string
Closed 1 year ago.
I am trying to evaluate JavaScript code based on what a user enters into a code editor. I get their code as a single string, use babel to transform it and then split on newlines to get the code by line. I want to see if the current line evaluates to something and if so, print that out. I skip lines that do not evaluate to anything but the problem is if some writes code like the following:
1 | const x = 5;
2 | x
Ideally I would like to print something like:
1 |
2 | 5
The problem though is that I need line 1 to evaluate line two. If I just join the lines of code and evaluate that (something like: const x = 5;\nx;) it will result in 5;
However, if a line further down does not evaluate to anything, then it will also return 5 but that is not correct because const y = 3; does not evaluate to 5. So for example the following:
1 | const x = 5;
2 | x
3 | const y = 3;
concatenated (something like: const x = 5;\nx\nconst y = 3;): would result in:
1 | undefined
2 | 5
3 | 5 // PROBLEM: this should also be undefined.
I have tried this solution: Context-preserving eval but it does not answer my question. Moreover, The solution throws an error in the following line when I tried it out:
// 'void (__EVAL = ${__EVAL.toString()});' causes an error
var __EVAL = s => eval(`void (__EVAL = ${__EVAL.toString()}); ${s}`);
I want to evaluate the latest statement in a block of code, given I have the code written before that, but only return a result if the current line evaluates to something. So as one final example, the following code:
1 | const x = 5;
2 | x
3 | const y = 3;
4 |
5 | const add = (a, b) => {
6 | return a + b;
7 | };
8 |
9 | add(x, y);
should give:
1 |
2 | 5
3 |
4 |
5 |
6 |
7 |
8 |
9 | 8
Related
I was developing a minesweeper game in typescript. But while defining a type named Cell, I encountered an error.
Code:
Not Working
const bomb = "๐ฃ";
const flag = "๐ฉ";
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | bomb | flag;
export type Board = Array<Array<Cell>>;
While defining type Cell the error raises:
'bomb' refers to a value, but is being used as a type here. Did you mean 'typeof bomb'?ts(2749)
while doing it in another way without any variable or constant works:
Fine
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | "๐ฃ" | "๐ฉ";
What am I doing wrong? What is the reason?
bomb and flag and not types.
The typeof operator will give you access to the type of a value.
const bomb = "๐ฃ";
const flag = "๐ฉ";
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | typeof bomb | typeof flag;
I could create a bitwise trie that just looks like this:
x
_____________|___________
| |
___โ___ ___โก___
| | | |
_โ _โ _โ โก_
| | | |
_โ __โ __ ____โ___ โ____
| | | | | |
โ โ โก_ โ _โ_ ___โก
| | | |
โ โ โ __โ
|
โ
However, I would like to try something different. Instead of doing binary tries (bitwise tries) -- which are based on taking 1 bit at a time and choosing the next 1 of 2 slots to visit -- I would like to use 2 bits at a time, or 3 bits at a time, etc. Using 2 bits at a time would create a trie that has 4 branches. Using 3 bits, it would have 8 branches. This would be nice to use to compact the trie a little bit.
So I'm wondering how to do that. How to take an integer and essentially slice off 2 or 3 or n bits at a time. So given an integer like this:
10010110
That is 150 in binary.
I would like to get let's say 2 bytes at a time, so:
10
01
01
10
That would mean I put it in slot 2, then 1, then 1, then 2. Or if I chose 4 bits, then:
1001
0110
That would put it in slot 9 then slot 6.
So the question is, how to implement a function sort of like this:
function sliceInteger(integer, start, length) {
return integer[start..length]
}
var x = sliceInteger(150, 4, 4) // => 6
You could just use bitwise arithmetic:
function sliceInteger(integer, start, length) {
return (integer >> start) & ((1 << length) - 1);
}
console.log(sliceInteger(150, 4, 4));
Edit
I notice that in your question you are slicing right to left i.e. MSB to LSB, whereas the function I've written above slices left to right i.e. LSB to MSB, hence it returns 9 where your suggested result is 6. If that is the way you want to slice, you should use this function instead. Note that if you want to slice longer than 8-bit integers, you will need to change the 8 in the code appropriately.
function sliceInteger(integer, start, length) {
return (integer >> (8 - start - length)) & ((1 << length) - 1);
}
console.log(sliceInteger(150, 4, 4));
you can convert number to binary string and splice it then convert that to decimal number
function sliceInteger(integer, start, length) {
var binary = integer.toString(2)
binary = binary.slice(start, start+length)
return parseInt(binary, 2)
}
console.log(sliceInteger(150, 4, 4))
I was practicing my javascript with CodeFights and after I finished an exercise I saw this function as a result:
// Subject :
// Several people are standing in a row and need to be divided into two teams.
// The first person goes into team 1, the second goes into team 2,
// the third goes into team 1 again, the fourth into team 2, and so on.
// You are given an array of positive integers - the weights of the people.
// Return an array of two integers, where the first element is the total weight of
// team 1, and the second element is the total weight of team 2
// after the division is complete.
// Example :
// For a = [50, 60, 60, 45, 70], the output should be
// alternatingSums(a) = [180, 105].
// answer
alternatingSums = a => a.reduce((p,v,i) => (p[i&1]+=v,p), [0,0])
I don't understand what p[i&1]+=v,p means.
The & symbol is a bitwise binary operator.
To understand what would happen, you have to convert each item to binary.
| i (decimal) | i (binary) | i & 1 |
|-------------|------------|-------|
| 0 | 0 | 0 |
| 1 | 1 | 1 |
| 2 | 10 | 0 |
| 3 | 11 | 1 |
| 4 | 100 | 0 |
| 5 | 101 | 1 |
Effectively, every even number will be transformed to 0, and every odd number will be transformed to 1.
If I was trying to achieve that outcome, I personally would have used the modulus operator (%)
p[i%2] += v;
But that's just me.
The other part is that there are two statements separated by a comma:
(p[i&1]+=v,p)
That's saying "Perform this action, then return p. It's shorthand for:
alternatingSums = a => a.reduce((p,v,i) => {
p[i&1]+=v;
return p;
},
[0,0])
It looks for an element of the p array that has index of i&1 - it is a bitwise AND operation. Then, increments its value by a value of v variable. Finally, returns the value of p variable.
I was looking at some javascript code to create a calculator app. It's straightforward, but what confused me was when there's function that returns a function.
With the code below, I understand each button of the calculator needs an event listener to utilize "click", upon which the function is called depending on what button was clicked. The addValue(i) function adds the button value to the result field when the button is clicked. The function below has a function that returns a function. Without the function call, the result returns "789+456-123/0.=x"
Can some explain why the addValue(i) function needs to return a function for this function to work.
for (var i=0; i<buttons.length; i++) {
if(buttons[i] === "="){
buttons[i].addEventListener("click", calculate(i));
} else {
buttons[i].addEventListener("click", addValue(i));
}
}
function addValue(i) {
return function() {
if(buttons[i].innerHTML === "รท") {
result.innerHTML += "/";
} else if (buttons[i] === "x") {
result.innerHTML += "*";
} else {
result.innerHTML += buttons[i].innerHTML;
}
}
};
In this example, I'm assuming that the webpage is a calculator, similar to:
|---------------|
| |
|---------------|
| 1 | 2 | 3 | * |
|---|---|---|---|
| 4 | 5 | 6 | / |
|---|---|---|---|
| 7 | 8 | 9 | = |
|---------------|
In this case, the button buttons[i] is one of the calculator buttons; | 1 |, | 5 |, etc. The actual number of the button is its index, so buttons[2] would be | 2 |, buttons[7] would be | 7 |, etc. And I'm guessing other values, like buttons[0] and buttons[10], are the operator buttons (| = |, | * |, | / |).
Now, when the user clicks on one of these buttons, the character on the button, which is the button's innerHtml, is added to the calculator's result (by adding it to the result's innerHTML), which is just a display of the operation. So if I clicked | 3 |, then | * |, then | 5 |, the calculator would look like
|---------------|
| 3*5 |
|---------------|
| 1 | 2 | 3 | * |
|---|---|---|---|
| 4 | 5 | 6 | / |
|---|---|---|---|
| 7 | 8 | 9 | = |
|---------------|
Here's where the addEventListener comes into play. When you call element.addEventListener("click", func), whenever element is clicked, func will be called. So to add the button to the result when it's clicked, you could do:
buttons[i].addEventListener("click", addButtonValueToResult);
where addButtonValueToResult is the function to add the button's value to the result.
The problem is, the different buttons have different values, so one function like this won't work for all of them. Therefore, addButtonValueToResult can't be a simple function; each button needs its own function. One such solution is to ditch the for loop and just do something like:
buttons[1].addEventListener("click", add1ToResult);
buttons[2].addEventListener("click", add2ToResult);
buttons[1].addEventListener("click", add3ToResult);
...
and then have functions like:
function add1ToResult() {
result.innerHTML += "1"
}
But this takes a lot of unneeded work, because you need to add functions for each of the number buttons (| 1 | through | 9 |) as well as the operator buttons (| = |, | / |, and | * |), which just add their innerHtmls to the result. Moreover, the button's index is already assigned to a variable i and the entire button can be referenced with that index with buttons[i]. Couldn't you just have the program make a function automatically, for each button, that when given the button's index i, gets the button (through buttons[i]) and adds that button's value to the result?
Well that's exactly what this program does: addValue(i) doesn't just add the button's inner value itself; it returns another function that, also with a few test cases for special buttons, adds the button's inner value. Looking at this code:
function addValue(i) {
return function() {
if(buttons[i].innerHTML === "รท") {
result.innerHTML += "/";
} else if (buttons[i] === "x") {
result.innerHTML += "*";
} else {
result.innerHTML += buttons[i].innerHTML;
}
}
};
Say you call addValue(3); this will return a function that will add the digit 3 to the result, in result. If you call addValue(9); this will return a function that will add the digit 9 to the result, in result. You can call the function addValue returns and actually add a digit to the result, through (addValue(digit)()). But addEventListener doesn't take an evaluated result; it takes a function, which it will later call when the button is clicked.
I have the following regex patterns that matches all the 'act' that ends with numbers within a list of URLs.
Regex pattern /\/ch(\d+)\/act(\d+)/gi
Javascript code
pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/gi;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(hasAct);
}
The expected results and actual results
| String | Expected Result | Actual Result |
| pageSrc[1] | false | false |
| pageSrc[2] | true | true |
| pageSrc[3] | true | *FALSE |
| pageSrc[4] | true | true |
| pageSrc[5] | true | *FALSE |
| pageSrc[6] | false | false |
Am not sure why pageSrc[3] won't return true. I used the regEx tester on gskinner.com and it worked fine, here is the link http://gskinner.com/RegExr/?344ap
Can anyone help me take a look please? thanks in advance!
Remove the g flag. From the RegExp.test documentation:
As with exec (or in combination with it), test called multiple times on the same global regular expression instance will advance past the previous match.
You don't want a global search when reusing a pattern like this.
> var pageSrc = [];
> pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/i;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(i, hasAct);
}
0 false
1 false
2 true
3 true
4 true
5 true
6 false
You are using /g. Remove that flag to make it work.
The g flag makes the regex start matching from pattern.lastIndex (the index where the previous match ended), until it fails, and then start at 0.