Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea: Improve typeof #178

Closed
jasonkuhrt opened this issue Oct 1, 2012 · 33 comments
Closed

Idea: Improve typeof #178

jasonkuhrt opened this issue Oct 1, 2012 · 33 comments

Comments

@jasonkuhrt
Copy link

Question:

Why does typeof! [1,2,3] return 'Number'?

Idea:

Can we interchange typeof and typeof! so that the operator we know and hate can become the operator we know and love? The lesser of the two should be hidden behind alt syntax.

My only concern is not being able to typeof arrays as questioned above.

@gkz
Copy link
Owner

gkz commented Oct 1, 2012

Use it as an expression

r = typeof! [1,2,3] #=> ["Number","Number","Number"]

@jasonkuhrt
Copy link
Author

Better?:

  • drop the confusing/inconsistent ! for a readable s
  • fix typeof
o = {a:1  b:2  c:\b  d:[\nested  \array]}
a = [1  2  \a  \b  [\sub  \tree]  o]



typeof  o   #=> \Object
typesof o   #=> {a:\Number  b:\Number  c:\String  d:\Array}

typeof  a   #=> \Array
typesof a   #=> [\Number  \Number  \String  \String  \Array]



a-numbers = a |> filter (-> typeof it is \number)
a-numbers = typesof a |> filter (-> it is \number)

#=> [1, 2]
#=> {a:1  b:2}                (imagine o-numbers)



a-arrays  = a |> filter (-> typeof it is \Array)
a-arrays  = typesof a |> filter (-> it is \Array)

#=> [[\sub, \tree]]
#=> {d:[\nested  \array]}     (imagine o-numbers)

@satyr
Copy link
Contributor

satyr commented Oct 1, 2012

My only concern is not being able to typeof arrays as questioned above.

drop the confusing/inconsistent ! for a readable s

Note that typeof! and Unary Spread are separate features.

$ livescript -pe 'typeof!([1 2 3])'
Array

$ livescript -pe '^^[1 2 3]'
[ {}, {}, {} ]

@jasonkuhrt
Copy link
Author

@satyr I'm mystified. Why do these produce different values?

typeof!([1,2]) #=> 'Array'
typeof! [1,2]  #=> ['Number', 'Number']

More importantly, can we improve the native typeof as exemplified above (namely 'Array' identification)? The plural form is sugar, not as important.

@vendethiel
Copy link
Contributor

Because it triggers the unary spread.
+foo<[bar baz]> gives you [+foo['bar'], +foo['baz']]

@gkz
Copy link
Owner

gkz commented Oct 2, 2012

Perhaps unary spread is no longer needed in LiveScript, and could be removed in order to have fewer special cases, as we can simply use operators as functions.

map (typeof!), [1, 2] #=> ["Number","Number"]

A bit longer yes, but I think worth it in reducing the amount of special cases a programmer needs to keep in mind.

@vendethiel
Copy link
Contributor

I just think typeof! Shouldn't be unary spreaded. (I don't see why you'd use typeof! [...] anyway but ...)

@jasonkuhrt
Copy link
Author

@gkz +1 reduce special cases (where the payoff is low).

And what about simply fixing the standard typeof?

map (typeof), [[1], [2]] #=> ["Array","Array"]

@michaelficarra
Copy link
Contributor

@gkz: +1 get rid of unary spread. It's a neat feature, but leads to some confusing/unintuitive behaviours, and it's unnecessary as you say.

@vendethiel
Copy link
Contributor

Like I said - Unary spread is really cool, removing typeof from unary spreading wouldn't be better ?
(and why would you write "typeof []" or "typeof [a, b, c]" in the first place ?)

@jasonkuhrt
Copy link
Author

LiveScript typeof, in the future?

typeof some-array-value         # => 'array'
typeof 'boo'                    # => 'string'
typeof 5                        # => 'number'
...



# JavaScript code:

typeof$(someArrayValue)

function typeof$(value){
  if (Array.isArray(value)){
    return 'array'
  }else{
    return typeof value
  }
}

Simple.

@vendethiel
Copy link
Contributor

(typeof! array)toLowerCase! here you go.

@jasonkuhrt
Copy link
Author

@Nami-Doc Two versions of typeof that don't return the same values? This is just needlessly terrible, when you could easily have one that behaves as expected.

@vendethiel
Copy link
Contributor

You may want the native version.

@jasonkuhrt
Copy link
Author

@Nami-Doc Keyword maybe. I don't think its worth it. And if it is, use alt-syntax for said 'native'-version, not the fixed version that will be employed 99% (?) of the time. Isn't this practice (moving less-useful js operators to obscure names) livescript's policy for bitwise operations?

@vendethiel
Copy link
Contributor

It's also meant to be compatible with coffeescript. Or just when you're starting LS

@jasonkuhrt
Copy link
Author

@Nami-Doc An incompatibility worth making. Type-checking is fundamental. Should we really waste metons working around it. typeof is broken, lets fixed it.

typeof [] produces 'object' instead of 'array'. That isn't totally wrong since arrays in JavaScript inherit from objects, but it isn't very useful. typeof null produces 'object' instead of 'null'. That is totally wrong.

We can correct this by defining our own typeOf function, which we can use in place of the defective typeof operator.

^ Or we can use a tool like LiveScript to never have to think about this again

Ad infinitum:

I would really like to see this real problem solved. Reading through the articles it appears that there's more we may want to do to (regexp detection? fix typeof null?):

@josher19
Copy link
Collaborator

josher19 commented Oct 8, 2012

typeof! [1,2,3] looks like typeof()([1,2,3]) at first glance, rather than
a LiveScript version of typeof.

I'd recommend type-of or is-a or is-type instead of changing typeof
(which could break existing LiveScript code) or using typeof!

