scala : how to inititialize a val with a check - javascript

In javascript there the logical OR is super useful in :
Given:
var sth = null;
var obj = sth || {}; // obj will be an empty object
var obj2 = sth || 'a'; // obj2 will be 'a'
is there anything similar for scala?

If an object may or may not exist, then it should be wrapped in an Option[A] - in which case, you can use getOrElse
val userOpt: Option[User] = db.getUser(id)
val user: User = userOpt getOrElse defaultUser
If you're talking about an arbitrary condition, then use:
val obj = if(condition) x else y

The most direct answer to this is the second part of what dcastro said about using an if expression on the left side of the equal sign.
val obj = if(condition) x else y
I wanted to elaborate some on that. I expect that the author of the question and others who like the approach used in JavaScript, Python, and other dynamic languages might find this to be verbose and prefer the use of || instead. The problem with this is that it only works when you are working in a language with little to no static type safety. In a language with good type safety, || is an operator that works on booleans and results in a boolean. Giving it arguments that aren't booleans is a type error. The || shortcut in JavaScript and other scripting languages only works because the arguments to || do not have to be boolean and all values have a natural 'truthy' or 'falsy' nature.

Related

JavaScript variable assignment with OR vs if check [duplicate]

This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well

Handling undefined variables simple conditions in NodeJS

