Hacker News new | ask | show | jobs
by ajanuary 4181 days ago
> This means that typeof can now throw

    >>> def f():
    ...     type(x)
    ...     x = 10
    ...
    >>> f()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in f
    UnboundLocalError: local variable 'x' referenced before assignment

    irb(main):010:0> def f()
    irb(main):011:1>     x.class
    irb(main):012:1>     x = 10
    irb(main):013:1> end
    => nil
    irb(main):014:0> f()
    NameError: undefined local variable or method `x' for main:Object
    	from (irb):11:in `f'
    	from (irb):14:in `evaluate'
    	from org/jruby/RubyKernel.java:1101:in `eval'
    	from org/jruby/RubyKernel.java:1501:in `loop'
    	from org/jruby/RubyKernel.java:1264:in `catch'
    	from org/jruby/RubyKernel.java:1264:in `catch'
    	from C:/jruby-1.7.12/bin/jirb_swing:53:in `(root)'

    public class Test {
    	public void f() {
    		boolean isInt = x instanceof Integer;
    		Integer x = 10;
    	}
    }
    >javac Test.java
    Test.java:3: error: cannot find symbol
                    boolean isInt = x instanceof Integer;
                                    ^
      symbol:   variable x
      location: class Test
    1 error
Oh no, it's now in line with just about every other lexically scoped language.
2 comments

`typeof a` right now returns the string value "undefined" (assuming `a` was not defined anywhere)

If it can either return "undefined" or throw an exception, can you see why that would be a problem?

No, because it can only throw if there's a flaw in the code. Not randomly according to the argument passed to the function. Unless I'm missing something, it will either always throw, or never throw.
If a statement didn't throw before and might start throwing now, that would be a problem for existing code wouldn't it?
No because the let keyword didn't exist before. So existing code won't suddenly start to throw. The article's author is making a terrible, bogus argument.
Except, now you have one that you expect and the other you don't. This doesn't make the language anything but more inconsistent. I prefer consistency inside a language far more than familiarity between languages.
Remember, it's not the function that's throwing the exception, it's the runtime. In order to make it not throw an exception, we'd have to special case typeof to make the runtime behave differently just for it. /That/ is inconsistent.
This throws an error:

    typeof x; // throws an error
    let x = 1;
This doesn't:

    typeof x; // returns "undefined"
    var x = 1;
While using variables before declaring them is bad practice, I think it's fair to argue that this behaviour is inconsistent.

    let x = 0;
    function typeof_wrapper(y) { return typeof y; }

    (function() {
        typeof_wrapper(x); // throws an error
        let x = 1;
    })();

    (function() {
        typeof_wrapper(x); // returns "undefined"
        var x = 1;
    })();
Again, typeof isn't throwing the error, the runtime is, because a variable declared with "let" is being referenced before the declaration. It's not inconsistent, it's one of the main points of "let".

You're essentially arguing that a feature added because the old behaviour was undesirable is inconsistent because it's not exhibiting the old undesirable behaviour.