Why does object destructuring throw an error if there is no var keyword in front of it?
{a, b} = {a: 1, b: 2};
throws SyntaxError: expected expression, got '='
The following three examples work without problems
var {a, b} = {a: 1, b: 2};
var [c, d] = [1, 2];
[e, f] = [1, 2];
Bonus question: Why do we not need a var for array destructuring?
I ran into the problem doing something like
function () {
var {a, b} = objectReturningFunction();
// Now a and b are local variables in the function, right?
// So why can't I assign values to them?
{a, b} = objectReturningFunction();
}
The issue stems from the {...} operators having multiple meanings in JavaScript.
When { appears at the start of a Statement, it'll always represent a block, which can't be assigned to. If it appears later in the Statement as an Expression, then it'll represent an Object.
The var helps make this distinction, since it can't be followed by a Statement, as will grouping parenthesis:
( {a, b} = objectReturningFunction() );
From their docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#assignment_separate_from_declaration_2
Notes: The parentheses ( ... ) around the assignment statement are required when using object literal destructuring assignment without a declaration.
{a, b} = {a: 1, b: 2} is not valid stand-alone syntax, as the {a, b} on the left-hand side is considered a block and not an object literal.
However, ({a, b} = {a: 1, b: 2}) is valid, as is var {a, b} = {a: 1, b: 2}
Your ( ... ) expression needs to be preceded by a semicolon or it may be used to execute a function on the previous line.
If you write Javascript without semicolons, then the 'assignment without declaration' syntax should be preceded with a semicolon for it to work predictably
let a, b
;({a, b} = objectReturningFunction()) // <-- note the preceding ;
Just wanted to highlight this as it caught me out, and hopefully can save others some time figuring out why it doesn't work and/or produces weird results with code formatters like prettier.
Indeed, it's actually right there in the accepted answer (last line of the quoted docs) but easy to miss, especially without seeing an example!
Here's another way:
let {} = {a, b} = objectReturningFunction()
Pros:
No parenthesis needed
No semicolons needed
The extra assignment is a guaranteed no-op (given that no weird things are going on - also, your transpiler might not realize this)
Cons:
Looks a bit weird, although in my opinion no weirder than the !(){...}() IIFE.
Might be confusing as to why it's there. It is guaranteed to throw people off on the first encounter, so I would advise against using it as a one-off.
Consider:
colors = { r: 204, g: 51, b: 102, hex: "#cc3366" };
Here's a gist of some of the ways of destructuring:
Destructuring to new variables
let { r, g, b } = colors;
// initializes variables r, g, b
Destructuring to new variables with different names
let { r: red, g: green, b: blue } = colors;
// initializes variables red, green, blue
Destructuring to existing variables
let r, g, b;
...
({ r, g, b } = colors);
Destructuring to existing variables with different names
let red, green, blue;
...
({ r: red, g: green, b: blue } = colors);
Destructuring into another object with same property names
let myColor = { r: 0, g: 0, b: 0 };
...
({ r: myColor.r, g: myColor.g, b: myColor.b } = colors);
Destructuring into another object with different property names
let myColor = { red: 0, green: 0, blue: 0 };
...
({ r: myColor.red, g: myColor.green, b: myColor.blue } = colors);
Related
Say I have a hash map m: HashMap<K, V>, a key k: K and a value v: V, and would like to do the following:
If m does not contain a value at index k, insert v at index k.
If m contains a value w at index k, apply a function fn combine(x: V, y: V) -> Option<V> to v and w, and:
If the result is None, remove the entry at index k from m.
If the result is Some(u), replace the value at index k by u.
Is there a way to do this "in-place", without calling functions that access, modify or remove the value at k multiple times?
I would also like to avoid copying data, so ideally one shouldn't need to clone v to feed the clones into insert and combine separately.
I could rewrite combine to use (mutable) references (or inline it), but the wish of not copying data still remains.
Digging deeper into the Entry documentation, I noticed that the variants of the Entry enum offer functions to modify, remove or insert entries in-place.
After taking std::collections::hash_map::Entry into scope, one could do the following:
match m.entry(k) {
Entry::Occupied(mut oe) => {
let w = oe.get_mut();
match combine(v, w) {
Some(u) => { *w = u; },
None => { oe.remove_entry(); },
}
},
Entry::Vacant(ve) => { ve.insert(v); },
}
(Here is a PoC in the Rust playground.)
This, however, requires combine to take a (mutable) reference as its second argument (which is fine in my case).
I managed to do it in one access, one write and one key-deletion in total in the worst case. The last key-deletion should not be necessary, but I'm not certain it can be done. I gave it my best so far. I hope this helps!
Okay, so I think we want to use the Entry API.
The full method list for Entry is here.
I think we'd do it in the following order:
If m contains a value w at index k: (two more steps)
Or insert v at index k.
This can be done by using .and_modify and then .or_insert. Something like this:
let map = // ... Initialize the map
// Do stuff to it
// ...
// Our important bit:
let mut delete_entry = false;
map.entry(k)
.and_modify(|w| { // If the entry exists, we modify it
let u = combine(v, w);
match u {
Some(y) => *w = y;
None => delete_entry = true;
}
}
)
.or_insert(v); // If it doesn't, we insert v
if delete_entry {
map.remove(k);
}
I don't think there's a way to do all three things without that last map.remove access, so this is my best attempt for now.
I was at a meetup recently and one of the talks was about how you can use Webpack to require just the pieces of a package that you need. I believe that it is called tree shaking. I was wondering if there is a way to do this without Webpack? For instance can you specify exactly the pieces of code you need rather than the whole node module.
Any information about this would be great. I am just looking to learn something new.
Cheers,
There's a couple pretty simple ways:
In ES6, you can do what is called destructuring.
Here's an example with arrays:
var a, b, rest;
[a, b] = [10, 20];
console.log(a);
// expected output: 10
console.log(b);
// expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// expected output: [30,40,50]
This is destructuring by index, where a = array[0], b=array of index 1 (hyperlink barred bracket format), etc... Notice the ... operator, called the spread operator in ES6. Here is a link to that if you are curious about what it does, or how to use it.
You can also do the same with objects, consider:
const someRandomObject = {
a: 1,
b: 2,
};
const {a} = someRandomObject;
console.log(a) // expected output: 1
You are destructing, by name, only the properties you need from the object, so you are not pulling in a bunch of unused stuff. If you are not using ES6, you can do something similar with:
const someRandomObject = {
a: 1,
b: 2,
};
const a = someRandomObject.b;
console.log(a) // expected output: 2
Same thing as above, you are pulling out of someRandomObject the property you want, and nothing else. Note that the above way is pulling the value on the right side, so the name of the variable does not matter. These two ways are functionally equivalent (I believe).
I'm looking for some pointers for writing a function (let's call it replaceGlobal) that takes an input string and a mapping of substrings to replacement values, and applies these mappings such that as many characters as possible from the input string are replaced. For example:
replaceGlobal("abcde", {
'a' -> 'w',
'abc' -> 'x',
'ab' -> 'y',
'cde' -> 'z'
})
would return "yz" by applying 'ab' -> 'y' and 'cde' -> 'z'.
The function will only apply one round of substitutions, so it can't replace a value and then use part of the replacement value as part of another substitution.
A greedy approach produces non-optimal results (shown here in Javascript):
"abcde".replace(/(abc|cde|ab|a)/g, function(x) {
return {
'a': 'w',
'abc': 'x',
'ab': 'y',
'cde': 'z'
}[x];
});
returns 'xde'
Any thoughts on a good starting point here?
I think the problem boils down to finding the lowest cost path in a weighted DAG constructed with the input string as a spine and other edges provided by the substitutions:
/------x------------\
/-----y------\ \
/---w--\ \ \ /-------z------\
0 -----> a ----> b -----> c -----> d ----> e ----> $
where edges along the spine have a cost of 1 but the other edges have cost zero.
But that may be overcomplicating things.
Seems to me that dynamic programming is the way to go. This is due to the restriction:
The function will only apply one round of substitutions, so it can't
replace a value and then use part of the replacement value as part of
another substitution.
Specifically, say you have some random string abcdefg as input. Now you apply some rule to substitute some middle part, say de -> x. Now you have abcxfg, where the only (smaller subproblems) strings you are now allowed to manipulate are abc and fg. And for repetitive substrings, you can then leverage memoization.
Based on #Matt Timmermans comments and the original DAG idea, here's what I came up with in Javascript as a first attempt (I'm more interested in the algorithm itself than any specific language implementation):
const replaceGlobal = (str, dict) => {
let open = []; // set of substitutions being actively explored
let best = { value: [], weight: 0 }; // optimal path info
// For each character in the input string, left to right
for (let c of str) {
// Add new nodes to `open` for all `substitutions` that
// start with `c`
for (let entry of dict)
if (entry.match[0] === c)
open.push({
value: best.value.concat(entry.sub),
rest: entry.match,
weight: best.weight
});
// Add current character onto best path
best.value.push(c);
++best.weight;
// For each `open` path, try to match against the current character
let new_open = [];
for (let o of open) {
if (o.rest[0] === c) {
if (o.rest.length > 1) { // still more to match
new_open.push({
rest: o.rest.slice(1),
value: o.value,
weight: o.weight
});
} else { // full match found
if (o.weight < best.weight)
best = o;
}
}
}
open = new_open;
}
return best.value.join('');
};
Which would be used:
replaceGlobal('abcde', [
{ match: 'a', sub: 'w' },
{ match: 'abc', sub: 'x' },
{ match: 'ab', sub: 'y' },
{ match: 'cde', sub: 'z' }
])) === 'yz'
It passes some simple unit tests, but I may be overlooking something silly and it still seems more complicated than needed.
You could also make dict a trie of characters to make looking up the matches easier (and do the same with open). Even with the trie, I believe this approach would still be O(str.length * dict.length) though.
Me and my friend are having some trouble in regards to understanding Static and Dynamic scoping. I believe with dynamic, the variable (global) will keep being updated by other functions until printed, whereas with static I think that whatever value get's assigned to a variable first stays that way.
Is this thinking correct or no?
For an example using my thoughts above I have calculated the following from this code snippet.
int a, b, c;
void p() {
int a = 3;
b = 1;
c = a + b;
q();
}
void print() { printf(“%d %d %d\n”, a, b, c); }
void q() {
int b = 4;
a = 5;
c = a + b;
print();
}
main() {
int c = 5;
p();
}
Output with static scoping: 315
Output with dynamic scoping: 549
With static scoping, print would fail because neither a, b, nor c are assigned values either inside print or at the scope where print is defined (namely, the first line of the file).
With dynamic scoping, the output would be 549, since each of a, b, and c has a value assigned in q. Not demonstrated by your code is also the fact that after q returns from its call inside p, the local variable a has the value 5 set in q, not the global variable. Namely, the following occurs:
Global variables a, b, and c are declared, but do not have values. Let's assume your language initializes such values to 0.
main is called. A variable c local to main is given the value 5; global c still equals 0.
p is called. A p-local variable a is assigned the value 3; global a is still 0.
No local variable b exists in p or its caller, main, so the global b is set to 1.
No local variable c exists in p, but one does in c, to its value is set to 3 + 1 = 4.
q is called. A local b is declared and set to 4, leaving global b set to 0.
No local variable a exists in q, but one does in its caller p, so that value changes from 3 to 5.
No local variable c exists in q or its caller p, but does in p's caller main, so that value is set to 5 + 4 = 9. Global c is still 0.
print is called, and lacking any local a, b, or c, it looks back in its call chain. It uses a from p, b from q, and c from main (none of the globals are used.
q returns. In p, the values of a and c are still 5 and 9 as set in q. b is still 1, since q declared a local b.
p returns. In main, we still have a=0 (since p declared its own copy before calling q), b=1 (since p modified the global b), and c=9 (since q ultimately modified the variable local to c).
main returns. We still have global a=0, b=1, and c=0.
If that's confusing (and I didn't confuse myself and make any mistakes), you might understand why most languages use static scoping: it's not only much easier, but possible, to reason about the behavior of the program without having to run or simulate it just to track variable assignments.
static scoping- 5 1 9// it takes global values as variables not defined within print function
dynamic scoping- 5 4 9
So I have this problem where I have to figure out the output using two different scoping rules. I know the output using lexical scoping is a=3 and b=1, but I am having hard time figure out the output using dynamic scoping.
Note:the code example that follows uses C syntax, but let's just treat it as pseudo-code.
int a,b;
int p() {
int a, p;
a = 0; b = 1; p = 2;
return p;
}
void print() {
printf("%d\n%d\n",a,b);
}
void q () {
int b;
a = 3; b = 4;
print();
}
main() {
a = p();
q();
}
Here is what I come up with.
Using Dynamic scoping, the nonlocal references to a and b can change. So I have a=2 ( return from p() ), then b=4 ( inside q() ).
So the output is 2 4?
As we know, C doesn't have dynamic scoping, but assuming it did, the program would print 3 4.
In main, a and b are the global ones. a will be set to 2, as we will see that this is what p will return.
In p, called from main, b is still the global one, but a is the one local in p. The local a is set to 0, but will soon disappear. The global b is set to 1. The local p is set to 2, and 2 will be returned. Now the global b is 1.
In q, called from main, a is the global one, but b is the one local in q. Here the global a is set to 3, and the local b is set to 4.
In print, called from q, a is the global one (which has the value 3), and b is the one local in q (which has the value 4).
It is in this last step, inside the function print, that we see a difference from static scoping. With static scoping a and b would be the global ones. With dynamic scoping, we have to look at the chain of calling functions, and in q we find a variable b, which will be the b used inside print.
C is not a dynamically scoped language. If you want to experiment in order to understand the difference, you're better off with a language like Perl which lets you chose between both.