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: Sat, 20 Mar 2021 14:49:42 +0300 Organization: A noiseless patient Spider Lines: 138 Message-ID: <20210320144942.f32b26506f67afa7a039ec2a@gmail.com> References: <20210313153232.40fa0c8b0adf07d7e807084d@gmail.com> <20210314185124.0bcbab76d172caf076ac3839@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Injection-Info: reader02.eternal-september.org; posting-host="0b6de666454792515201e0a3034742c6"; logging-data="7145"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19puO/caBFLXS9Cv6DbF02zcntAPMdho8g=" Cancel-Lock: sha1:5crswVOFTftvWYfnHI0qjrLglxk= X-Newsreader: Sylpheed 3.7.0 (GTK+ 2.24.30; i686-pc-mingw32) Xref: csiph.com comp.lang.javascript:39716 Michael Haufe to Anton Shepelev: > > What is the JavaScript style of implementing TryParse() > > and TryGetValue()?-- > > TryParse: https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse > > ``` > let x = parseInt('145') > ``` > > x is the number or NaN if it failed. I know about parseInt(), but its interface is different: it has no out parameter and no boolean return. Therefore, it cannot be used inside a condition without additional trickery, e.g.: var i; if( isNaN(i = parseInt(`d5`))) console.log("Not a number."); else console.log(`Parsed. The double is ${2*i}.`); > If you want a default value: > > ``` > let x = parseInt('not a number') || 12; > ``` > Note in the latter case '0' would be treated as a failure. No, not in this case, but thanks for pointing out the possibility. > Slightly longer alternative: > > ``` > let parseIntOrDefault = (x, defaultValue) => { > let result = parseInt(x, 10) > return isNaN(result) ? defaultValue : result > } > ``` That is what I would use if I needed a default value: function parseIntDef(s, def) { var res; if( typeof(s) != "string" ) { throw new Error("`s' is not a string."); } if( typeof(def) != "number" ) { throw new Error("`def' is not an int."); } res = parseInt(s); if( isNaN( res ) ) { res = def; } return res; } > > TryGetValue: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.trygetvalue > > In JavaScript operations belong to the object and not to > the type. I try not to rely on it, preferring to pass all the necessary data in parameters. > The default value is supplied by you and not implied by > the type system. I do not care about any implied default values, because I use the out parameter only if the invocation succeeded. If it failed and returned false, it means the dictionary does not contain the key, and I can provide my own default value, should I so desire. > > while( read_next( stream, out element ) > > { // process the element > > } > > > > What alternative(s) does JavaScript propose? > > JavaScript has iterators and generators for this style of > coding: > > US/docs/Web/JavaScript/Guide/Iterators_and_Generators> I think it is rather complicated approach that goes way beyond procedural programming and relies on object-oriented and functional mechanisms (with `yield' implemented as an entire state machine under the hood!), when all I ask for is a simple function. OK, I can write it in JavaScript by passing it a callback: function read_next( stream, set_elem ) { var res; res = true; if EOF( stream ) res = false; else set_elem( NEXT( stream ) ); return res; } But obviously it clumsier than a plain output parameter, about which you write: > The problem is that it makes local reasoning more > difficult. I can not simply look at a function call and > know that it's simply returning a value, I'd have to > inspect the arguments to see what side-effects are > potentially happening in my scope. In that sense, OOP is all about such side-effects, where a method call may change the state of data that is not explicitly passed to it, but is buried somewhere in `this'. If a function changes the value of an `out' parameter, it is not a side effect but an explicitly specified operation that in many languages is visible in the call: C : hasData = ReadNext( &stream, &element ); C#: hasData = ReadNext( stream, ref element ); Both of these calls change the state of `stream' and, if a new element has been read, put it into the `element' variable. Remember also that I am talking about *scalar* output parameters. They are entirely free of side effects because a function cannot partially modifythem, as it can modify some, but not all, fields of an object. Therefore, modification of object members (allowed in JavaScript) is actually less transparent than modification of scalar values (not allowed in JavaScript). -- () ascii ribbon campaign -- against html e-mail /\ http://preview.tinyurl.com/qcy6mjc [archived]