5 ms·
I'll come to the defense of &. - for better or worse Ruby is mostly used for building database backed web applications where nils are simply unavoidable without
by jacobsenscott 8y ago
I'll come to the defense of &. - for better or worse Ruby is mostly used for building database backed web applications where nils are simply unavoidable without some extreme over engineering or awkward idioms. `user&.address&.street` is at least safer than `try` - `user.try(:adress).try(:street)` - will not raise an error that `adress` is not a method. You could try and apply the null object pattern, but then `user.address.present?` is quite a rabbit hole - and frankly nil is the right return value for a user with no address on file.
- mberning 8y agoAgreed. This does not seem that egregious and is way better than .try() or even worse putting a rescue at the end.
- schneidmaster 8y agoYeah, the safe navigation operator is great, and I really miss it especially when I write JavaScript and have to do something like `foo && foo.bar && foo.bar.baz` instead (...which isn't even the same since it returns `false` if something is null).
- lobo_tuerto 8y agoJust use lodash for that. Your example would become: // this won't throw an exception if foo is null _.get(foo, 'bar.baz') And you can even set a default value to return if it is: https://lodash.com/docs/4.17.11#get https://lodash.com/docs/4.17.11#get
- freewilly1040 8y agoThe point isn't that it's an unsolvable problem, the point is that you have to resort to clunky syntax or a 3rd party library to do this. And for something as basic as this, there's probably a number of different libraries that solve the same problem a slightly different way.
- hombre_fatal 8y agoYou lose all static analysis with that including Typescript checking/inference.
- benaiah 8y ago> which isn't even the same since it returns `false` if something is null That's not the case AFAIK - checking in both node and FireFox, `true && null` evalutes to `null`, `true && undefined` evaluates to `undefined`, and `true && null && true` again evaluates to `null`. In what scenario does `&&` coerce the returned value to a boolean? EDIT: checked MDN's docs at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... - it seems to indicate that there is no such coercion of falsy values to false.
- schneidmaster 8y agoYeah, you're right, I was misremembering the behaviour of `null && null`. At any rate, still clunkier :)
- simpsond 8y agoI also use and prefer safe navigation over the standard alternative. However, Maybe/Option monads are also nice. Perhaps that is what the author has in mind.
- cknoxrun 8y agoKeep in mind there is also the try! method to raise an error if the method does not exist (which is now likely implemented as &.)
- jacobsenscott 8y agoAh, I did not know about try!. Thanks.
- otabdeveloper2 8y ago> building database backed web applications where nils are simply unavoidable without some extreme over engineering or awkward idioms Say what? Adding a 'NOT NULL' to your database fields is a no-brainer.
- jacobsenscott 8y agoOnly for fields where a not null constraint makes sense of course. But NULL represents the absence of a value - which is very often a valid choice in a database.
- dragonwriter 8y ago> Only for fields where a not null constraint makes sense of course A NOT NULL constraint always makes sense, assuming your tables are designed correctly, such that each table contains all and only those columns needed to represent a distinct category of fact that needs to be stored, which necessarily means that all columns must occur together or not at all. When tables are designed instead to contain multiple different shapes of facts with some shared elements, then you get the need for nullable columns, but that's problematic in other ways, too.
- jacobsenscott 8y agoJust because you can design a database that way doesn't mean you want to, or that you even have control over the db design. Anyway, data is still present or absent. Even if you have an address table where all the columns are not null you might not have an entry in that table for a user so what would you like user.address to return?
- dragonwriter 8y ago> Even if you have an address table where all the columns are not null you might not have an entry in that table for a user so what would you like user.address to return? IMO, the best general solution is: if a relationship has a fixed cardinality of exactly one in the direction of interest, trying to traverse it should return the exactly one item it refers to. If a relationship has any other cardinality (fixed at some number > 1, variable between 0 and 1, variable between 0 and +∞, variable between 7 and 13, ...), trying to traverse it should return a container (set, bag, list, generator, ...) of values, whose cardinality will be the actual cardinality of the relationship. (That's really just as true if the underlying DB uses nulls or magic values or whatever else to indicate missing data; and, yes, returning application language nulls from low level database routines may be a convenience for those implementing the higher level abstraction layer on top of that low-level interface, but once you get into the mode layer there's not a great reason for presenting NULLs -- except in the special case of languages where the NULL is the empty list or another appropriate empty container.)
- bozhidar 8y agoYou've missed my point about `&.` (probably because I didn't provide much of an explanation) - it's fine in certain cases (your example is a good one), but it's also something that can be easily abused. Very often I've seen people use `&.` even for methods that can never return `nil`, which is confusing for people who read their code. I've also seen plenty of methods which could have returned a en empty collection on an empty string that return a nil for no good reason, but it's easy to deal with nil now, so why bother to think carefully... Every feature that promotes sloppy APIs nil is a potential liability and should be used carefully.