20

Today I bumped exactly into this issue: Uncaught TypeError: (intermediate value)(...) is not a function

So yeah, after placing the semicolon where appropriate, it no longer throws that error. However, I never knew there is such a concept in JavaScript (intermediate value).

Apparently you can generate a similar variation of that error with this piece of code:

[myFunc] = function(someVar){
 
 console.log(someVar);
 return 7;
}();

//error thrown: (intermediate value) is not a function or its return value is not iterable

And if you name the function, it's no longer intermediate:

function hi(){return undefined}

[a] = hi(); 

// error thrown: hi is not a function or its return value is not iterable

I understand that it refers to something that is intermediate, but in this case we have an anonymous function, and there are ways to determine if a function is anonymous, so the error message could've been a little more explicit.

Searching the js mozilla mdn I found this page that talks about Array.from, where the concept of "intermediate array" can be found:

More clearly, Array.from(obj, mapFn, thisArg) has the same result as Array.from(obj).map(mapFn, thisArg), except that it does not create an intermediate array.

But besides pieces of info here and there, it's not clear what an intermediate value is.

Is there an official definition to this?

wonea
  • 3,987
  • 17
  • 71
  • 134
Adelin
  • 6,791
  • 5
  • 33
  • 58
  • You get the same error in your second example if you provide the same return value as the first. You changed it to `undefined`. The value `7` is not useful for destructuring assignment. –  May 14 '18 at 11:38
  • @CrazyTrain: Yeah. On Chrome, you get the same error other than `(intermediate value)` vs. `hi` (the one shown in the comments in the snippets above). But in SpiderMonkey, the `undefined` thing did indeed make it use a completely different error message. – T.J. Crowder May 14 '18 at 11:40
  • 1
    @T.J.Crowder: I was just about to ask you about that below. At first I thought I wasn't getting an error with `undefined`, but I see now that it just changed the message. –  May 14 '18 at 11:42

1 Answers1

13

An "intermediate value" is just a value that's produced inside an expression that isn't the final value of the expression. In a = (b * c) + d the result of b * c is an intermediate value in the right-hand-side expression.

Yes, in this specific case, the error message could say "(anonymous function) is not a function or its return value is not iterable". Not all intermediate values are anonymous functions, though. The implementers of V8 just chose to use a generic error message. (SpiderMonkey [in Firefox] uses the same terminology, though a different message.)

Is there an official definition to this?

The specification uses the term "intermediate result" here, to mean essentially the same thing as "intermediate value" (to my eye):

6.2 ECMAScript Specification Types

A specification type corresponds to meta-values that are used within algorithms to describe the semantics of ECMAScript language constructs and ECMAScript language types. The specification types include Reference, List, Completion, Property Descriptor, Lexical Environment, Environment Record, and Data Block. Specification type values are specification artefacts that do not necessarily correspond to any specific entity within an ECMAScript implementation. Specification type values may be used to describe intermediate results of ECMAScript expression evaluation but such values cannot be stored as properties of objects or values of ECMAScript language variables.

(my emphasis)


Note that your code samples are not identical other than giving the function a name. One of them attempts to iterate the value 7. The other attempts to iterate the value undefined. It doesn't matter to the error message from V8 but it did for SpiderMonkey. Let's compare apples with apples, remove irrelevancies, and declare our variable:

"use strict";

var myFunc;

try {
  [myFunc] = function(){
    return 7;
  }();
} catch (e) {
  console.error(e.message);
}

try {
  [myFunc] = function hi(){
    return 7;
  }();
} catch (e) {
  console.error(e.message);
}

try {
  function hi(){
    return 7;
  }
  [myFunc] = hi();
} catch (e) {
  console.error(e.message);
}
T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • You'd think that JS, by the time it displays that error message, would know exactly what "intermediate value" is... – Adelin May 14 '18 at 11:44
  • 1
    @Adelin - I haven't implemented a highly-optimized JavaScript engine, so I wouldn't know. :-) – T.J. Crowder May 14 '18 at 11:45
  • @Adelin back at the start of the 60s when the AI field was just starting, people *in the field* were already going "you'd think that in 5 years time, we'd have intelligent computers". Half a century later and we're even further than what the expectations were back then. Turns out some things in computer science are *hard* when you actually start looking into them. [Relevant XKCD](https://xkcd.com/1425/) (check the alt text). – VLAZ May 14 '18 at 11:52
  • seriously, with a clear order of execution and each part of an expression being evaluated one at a time, I find it strange that such errors even exist. I still don't understand why I don't just see `undefined` there instead of `intermediate value` – Adelin May 14 '18 at 11:56
  • @Adelin - Because the intermediate value isn't `undefined`. It's a function. (Note the error message is "(intermediate value) is not a function or its return value is not iterable" -- in this case, the relevant bit is the second part: "its return value is not iterable".) If you haven't implemented a highly-optimized, memory-efficient, blazingly-fast JavaScript engine, I'd suggest just assuming the people who have have a reason for what they've done. :-) – T.J. Crowder May 14 '18 at 12:04
  • @T.J.Crowder **(1)** Imagine `var num = 7;`. To me. that error message is like seeing `num is not a number or it's not bigger than 10`. Something is either a function or not, but if it's not, you can check and know from the first line of execution. I don't think it's ok to say: "that is not a function, or it's a function that doesn't return what we expect" **(2)** Imagine `bye = function(){return 7}`. If instead of `[a] = bye()` if you use `[a] = 7 + bye()`, the error message is no longer that vague, it's: `(7 + bye(...)) is not iterable`. So in some cases they know if it's iterable. – Adelin May 14 '18 at 12:20
  • 2
    Again, you are assuming a lot. JavaScript doesn't exactly evaluate everything line by line. It will pre-process a script and THEN start executing it. Your `var num = 7` actually includes *three steps* to even execute that line. It gets defined, so `num` exists as a concept, then it gets initialised, so it can be *used*, finally it gets assigned the value `7`. If you theoretically have `num > 10` after it's defined but before it's initialised you would also get an error message which may as well say `num is not a number` (it's not even `undefined` yet) `or is not bigger than 10` - it's not. – VLAZ May 14 '18 at 12:33
  • @Adelin - Fine. :-) Implement your own JavaScript engine, and have the error messages be exactly as you like them. :-) – T.J. Crowder May 14 '18 at 12:39