I am trying to implement a deep learning model in the browser and this requires porting some custom layers, one of them is an instant layer normalization. Below the piece of code that is supposed to work but it's a bit old.
I get this error:
Uncaught (in promise) ReferenceError: initializer is not defined
at InstantLayerNormalization.build
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs/dist/tf.min.js"> </script>
<script>
class InstantLayerNormalization extends tf.layers.Layer
{
static className = 'InstantLayerNormalization';
epsilon = 1e-7
gamma;
beta;
constructor(config)
{
super(config);
}
getConfig()
{
const config = super.getConfig();
return config;
}
build(input_shape)
{
let shape = tf.tensor(input_shape);
// initialize gamma
self.gamma = self.add_weight(shape=shape,
initializer='ones',
trainable=true,
name='gamma')
// initialize beta
self.beta = self.add_weight(shape=shape,
initializer='zeros',
trainable=true,
name='beta')
}
call(inputs){
mean = tf.math.reduce_mean(inputs, axis=[-1], keepdims=True)
variance = tf.math.reduce_mean(tf.math.square(inputs - mean), axis=[-1], keepdims=True)
std = tf.math.sqrt(variance + self.epsilon)
outputs = (inputs - mean) / std
outputs = outputs * self.gamma
outputs = outputs + self.beta
return outputs
}
static get className() {
console.log(className);
return className;
}
}
tf.serialization.registerClass(InstantLayerNormalization);
</script>
The methods of the inherited class tf.layers.Layer are not called properly.
self in python is this in js
add_weight is rather addWeight
Here is the signature of the addWeight method. Please notice that in js there is not the format variable=value for function arguments destructuring assignment
// instead of this
self.gamma = self.add_weight(shape=shape, initializer='ones', trainable=true, name='gamma')
// it should rather be
this.gamma = this.addWeight('gamma', shape, undefined, 'ones', undefined, true)
Related
I'm trying to make a non-component class in ReactJS. Most tutorials I've followed on JavaScript show that when you're making a class, you can create properties simply by specifying them with this.[name].
Something really doesn't like this, and it throws me a no-undef error for my properties.
Here is the code in question:
class MicroBitConnection {
constructor(device) {
this.device = device;
this.connectDAP();
}
connectDAP() {
this.transport = new DAPjs.WebUSB(device);
this.dap = new DAPjs.DAPLink(transport);
}
}
Right now I don't even instantiate the class anywhere, it gives me this error right off the bat:
Line 11:43: 'device' is not defined no-undef
Line 12:44: 'transport' is not defined no-undef
It doesn't seem like a linting problem, because even with this warning off using /* eslint no-undef: 0 */ // --> OFF at the top of the file, actually running the code with the class instantiated somewhere gives the same error:
Error: ReferenceError: device is not defined
In your connectDAP method you are referencing undefined variables device and transport. You probably want to use the properties defined on the instance this:
class MicroBitConnection {
constructor(device) {
this.device = device;
this.connectDAP();
}
connectDAP() {
this.transport = new DAPjs.WebUSB(this.device);
this.dap = new DAPjs.DAPLink(this.transport);
}
}
Please also note that this is not automatically bound to the instance, e.g. when using an instance method as an event handler. To make sure it's bound to the instance in all circumstances, call Function.prototype.bind in the constructor:
this.connectDAP = this.connectDAP.bind(this);
If you want to omit this you need to locally declare the variables, which can easily be done using destructuring:
class MicroBitConnection {
constructor(device) {
this.device = device;
this.connectDAP();
}
connectDAP() {
const { device } = this;
this.transport = new DAPjs.WebUSB(device);
const { transport } = this;
this.dap = new DAPjs.DAPLink(transport);
}
}
A third alternative (not recommended) is using with statement:
class MicroBitConnection {
constructor(device) {
this.device = device;
this.transport = null;
this.dap = null;
this.connectDAP();
}
connectDAP() {
with (this) {
transport = new DAPjs.WebUSB(device);
dap = new DAPjs.DAPLink(transport);
}
}
}
I'm not sure this last version does what you expect, just listing it for completeness' sake and to make you aware of the existence of the with statement.
I'm trying to import an object into another JS file, and I keep getting this error, Uncaught ReferenceError: Cannot access 'stocks' before initialization. I've declared stocks, and I've imported it correctly, so I can't see what I did wrong. Any help is much appreciated. Thanks.
In the stocks file:
export const stocks = {
megaCorp: {
name: 'Mega Corporation',
value: decideStockValue(),
portIn: 0,
document: "mega"
},
lunaBake: {
name: "Luna Baking",
value: decideStockValue(),
portIn: 1,
document: "luna"
},
}
And in the user file :
import { stocks } from "./stocks.js";
export let user = {
money: 2000,
portfolio: [0, 0, 0, 0]
}
function getValue () {
let value = user.money;
let cannon = stocks.cannonRock.value * user.portfolio[0];
let alpha = stocks.alphaComp.value * user.portfolio[1];
let luna = stocks.lunaBake.value * user.portfolio[2];
let mega = stocks.megaCorp.value * user.portfolio[3];
value += cannon;
value += alpha;
value += luna;
value += mega;
return value;
}
user.value = getValue();
Again Looking at the code it seems syntactically fine, so this is not an answer but i rather want to share a snippet of code to see how it behaves.
The error you shared Uncaught ReferenceError: Cannot access 'variable_name' before initialization is thrown when a lexical variable was accessed before it was initialized ( what is known as a temporal dead zone error), however in the code you share there is nothing that should throw this error.
for example this code will throw this error
const x = 3
function a(){
console.log(x)
const x = 5;
}
a()
Assuming indeed that the error originated from the user file, then the following code might solve it. In the code u had getValue was a function expression that should be hoisted ( which again should be fine), but it could be that a bundler you are using is misbehaving.
import { stocks } from "./stocks.js";
const getValue = (stocks, money, portfolio) => {
let value = money;
let cannon = stocks.cannonRock.value * portfolio[0];
let alpha = stocks.alphaComp.value * portfolio[1];
let luna = stocks.lunaBake.value * portfolio[2];
let mega = stocks.megaCorp.value * portfolio[3];
value += cannon;
value += alpha;
value += luna;
value += mega;
return value;
};
const money = 2000;
const portfolio = [0, 0, 0, 0];
export const user = {
money,
portfolio,
value: getValue(stocks, money, portfolio),
};
After debugging for a little, I closed the server and opened it again. This time, it worked fine. I'm still not sure why the original error happened, but now it's working great. Thanks for everyone's help
This is a classic example of cycle overloading of certain dependancy (c) Sergei Vohmianin
The easiest thing you can do is to move that object into it's separate module just to omit cycle like app => method => app.
I was getting this error ReferenceError: Cannot access 'process' before initialization
when I attempted to do this:
require("dotenv-safe").config();
console.log(process.env);
const DATABASE_URI = process.env.DATABASE_URI;
Turns out, the problem was I was mistakenly declaring process further down in the same file like this:
const process = require("process");
This require was unnecessary since it's available in Node's global context. Deleting that line fixed the problem.
I have this simple code written in python to create a small
Cards game and I want to make the same using typescript but I'm
facing a big problem with 'this' in my main class in Typescript
this is the original python class:
class deck:
card_type=['Hearts ','Diamonds','Spades','Clubs']
card_rank=[2,3,4,5,6,7,8,9,10,'A','J','Q','K']
full_deck=[]
def build_deck(self):
single={}
for card in self.card_type:
for n in self.card_rank:
single={n: card}
self.full_deck.append(single)
shuffle(self.full_deck)
def reshuffle (self):
print('Re-shuffling again!')
shuffle(self.full_deck)
def choose_card(self):
chosen=choice(self.full_deck)
the_index= self.full_deck.index(chosen)
self.full_deck.pop(the_index)
return chosen
def pick_hand(self, number_of_cards):
hand=[]
new_card={}
for i in range(number_of_cards):
new_card = self.choose_card()
hand.append(new_card)
return hand
And in my main game file I do something like this:
from classes import deck
deck1= deck()
deck1.build_deck()
my_hand=deck1.pick_hand(3)
compu_hand=deck1.pick_hand(3)
But when I try to create a similar class in type script I wrote the following:
export class deck {
single_card: {
cType: string;
cNumber: any;
};
fullDeck: any[] = [];
card_type=['Hearts ','Diamonds','Spades','Clubs'];
card_rank=[2,3,4,5,6,7,8,9,10,'A','J','Q','K'];
shuffle() {
let counter = this.fullDeck.length;
// While there are elements in the array
while (counter > 0) {
// Pick a random index
let index = Math.floor(Math.random() * counter);
// Decrease counter by 1
counter--;
// And swap the last element with it
let temp = this.fullDeck[counter];
this.fullDeck[counter] = this.fullDeck[index];
this.fullDeck[index] = temp;
}
// return this.fullDeck;
}
buildDeck (){
for (let t in this.card_type) {
for ( let n in this.card_rank) {
this.single_card.cType = this.card_type[t];
this.single_card.cNumber = this.card_rank[n];
this.fullDeck.push(this.single_card);
console.log(this.single_card);
}
}
// this.shuffle()
}
}
When I try to use the class from the main 'ts' file like so:
import {deck} from './myclasses'
$(document).ready (function(){
let deck1= new deck;
deck1.buildDeck();
});
The console.log call returns the same error :
jQuery.Deferred exception: Cannot set property 'cType' of undefined
TypeError: Cannot set property 'cType' of undefined
at deck.buildDeck (file:///run/media/Work/HTML_Porjects/Game_TS/built/myclasses.js:132:44)
How is it undefined?
What do I need to do to make the Typescript code work like the Python code?
Thanks in advance ...
The error simply states that single_card is undefined, which it is:
class deck {
single_card: {
cType: string;
cNumber: any;
};
// …
}
This will declare the property single_card on the TypeScript class, so that the compiler will accept when you refer to the single_card property of an object of that type (e.g. when doing this.single_card). However, doing so will not actually assign an object of that type to the object. So for the compiled JavaScript (where type information is removed), that property does not exist since you never assign to it. You can easily verify that by looking at the compiled JavaScript there.
So what you would need to do first is assign something to single_card just like you did in the Python version:
this.single_card = {}
However, if you actually look at your Python version, single_card is not a member of the object and it actually doesn’t make any sense for it to be. You are using that to construct the card object you are then adding to the fullDeck array. In Python, it is a local variable, so you should make it a local variable in the TypeScript version too:
buildDeck() {
for (const t of this.card_type) {
for (const n of this.card_rank) {
const single_card = {
cType: this.card_type[t],
cNumber: this.card_rank[n]
};
this.fullDeck.push(single_card);
}
}
}
Btw. you also want to use a for…of loop there instead of for…in.
You should also think about making fullDeck properly typed. Right now it is an array of any, so it can store any object. But what you want to do is actually just keep objects in there that look the way single_card looks. So consider declaring a type for this:
interface SingleCard {
cType: string;
cNumber: any;
}
Then, you can properly type fullDeck:
fullDeck: SingleCard[] = [];
I've become hopelessly addicted to Screeps recently, and I refactored some code to make a task-based implementation. Tasks are things like "walk to and then harvest until you are at full capacity" and are based off of a single base task template written as an ES6-style class. Creeps can be assigned tasks through a wrapper (tasks.js) that loads the relevant task file and returns a new task instance.
Today I ran into a strange bug that makes me think I don't fully understand Javascript's inheritance model. Below is the relevant code:
Task.js: (base task class)
class Task {
constructor(taskName) {
// Parameters for the task
this.name = taskName; // name of task
this.quiet = false; // suppress console logging if true
this.creep = [creep assigned to this task]
this.target = [thing task operates on, e.g. "repair this wall"]
...
}
...
// Execute this task each tick. Returns nothing unless work is done.
step() {
...
if (creep.pos.inRangeTo(target, this.targetRange)) {
var workResult = this.work();
console.log(this.quiet) // < returns false, should be true?
if (workResult != OK && this.quiet == false) {
creep.log("Error: " + workResult); // < is printed when run
}
return workResult;
} [else move to target]
}
...
// Task to perform when at the target
work() {
// overwrite this in child class
}
}
module.exports = Task;
task_harvest.js: (harvesting task)
var Task = require('Task');
class taskHarvest extends Task {
constructor() {
super('harvest');
// no mention of this.quiet here
}
...
work() {
console.log("harvest:" + this.quiet);
return this.creep.harvest(this.target);
}
}
module.exports = taskHarvest;
tasks.js: (wrapper to generate a new task instance via a function call)
module.exports = function (taskName) {
var TaskClass = require('task_' + taskName); // all tasks follow this naming pattern
var taskInstance = new TaskClass;
return taskInstance;
};
harvester.js: (behavior model for a harvester creep)
var tasks = require('tasks');
var roleHarvester = {
...
harvest: function (creep) {
var target = Game.getObjectById(creep.memory.assignment);
var taskHarvest = tasks('harvest');
taskHarvest.quiet = true; // < this task shouldn't print anything
creep.assign(taskHarvest, target); // assigns to creep.task
return OK;
},
...
run: function (creep) { // executed every tick
// execute the task
creep.task.step();
},
...
}
When I assign a creep to harvest from a source, I create a new task from task_harvest.js, set its quiet property to be true, and bind it and its target to the creep. Once the creep has a task it is instructed to run it until it becomes invalid (code not included above). The creep executes the task fine, but it still logs everything to the console.
I would think that in harvester.js, when I set taskHarvest.quiet = true;, the behavior imported from Task.js would see this.quiet as true. However, it seems as though that is not the case. In roleHarvester, running console.log(creep.task.quiet) returns true, but in Task, running console.log(this.quiet) when the creep is executing the assigned task gives false.
I could add quiet into the constructor as an optional parameter, but that's convoluted and I want to know why what I'm doing isn't working.
Nevermind, it actually wasn't an inheritance problem; it was a problem caused by the game mechanics: taskHarvest.quiet wasn't getting deleted each tick. Screeps only allows you to store JSON-serializable objects in memory, so I store the task settings in memory and reconstruct the task object each tick:
Object.defineProperty(Creep.prototype, 'task', {
get: function () { // provide new task object recreated from literals stored in creep.memory.task
if (this.memory.task != null) {
var task = tasks(this.memory.task.name);
task.creepName = this.memory.task.creepName;
task.targetID = this.memory.task.targetID;
task.data = this.memory.task.data; // < task.quiet is now task.data.quiet
return task;
} else {
return null;
}
},
set: function(newTask) {
if (newTask != null) {
this.log("use Creep.assign() to assign tasks. Creep.task = ___ should only be used to null a task.");
} else {
this.memory.task = newTask;
}
}
});
taskHarvest.quiet wasn't getting stored in memory, so it wouldn't persist past the first tick of the task. I now store all instance-level adjustable parameters in a task.data object, so task.quiet is now task.data.quiet. This fixed the problem; sorry for producing any confusion!
all. I have kind of a doozy of a problem, that could be solved really simply, if I just wanted to duplicate the code. I mean, really, it's a small part of a project that I'm doing just to see if I can, more than anything else, but it is bothering me since I've thought it up.
The Project
For fun, I've decided to take someone's ActionScript 3, text-based game engine and convert it to TypeScript and ultimately JavaScript using PixiJS.
The thing is, there are still 20213 errors to be fixed running tsc, so I could just leave this to a later date. But I was working on the Button class, which they defined as a subclass of MovieClip. That's fine; I just responded by reading up on PIXI buttons, and they seem fairly straightforward. Just, in the button's constructor, add something akin to the following lines:
export class Button extends PIXI.Sprite {
private _callback : Function;
private _height : number;
private _width : number;
public get callback() : Function { return this._callback; }
public set callback(fn : Function) {this._callback = fn; }
public get height() : number { return this._height; }
public set height(h : number) {this._height = h; }
public get width() : number {return this._width; }
public set width(w : number) {this._width = w; }
public constructor(width = 180, height = 90, callback: Function = null){
super(new PIXI.Texture(new PIXI.BaseTexture(GLOBAL.BTN_BACK, PIXI.SCALE_MODES.NEAREST)));
this.callback = callback;
this.width = width;
this.height = height;
this.buttonMode = true;
this.interactive = true;
this.anchor.set(0.5);
this.on('mousedown', this.callback)
.on('touchstart', this.callback);
}
}
That's a bit of a simplified version, and the version I did on Codepen uses a Container and a private _sprite field instead (as well as a ColorMatrixFilter that doesn't work too well on the black icons I picked out, but that's not really important for this question), but that's roughly the gist of how it's done.
The Problem
The problem is that, in the codepen, I'd like to do the following:
// assign `this.callback` to each of the following events:
let that = this;
['click','mousedown','touchstart'].map(evt => that.on(evt, that.callback});
with a simple call being passed in their constructors elsewhere:
for (let n = 0; n < 5; ++n){
btnArray.push(new Button(16, 16, () => console.info('You pushed button %d', n)));
}
but I'm not getting anything from them, even in the Chrome Console. I even logged that ColorMatrixFilter I mentioned earlier, to see if it was console.info that was wrong. Nope. So now, I'm confused on that. I was hoping to be able to just make a GLOBAL (a legacy static object from the AS source) key to iterate through for the events, but it looks like that's not happening.
The Questions
Is what I'm trying to do feasible, if odd? Is it blocked by a security feature (for which I'd be grateful)? If not, what am I doing wrong?
Should I even worry about setting all these different event handlers, or is just listening to click enough?
When an arrow function like your event map is executed the this context is not set, so any code that references this is going to get the current value, including any functions your map calls.
Replace your event map with the following:
['click','mousedown','touchstart'].map(function(evt) { that.on(evt, that.callback} } );
A demonstration:
function Named(x) {
this.name = x;
}
var foo = new Named("foo");
var bar = new Named("bar");
var showFunc = function show() {
// this is context dependant
console.log(this.name);
}
var showArrow;
// this is the window
showArrow = () => console.log(this.name);
var fooShowArrow;
(function() {
// this is foo
that = this;
fooShowArrow = () => console.log(that.name);
}).apply(foo);
var example = function(func) {
// For the demo, at this point, this will always be bar
func.apply(this, [ "arbitrary value" ]);
}
// explicitly set the current "this" to bar for the execution of these functions
example.apply(bar, [showFunc]); // works
example.apply(bar, [showArrow]); // fails, this is still the window
example.apply(bar, [fooShowArrow]); // fails, this is still foo