I'm new to JavaScript. In nashorn 1.8.0_11 I see the behavior below. Note print(x) works fine yet evaluating x causes a crash. May I consider this a bug? If so, is it a known bug?
jjs> var x = Object.create(null);
jjs> print(x);
<shell>:1 TypeError: Cannot get default string value
jjs> x;
Exception in thread "main" ECMAScript Exception: TypeError: Cannot get default string value
at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:56)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:212)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:184)
at jdk.nashorn.internal.objects.Global.getDefaultValue(Global.java:592)
at jdk.nashorn.internal.runtime.ScriptObject.getDefaultValue(ScriptObject.java:1257)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:256)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:252)
at jdk.nashorn.internal.runtime.JSType.toStringImpl(JSType.java:993)
at jdk.nashorn.internal.runtime.JSType.toString(JSType.java:326)
at jdk.nashorn.tools.Shell.readEvalPrint(Shell.java:449)
at jdk.nashorn.tools.Shell.run(Shell.java:155)
at jdk.nashorn.tools.Shell.main(Shell.java:130)
at jdk.nashorn.tools.Shell.main(Shell.java:109)
This is as expected. When you evaluate expressions interactively with "jjs" shell tool, it converts evaluated expression result as String to print the same. Also, "print" function calls toString on object to print string representation of it to console. With Object.create(null), you are creating an object whose prototype is null (and hence does not inherit Object.prototype.toString). Also, your object does not have "toString" property with function typed value and hence the TypeError. Please note that you can similar behaviour with v8 shell as well.
V8 version 3.25.15 [sample shell]
var x = Object.create(null)
x;
print(x)
Related
Just added Flow types to a project I'm working on and progressively adding types until I got to this error:
Cannot call JSON.parse with localStorage.getItem(...) bound to text because null or undefined [1] is incompatible with
string [2]
This comes from a expression:
const myVar = JSON.parse(localStorage.getItem('itemName'))
I understand why I get this error (except maybe the "bound to text" part), but couldn't find a way around it. I'd appreciate any help here!
So, the function localStorage.getItem can return null values and flow wants you to tackle them before parsing it. As JSON.parse only takes a string, you can do the following:
localStorage.getItem("key") || '{}'
So, if it returns null. The empty object string is chosen, which JSON.parse can parse into an empty object.
Prefer using 'null' than '{}' as it parses to empty object
JSON.parse(localStorage.getItem("key") || 'null') // null
JSON.parse(localStorage.getItem("key") || '{}') // {} - empty object
I have a php script which was written on php 5.6.19, works on 5.3 version to, with some installed addons.
I decide to try execute it on php7.
The special of the script that I am initializing a class with parameter by reference via creating a new instance with Reflection::class. And there warning then waited variable by reference but value received.
Definition of the class' constructor method tried to create an instance from:
public function __construct($user, IDatabase &$repository, $errors = null);
Sample of code where this constructor is used:
// define manager type to create (all managers has the same constructor)
$manager = $managersNamespace . ucfirst($this->_manager) . "Manager";
// trying to create the manager
// !!!And here a Warning occurs
$reflect = new \ReflectionClass($manager);
$manager = $reflect->newInstance($user, $database, $errors);
After these I am invoking a method I need, and here the fatal error with stopped the script:
$method = "show" . ucfirst($this->_page) . "Page";
$reflect->getMethod($method)->invoke($manager);
I didn't see any changes in documentation. Anyone had the same issue?
First and foremost, why are you passing an object by reference !?
Objects have pass-by-reference semantics, forcibly trying to pass objects by reference has not made good sense since PHP 4.
Just remove the & ...
Let's ignore that, and pretend there is still a problem, so that you can try to understand what is going on.
To break down the problem, first you need to understand the distinction between a variable and an expression:
mine(1 + 2);
The argument to mine has no name, it's represented by a temporary variable in the engine: it's an expression.
mine(1);
The argument to mine has no name, it's not an expression, but a literal constant, represented by a compiler variable in the engine. It's similar to a temporary variable, a kind of constant expression.
mine($a);
The argument to mine has a name, which you can use to refer to it's value. It's a normal variable.
Only variables can be passed by reference because you cannot refer to expressions or literal constants
Next you need to understand why we pass-by-reference:
function mine(int $thing) {
$thing++;
}
$a = 1;
mine($a);
var_dump($a); // int(1)
In this code, $a is passed to mine() by value, so that the changes that mine() make to $thing are only visible inside the scope of mine. $a is unchanged after the call to mine() returns because $a and $thing are distinct, having been passed-by-value, which means it's value was copied on to the call stack for the invocation of mine().
function mine(int &$thing) {
$thing++;
}
$a = 1;
mine($a);
var_dump($a); // int(2)
In the code above, $a is passed to mine() by reference, this means that $a and $thing are no longer distinct. The changes mine() make to $thing are now visible after the call to mine() returns.
The last piece in the puzzle is Reflection:
function mine(int &$thing) {
$thing++;
}
$a = 1;
$reflector = new ReflectionFunction("mine");
$reflector->invoke($a);
The code above will raise:
Warning: Parameter 1 to mine() expected to be a reference, value given in /usr/src/php-src/refs.php on line 9
This is because ReflectionFunction::invoke and similar reflection functions (ReflectionClass::newInstance) accept their parameters by value and pass them onto the invoked function by value.
But ...
There is still a difference between pass-by-reference semantics, and passing by reference, a dangerous one:
class Foo {
public function qux() {}
}
class Bar {}
function mine(Foo &$foo) {
$foo = new Bar();
}
$foo = new Foo;
mine($foo);
$foo->qux();
Will obviously yield:
PHP Fatal error: Uncaught Error: Call to undefined method Bar::qux() in /usr/src/php-src/refs.php:16
Stack trace:
#0 {main}
thrown in /usr/src/php-src/refs.php on line 16
The declaration of mine() tells lies about the type safety of it's parameter. Type safety is only guaranteed upon entry to the function, the function body is free to break type safety, but it doesn't usually affect the caller when relying on the engines pass by reference semantics for objects.
This is an extremely scary kind of API, that should be avoided.
What is the best method for handling a Void type when it is returned by a function? The suggestions in http://docs.julialang.org/en/release-0.5/manual/faq/#how-does-null-or-nothingness-work-in-julia don't work.
A MWE (must be run from the REPL so Base.source_dir() returns Void):
julia> isempty(Base.source_dir())
ERROR: MethodError: no method matching start(::Void)
Closest candidates are:
start(::SimpleVector) at essentials.jl:170
start(::Base.MethodList) at reflection.jl:258
start(::IntSet) at intset.jl:184
...
in isempty(::Void) at ./iterator.jl:3
in isempty(::Void) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
julia> isdefined(Base.source_dir())
ERROR: TypeError: isdefined: expected Symbol, got Void
julia> typeof(Base.source_dir()) == Void
true
This is on Julia 0.5. The latter option works, but it's a bit ugly.
Void is a singleton -- a type with exactly one instance.
That one instance is Void() also called nothing.
Be aware that nothing === Void()
You can treat it just like any other value.
It is returned by a bunch of functions, like println.
You can check if something has returned nothing -- ie and instance of type Void.
By
julia> println()===nothing
true
For the sake of type-stability,
a method should not return nothing some of the time, and something some of the time.
in those case it should instead return a Nullable,
generally.
I got a strange kind of issue. When I define this table:
function test()
a = Float32[0.3010299957,0.3010299957,-0.3010299957,0.3010299957,0.3010299957]
return a[1]*a[3]
end
It's fine. After call test() i got correct output. But when I define this one, there is an error ErrorException("−3 not defined"):
function test()
a = Float32[2.718281828, −3.141592654 , 1.414213562 , 0.5772156649 , 0.3010299957]
return a[1]*a[2]
end
You're using two different dashes: - (HYPHEN-MINUS) in the first, and − (MINUS SIGN) in the second. Issues like these often happen when you copy text from a formatted source (web page, document, etc.) You want to use HYPHEN-MINUS:
julia> -1 # hyphen-minus
-1
julia> −1 # minus sign
ERROR: syntax: invalid character "−"
This snippet of F# code
let rec reformat = new EventHandler(fun _ _ ->
b.TextChanged.RemoveHandler reformat
b |> ScrollParser.rewrite_contents_of_rtb
b.TextChanged.AddHandler reformat
)
b.TextChanged.AddHandler reformat
results in the following warning:
traynote.fs(62,41): warning FS0040: This and other recursive references to the object(s) being defined will be checked for initialization-soundness at runtime through the use of a delayed reference. This is because you are defining one or more recursive objects, rather than recursive functions. This warning may be suppressed by using '#nowarn "40"' or '--nowarn:40'.
Is there a way in which the code can be rewritten to avoid this warning? Or is there no kosher way of having recursive objects in F#?
Your code is a perfectly fine way to construct a recursive object. The compiler emits a warning, because it cannot guarantee that the reference won't be accessed before it is initialized (which would cause a runtime error). However, if you know that EventHandler does not call the provided lambda function during the construction (it does not), then you can safely ignore the warning.
To give an example where the warning actually shows a problem, you can try the following code:
type Evil(f) =
let n = f()
member x.N = n + 1
let rec e = Evil(fun () ->
printfn "%d" (e:Evil).N; 1)
The Evil class takes a function in a constructor and calls it during the construction. As a result, the recursive reference in the lambda function tries to access e before it is set to a value (and you'll get a runtime error). However, especially when working with event handlers, this is not an issue (and you get the warnning when you're using recursive objects correctly).
If you want to get rid of the warning, you can rewrite the code using explicit ref values and using null, but then you'll be in the same danger of a runtime error, just without the warning and with uglier code:
let foo (evt:IEvent<_, _>) =
let eh = ref null
eh := new EventHandler(fun _ _ ->
evt.RemoveHandler(!eh) )
evt.AddHandler(!eh)