The interpreter's ability to deal with such an implicit definition depends on the delay resulting from wrapping the call of add_streams into a function definition. Without this delay, the interpreter could not construct integ before evaluating both arguments to pair, which would require that integ already be defined. In general, such a delay is crucial for using streams to model signal-processing systems that contain loops. Without a delay, our models would have to be formulated so that the inputs to any signal-processing component would be fully evaluated before the output could be produced. This would outlaw loops.
[1] This is a small reflection, in JavaScript, of the difficulties that conventional strongly typed languages such as Pascal have in coping with higher-order functions. In such languages, the programmer must specify the data types of the arguments and the result of each function: number, logical value, sequence, and so on. Consequently, we could not express an abstraction such as map a given function fun over all the elements in a sequence by a single higher-order function such as stream_map. Rather, we would need a different mapping function for each different combination of argument and result data types that might be specified for a fun. Maintaining a practical notion of data type in the presence of higher-order functions raises many difficult issues. One way of dealing with this problem is illustrated by the language ML (Gordon, Milner, and Wadsworth 1979), whose polymorphic data types include templates for higher-order transformations between data types. Moreover, data types for most functions in ML are never explicitly declared by the programmer. Instead, ML includes a type-inferencing mechanism that uses information in the environment to deduce the data types for newly defined functions.
3.5.4 Streams and Delayed Evaluation