Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Anton Shepelev Newsgroups: comp.lang.javascript Subject: Re: input/output parameters Date: Sun, 21 Mar 2021 17:35:45 +0300 Organization: A noiseless patient Spider Lines: 123 Message-ID: <20210321173545.545eb9058531187e4dced4bd@gmail.com> References: <20210313153232.40fa0c8b0adf07d7e807084d@gmail.com> <20210315002732.dbb3221feb6d3a0c065292cf@gmail.com> <604f92ed$0$13963$e4fe514c@newszilla.xs4all.nl> <20210320155006.f1909610fd93de6c3afec7cb@gmail.com> <1sgc5g57tii460r30erthh6nvp94gu4mab@4ax.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Injection-Info: reader02.eternal-september.org; posting-host="b77e6093baab2ad7ae021e22a1d13939"; logging-data="19332"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+6FfTKihUeZguj14LtdKb3EPq7YRretJA=" Cancel-Lock: sha1:aE1Q4uv0CLlhMBpns2NfL+7oxyY= X-Newsreader: Sylpheed 3.7.0 (GTK+ 2.24.30; i686-pc-mingw32) Xref: csiph.com comp.lang.javascript:39731 John G Harris about output parameters: > One disadvantage is that proving that the function does > what it's supposed to do is more complicated. If there's > just a returned data structure to check then that is (we > hope) straightforward. If there are external altered data > structures to check then the job becomes partly a check of > the function and partly a check that it's used sensibly. I don't see how the introduction of output parameters makes you check the function itself and data structures it has altered instead of just testing its output. One must *always* check that any function is used sensibly: is applied to the right values, its result is store in the right variable(s). It hardly matters whether the result comes from the return value of output parameters. Consider the following examples: var i1, i2, i3; var o1; makeref("o1"); var o2; makeref("o2"); var o3; makeref("o3"); // ... ( {o1, o2, o3} = f1( i1, i2, i3 ) ); f2( i1, i2, i3, $o1, $o2, $o3 ); where the second one uses my makeref() macro-like function that wraps a value into a pair of getter/setter closures to make it behave like a by-reference argument. Both invocations are equally easy to test, say, by some function check( o1, o2, o3 ) { /* ... */ } As to the human reader, local reasoning about both the invocations is the same. It becomes somewhat harder, though, when you pass not scalar variables, but the properties of an object. Let us now try to do what you call alteration of local data structures, first my way: function makeref(v, n) { return `var ${n} = {set _(val){${v}=val;},get _() {return ${v};}}`; } function func1( $1, $2 ) { $1._ += 1; $2._ += 2; } function func2( v1, v2 ) { return [ v1 + 1, v2 + 2 ]; } var obj = {f1:0, f2:0}; eval( makeref("obj.f1", "$1") ); eval( makeref("obj.f2", "$2") ); func1( $1, $2 ); console.log(`${obj.f1} ${obj.f2}`); Althouth the invocation of func1() now changes local structures, it is still perfectly transparent because the reader can see the passing of the individual properties as "output" parameters. With multiple assignments it would look like this: function func2( v1, v2 ) { return [ v1 + 1, v2 + 2 ]; } ({obj.f1, obj.f2} = func1( $1, $2 );); but destructuring does not work with object properties, which is why it is not called multiple assignment (I guess). A third way to modify local data structures is by passing them to the function wholesale: function func3( o ) { o.f1 += 1; o.f2 += 2; } /* ... */ func3(obj); Now we have introduced a level of non-transparency, where the reader of invocation cannot tell which properties are going to change and which are not. Sometimes it is OK, as I know the intent of the function. But formally, the effect of the invocation upon the local structures is not evident. But I must admit that the need to modify several properties of an object in a single invocation of a function not specific to that object type is quite rare in well- structured code. A more ralistic example would be the modification of a signle property: o.f1 = func4(); // or: func4( $o_f4 ); which, again, are equally transparent, or would be if JavaScirpt had supported output parameters natively. > Also, building code that runs a confidence test of the > function becomes more complicated. What is a confidence test? All I find in the internet are psychological quizzes. Anyway, ease of use should be always preferred to the ease of testing. A little wrapper to invoke the function according to its interface is not a big deal, if you need automated tests. > That said, sometimes it can't be avoided : where a file is > read by several different functions for instance. What can't be avoided -- managing the state of the file object? -- () ascii ribbon campaign -- against html e-mail /\ http://preview.tinyurl.com/qcy6mjc [archived]