Given this function:
var test = function(param1, param2_maybe_not_set) {
var my_object = {};
// code here...
}
What's the best, in your opinion?
my_object.new_key = (param2_maybe_not_set === undefined) ? null : param2_maybe_not_set;
OR
my_object.new_key = (param2_maybe_not_set === void 0) ? null : param2_maybe_not_set;
OR
my_object.new_key = (typeof param2_maybe_not_set === 'undefined') ? null : param2_maybe_not_set;
Alternatively, would this shortened expression be correct?
my_object.new_key = param2_maybe_not_set || null;
All four methods work (in the NodeJS console at least). Also jsPerf doesn't show a big gap between any of these (http://jsperf.com/typeof-performance/8)
Which one should be used, as a good practice?
They are not strictly equivalent, but can often be used interchangeably. Here are the major differences between them:
x === undefined: this performs a strict-equality comparison between the value and undefined, meaning that only a actual value of undefined will be true, whereas similar values like null or 0 will be false.
In the case of a function call, this check does not differentiate between f(a) and f(a, undefined) (in fact, none of the examples will; to differentiate, you'll have to look at arguments).
x === void 0: this uses the void keyword, which evaluates any expression and returns undefined. This was mostly done in the olden days to prevent surprises from people redefining the global undefined variable, but is not so useful nowadays (ECMAScript 5 mandates that undefined be read-only)
typeof x === 'undefined': this uses the typeof keyword, which has a unique ability - namely, that the operand is unevaluated. This means that something like typeof foobarbaz returns 'undefined' even if no such variable foobarbaz exists at all. Contrast this with foobarbaz === undefined, which will throw a ReferenceError if the variable name has never been declared.
x || null: this is the simplest and probably most readable alternative. The || operator is often used to "set defaults" on arguments, and can be chained like x || y || z || null.
In most cases, this is the idiomatic technique used. However, note that || performs implicit conversions, which means that any "falsy" values will trigger the next value (meaning that it can't differentiate between undefined, false, null, 0, '', and NaN). So, if your function expects to receive falsy values as arguments, it may be more prudent to explicitly check for undefined.
The option chosen to be an idiom in Javascript development to force a value for an unspecified argument is actually the last:
my_object.new_key = param2_maybe_not_set || null;
So this one should be preferrable since a lot of Javascript developers will immediately get its purpose.
Best.

Concise way of handling javascript null objects

What I want to achieve is clean code with several possible null returns where I'm not returning in more than one place, the code is easy to follow and is not a nested nightmare. For example consider
var topLevel = testdata['key'];//testdata['key'] may be null
var nextLevel = topLevel['subkey']; //topLevel['subkey'] may be null
var subSubLevel = ...
My initial thoughts are to do something like
var topLevel = testdata['key'] || 'error';
This will at least stop the "cannot get x of null" errors but then I'll have a block at the end where I'll need to check if each of these vars is error and if so return null and provide an appropriate error message (probably with an associative object).
Does anyone have a smarter, more concise way of achieving the same end result?
I'd probably do it with JavaScript's curiously-powerful && operator (the cousin of the curiously-powerful || operator you're already using):
var topLevel = testdata['key'];
var nextLevel = topLevel && topLevel['subkey'];
// ...
If topLevel is falsey (null, undefined, and so on), nextLevel will get that falsey value (the left-hand operand); if not, the right-hand operand is evaluated and nextLevel receives the value of that. Using these kinds of guards, you can keep going as long as you want.
var topLevel = testdata['key'];
var nextLevel = topLevel && topLevel['subkey'];
var nextNextLevel = nextLevel && nextLevel['key3'];
var nextNextNextLevel = nextNextLevel && nextNextLevel['key4'];
This is really handy when you're expecting an object reference, null, or undefined.

Create array and push into it in one line

The following is just a theoretical JavaScript question. I am curious if the following can be converting into a single statement:
if(!window.foo){
window.foo = [];
}
window.foo.push('bar');
everyone has probably written this code before, but can it be done in one line?
At first I thought something like this would work:
(window.foo || window.foo = []).push('bar');
but that doesn't work because of an invalid assignment. Next I tried chaining something on the push, but that doesn't work because push does not return the array.
Any thoughts on if this can be done in plain JavaScript?
(the result by the way should be that window.foo = ['bar'])
You've got your assignment backwards*. It should be:
(window.foo = window.foo || []).push('bar');
The || operator in JavaScript does not return a boolean value. If the left hand side is truthy, it returns the left hand side, otherwise it returns the right hand side.
a = a || [];
is equivalent to
a = a ? a : [];
So an alternative way of writing the above is:
(window.foo = window.foo ? window.foo : []).push('bar');
* see comments for details
Your code works just fine if you add parentheses so that it does what you intended:
(window.foo || (window.foo = [])).push('bar');
Without the parentheses, it thinks that it should evaluate window.foo || window.foo first, and then assign the array to the result of that, which is not possible.
This question got me playing with different options for fun. It's too bad push returns the length instead of the original array reference, but for even shorter expressions it can be helpful to have something that can be immediately iterated, mapped, etc.
window.foo = (window.foo||[]).concat(['bar']); // always returns array, allowing:
(window.foo = (window.foo||[]).concat(['bar'])).forEach( ... )
(window.foo = window.foo||[]).push('bar'); // always returns length
window.foo && window.foo.push('bar') || (window.foo = ['bar']); // playing around
2021 Update
#zzzzBov's helpful answer,
(window.foo = window.foo || []).push('bar');
can be further simplified using the new ||= operator, logical OR assignment1,
(window.foo ||= []).push('bar');
1 See tcs39/proposal-logical-assignment, currently in Stage 4, and supported by major browsers.
The shortest way to do this is using Logical Nullish Assignment:
(window.foo ??= []).push('bar');
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment
You can use .concat instead of .push, since .concat returns the array and .push returns the array's length.
window.foo = (window.foo || []).concat('bar');
This way the code is easier to read and understand.
Shorter version with a new ||= operator: (may be slightly harder to read though)
window.foo ||= [].concat('bar');

Calling javascript function with an objectstring in dot notation

Suppose I have the string:
var string = "function";
With
window[string];
I can call a function with the name of "function".
But, when I have:
var string2 = "function.method.weHaveTogoDeeper";
it should call
window["function"]["method"]["weHaveTogoDeeper"]
I can't do:
window[string2]
in this case. I dont know the number of "." in the string, so I need some kind of routine.
you can split the string across . by using the String.split method:
var string2 = "function.method.weHaveTogoDeeper";
var methods = string2.split(".");
In this examples, methods will be the array ["function","method","weHaveTogoDeeper"]. You should now be able to do a simple iteration over this array, calling each function on the result of the previous one.
Edit
The iteration I had in mind was something like this:
var result = window;
for(var i in methods) {
result = result[methods[i]];
}
In your example, result should now hold the same output as
window["function"]["method"]["weHaveTogoDeeper"]
function index(x,i) {return x[i]}
string2.split('.').reduce(index, window);
edit: Of course if you are calling functions from strings of their names, you are likely doing something inelegant which would be frowned upon, especially in a collaborative coding settings. The only use case I can think of that is sane is writing a testing framework, though there are probably a few more cases. So please use caution when following this answer; one should instead use arrays, or ideally direct references.
I wrote one a while back:
function RecursiveMapper(handlerName, stack) {
// check if empty string
if(!handlerName || handlerName === '' || (handlerName.replace(/\s/g,'') === '')) return null;
var buf = handlerName.split('.');
stack = stack || window;
return (buf.length === 1) ? stack[buf[0]] : this.RecursiveMapper(buf.slice(1).join('.'), stack[buf[0]]);
}
Call it like this: RecursiveMapper(window[string2]);
This one also checks if the function is defined in window scope first and returns the global one fi found.

Categories