go version)?go version go1.11 darwin/amd64
Yes.
go env)?js/wasm
JS has the concept of "truthy" and "falsy". It'd be nice if these were part of syscall/js, either as part and parcel of Value.Bool(), or failing that something along the lines of
func (o Value) Falsy() bool {
return !o.Truthy()
}
func (o Value) Truthy() bool {
switch o.Type() {
case TypeUndefined, TypeNull:
return false
case TypeBoolean:
return o.Bool()
case TypeNumber:
if math.IsNaN(o.Float()) {
return false
}
return o.Float() != 0
case TypeString:
return o.String() != ""
case TypeSymbol, TypeObject, TypeFunction:
return true
}
return true
}
/cc @neelance
I'm not yet sure if it would be good to include it in syscall/js. For which APIs would you need the concept of "truthy"? Could you provide examples please?
I've been updating my Vue.js wrapper to use your wasm-sync-callbacks tree. I was trying to replicate an example from the Vue Guide (here, the bit that starts with "This will render the same result. We can also bind to a computed property that returns an object.") The JS in question is
function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
So for this.isActive and this.error I wanted "truthy", for !this.error I wanted "falsy". I implemented that part of that example like this:
return hvue.Map2Obj(hvue.M{
"active": hvue.Truthy(data3.Get("isActive")) &&
hvue.Falsy(data3.Get("error")),
"text-danger": hvue.Truthy(data3.Get("error")) &&
data3.Get("error").Get("type").String() == "fatal",
})
where hvue.Map2Obj(hvue.M{...}) is similar to how GopherJS automagically transforms a GopherJS js.M{} into a JS object, and hvue.Truthy() and Falsy() are similar to the example code I posted at the top of this issue, except obviously not methods on js.Value. (See here.)
One could certainly argue that the _absence_ of such a vague concept as "truthiness" in Go is (one of the reasons) _why we use Go_ and not JavaScript, and I could certainly understand that, and agree that in most cases you shouldn't do it. But pragmatically I think there are clear use-cases for it.
So to sum up, when transliterating JavaScript to Go, since JavaScript uses truthiness a lot, I think it'd be handy and pragmatic for JS-transliterated-to-Go to be able to do the same, "out of the box".
I could see that you might not want Value.Truthy()/Falsy() in syscall/js (although obviously _I_ think having them as methods on Value would be the most useful). There are other utility-functions that might also be handy, that shouldn't be in syscall/js. So perhaps a syscall/js/jsutil or top-level jsutil package would be appropriate? We discussed this a bit in the Gophers #webassembly channel (starting here), and one library with some nice utilities was pointed out: https://github.com/dennwc/dom/tree/master/js (permalink).
I'm not yet sure if it would be good to include it in syscall/js
I'd tend to agree; the implementation of "truthy" or "falsey" feels like something that should be left to the JavaScript VM; we would be reimplementing that logic which feels wrong.
we would be reimplementing that logic
Not necessarily. It could be
// Global JavaScript function
function isTruthy(o) {
if (o) { return true } else { return false }
// or even: return !!o
}
func (o Value) Truthy() bool {
return Global().Call("isTruthy", o).Bool()
}
That said, the concept of "truthy", while admittedly a bit general, is actually pretty well-defined: "All values are truthy unless they are defined as falsy (i.e., except for false, 0, "", null, undefined, and NaN)". (In fact in my initial implementation of Truthy() & Falsy() I had Falsy() checking for false/0/etc, and Truthy was !Falsy, but then I inverted them.) My point being, I suspect that a pure-Go version would be faster and just as accurate as trampolining to JavaScript.
I suspect that a pure-Go version would be faster and just as accurate as trampolining to JavaScript.
It might be useful to have some hard numbers here. It seems like a lot of work is being done to speed up these types of calls.
It might be useful to have some hard numbers here
Happy to give it a shot, if @neelance (et al) think this is a reasonable feature in the first place. If they don't want to do it, it doesn't matter how fast it is. :)
If the JS-inclined people generally agree this is a good idea, I don't object to adding one method. Two seems overkill, though. (e.g. we have utf8.ValidString but we don't also have utf8.InvalidString for the opposite)
I am quite sure that the pure-Go version will be faster.
In JS, using truthiness is common, but I think this is mostly because it has the simplest syntax. Not using truthiness in JS just looks ugly quite often.
I've seen truthiness hiding bugs. Having a strong expectation about a type of a value is usually safer. However, there are use cases with legacy code that need truthiness.
I don't object to adding just Truthy either. I just hope it will get used sparingly.
I think in the case of porting legacy JS into a Go ecosystem, the Truthiness concept and the need to port this behaviour would appear often, and could be a point of confusion and or bugs.
In the interests of correctness on the Go side of the fence, it would be good if syscall/js provided a correct implementation for all to use, and make porting that little bit more attractive.
Having said that, I hope that I _never ever_ have the need to use this syscall myself.
I am slightly leaning in favor of this. I suspect more people will ask for this as wasm gains in popularity. I would also prefer a pure-Go version since truthy-ness is quite well-defined.
@theclapp Mind creating a CL? :)
@neelance Will do. It may be a few days. This'll be my first Go code contribution, so there's that first-timer learning curve to climb.
Change https://golang.org/cl/144384 mentions this issue: syscall/js: add Truthy() as a method on js.Value
Change https://golang.org/cl/154618 mentions this issue: doc/go1.12: add notes for syscall/js CLs 141644, 143137, 144384
Most helpful comment
It might be useful to have some hard numbers here. It seems like a lot of work is being done to speed up these types of calls.