Note that it's sometimes tricky to use duck-typing or to fix typeof across
Frames.
jashkenas/underscore#12 (comment)

->> Josh <<-

@jasonkuhrt
Copy link
Author

@josher19 +1 that the bang in typeof! is terrible. I don't know about is-a though. In practice it is not ideal and is-a is less descriptive than typeof.

if is-a var is \array then ...

Just throwing this out there type-of:

if type-of var is \array then ...

Possible improvements could include:

- fix typeof null           #=> 'null'   ?
- better typeof []          #=> 'array'
- better typeof /boo/       #=> 'regex'
- better typeof NaN         #=> 'NaN'

@gkz @Nami-Doc thoughts?

@goto-bus-stop
Copy link

I think @josher19 means variable is-a \string or perhaps variable is-a string -> typeof$(variable) is \string

@jasonkuhrt
Copy link
Author

@renekooi Then is-a takes two arguments making it an infix function:

x is-a \string    # => true || false

is-a x \string    # => true || false

# What If we need to store the type for some other task?
# change is-a behaviour when given only 1 argument (return type)
# Confusing to read, unnecessary magic under-the-hood:

type = x is-a              #=> \string

type = is-a x              #=> \string

VS

type-of x is \string    # => true || false

# What If we need to store the type for some other task? 
# Clean, no-brainer:

type = type-of x        #=> \string

To my intuition it is obvious which one is better. The operator name, typeof, is a good one. It combined beautifully with is. LiveScript doesn't need is-a.

@vendethiel
Copy link
Contributor

(You can already infix with the backticks, but I agree with type-of)

@goto-bus-stop
Copy link

@jasonkuhrt I know, I didn't mean a function, but is-a as an operator (that's how I interpreted @josher19's suggestion)

@josher19
Copy link
Collaborator

josher19 commented Oct 9, 2012

type-of is better than typeof! because ! already has too many meanings:

  • not : !true # => false
  • no return value for functions : noreturn = !-> 1 # => function (){ 1; }
  • function call without arguments: {}.toString! # => [object Object]

One advantage of current typeof operator vs. a type-of function is when dealing with things that have not been defined:

typeof nothing  # => "undefined"
type-of nothing # => Error: nothing is not defined

is-a is probably too close to is but it would be nice if there was an improved instance-of operator that works across Frames and iFrames. If iArray is defined in an iFrame, this fails in the parent frame:

iArray instanceof Array  # => false
iArray instanceof Object # => false

instance-of(obj,klass) = obj instanceof klass or type-of(obj) ~= (klass.name or klass)

iArray `instance-of` Array # => true
iArray `instance-of` Object # => false

[] instanceof Array # => true
[] instanceof Object # => true

See also:

@gkz, +1 get rid of unary spread.

@jasonkuhrt
Copy link
Author

@josher19 make an issue about instance-of for cross-frame support? Sounds interesting.

Also @josher19 couldn't we compile down to a try ... catch ...? Look:

# Attempting to create an ideal typeof
# *Note: Pretend this function is an operator.
type-of = ->
  | it is null           => 'null'
  | Array.isArray it     => 'array'
  | it instanceof RegExp => 'regexp'
  | NaN === it           => 'NaN'
  | otherwise            => typeof it


# when we use type-of
# (I am consciously omitting parens, if you want this code to work in current livescript, wrap a with () )
if type-of a is 'array' then return \boom

# ...it should compile down into a try-catch expression
# This ensures type-of something-undefined doesn't throw a reference error
if (try type-of a catch 'undefined') is 'array' then return \boom

@Nami-Doc @gkz Where are opinions at now?

@gkz gkz closed this as completed in 7330542 Oct 24, 2012
@vendethiel
Copy link
Contributor

Whoops ;).

@gkz gkz reopened this Oct 24, 2012
@jasonkuhrt
Copy link
Author

Is there any consensus here? If not we should just close the issue for real. It wouldn't be a huge deal to just create a type-of function, so the real question is, is this issue worth solving at the core-level for the whole community (that uses livescript)?

@vendethiel
Copy link
Contributor

Unary spread is now better documented (t = typeof! [\b 5 {}] #=> ["String", "Number", "Object"]) as of 535f737.
Do you still want to get rid of them ?
Or change the syntax to a more obvious one (like <<[] or something - can't remember in languages that has that).

@jasonkuhrt I'd be okay with type-of, looks more like a keyword than typeof! (but ! is already used for compat. Bang meaning LS version: require, typeof. Bang meaning js version: delete).
I don't think it matters much. (and typeof!([1, 2]) is just typeof! ([1, 2]). Since types aren't backtraced ...)

@jasonkuhrt
Copy link
Author

@Nami-Doc Overloadding the ! character with multitude of concepts just for the sake of compat is a shame? Degrading language design and consistency might fail just as many people as the compat aspect wins.

But, if ! variant ops are here to stay, then just close this issue. I have a gripe with ! ops but at least it is a consistent gripe.

@robotlolita
Copy link
Contributor

I think getting rid of unary spread would make everything so much simpler, so that's a win. You can compose things easily because you can section operators into first-class functions, thus:

types-of = map (typeof)

I also vote for renaming typeof! to class-of, which would avoid the confusion between a value's type and it's internal [[Class]]. However, since LiveScript also provides a class syntax, I'm not sure how constructor functions generated by the class declaration should be handled.

@vendethiel
Copy link
Contributor

I'll go ahead and reopen this one (from #523). I think with the (+) syntax, we don't really need it anymore. ("let's use functions instead of core constructs")

@rhendric
Copy link
Collaborator

After (the still undocumented, alas) #863, it doesn't seem like there are any outstanding needs here, so I'll reclose.

@determin1st
Copy link

it's not well documented what typeof! returns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants