PureScript FFI function without return value, only side-effects - ffi

How to correctly call/define the foreign function that doesn't return anything. What am I doing wrong?
Renderer.purs:
module Renderer where
import Prelude
import Effect (Effect)
foreign import renderMd :: String -> Effect Unit
Renderer.js:
var md = require('markdown-it')();
exports.renderMd = function(str) {
document.body.append( md.render(str) );
}
Finally calling with:
import React.Basic.DOM as R
import React.Basic.DOM.Events (targetValue)
import React.Basic.Events as Events
R.textarea
{ onChange: Events.handler targetValue $ maybe (pure unit) renderMd
}
Compiles fine, but gives:
Uncaught TypeError: cb(...) is not a function
in the definition of what's probably purescript-react-basic's handler, compiled:
var handler = function (v) {
return function (cb) {
return function ($22) {
return cb(v($22))();
};
};
};

I think the solution is to wrap the result of your FFI function in a zero-argument function:
var md = require('markdown-it')();
exports.renderMd = function(str) {
return function() {
document.body.append( md.render(str) );
}
}
This chapter of the excellent book PureScript by Example mentiones it: https://leanpub.com/purescript/read#leanpub-auto-representing-side-effects
I have to admit, this is less than obvious, but it actually makes sense: wrapping the effectful result in a function delays its evaluation until the function is called, which is needed for controlling side-effects.

Related

Referring to Class functions inside a function when function is intended to be abstract. (Cannot read properties of undefined) [duplicate]

What is the difference between class method, class property which is a function, and class property which is an arrow function? Does the this keyword behave differently in the different variants of the method?
class Greeter {
constructor() {
this.greet();
this.greet2();
this.greet3();
}
greet() {
console.log('greet1', this);
}
greet2 = () => {
console.log('greet2', this);
}
greet3 = function() {
console.log('greet3', this);
}
}
let bla = new Greeter();
This is the resulting JavaScript when transpiled from TypeScript.
var Greeter = /** #class */ (function () {
function Greeter() {
var _this = this;
this.greet2 = function () {
console.log('greet2', _this);
};
this.greet3 = function () {
console.log('greet3', this);
};
this.greet();
this.greet2();
this.greet3();
}
Greeter.prototype.greet = function () {
console.log('greet1', this);
};
return Greeter;
}());
var bla = new Greeter();
My TypeScript version is 3.4.5.
There are differences between all 3 versions. This differences are in 3 areas:
Who is this at runtime
Where the function is assigned
What is the type of this in typescript.
Lets start with where they work just the same. Consider this class, with a class field:
class Greeter {
constructor(private x: string) {
}
greet() {
console.log('greet1', this.x);
}
greet2 = () => {
console.log('greet2', this.x);
}
greet3 = function () {
// this is typed as any
console.log('greet3', this.x);
}
}
let bla = new Greeter(" me");
With this class all 3 function calls will print as expected: 'greet* me' when invoked on bla
bla.greet()
bla.greet2()
bla.greet3()
Who is this at runtime
Arrow functions capture this from the declaration context, so this in greet2 is always guaranteed to be the class instance that created this function. The other versions (the method and function) make no such guarantees.
So in this code not all 3 print the same text:
function call(fn: () => void) {
fn();
}
call(bla.greet) // greet1 undefined
call(bla.greet2) //greet2 me
call(bla.greet3) // greet3 undefined
This is particularly important when passing the function as an event handler to another component.
Where the function is assigned
Class methods (such as greet) are assigned on the prototype, field initializations (such as greet2 and greet3) are assigned in the constructor. This means that greet2 and greet3 will have a larger memory footprint as they require an allocation of a fresh closure each time Greeter is instantiated.
What is the type of this in typescript.
Typescript will type this as an instance of Greeter in both the method (greet) and the arrow function (greet2) but will type this as any in greet3. This will make it an error if you try to use this in greet3 under noImplictAny
When to use them
Use the method syntax if this function will not be passed as an event handler to another component (unless you use bind or something else to ensure this remains the instance of the class)
Use arrow function syntax when your function will be passed around to other components and you need access to this inside the function.
Can't really think of a good use case for this, generally avoid.
this keyword difference:
In the above all three have same this but you will see the difference when you will pass the method to another functions.
class Greeter {
constructor() {
}
greet() {
console.log(this);
}
greet2 = () => {
console.log(this);
}
greet3 = function() {
console.log(this);
}
}
let bla = new Greeter();
function wrapper(f){
f();
}
wrapper(bla.greet) //undefined
wrapper(bla.greet2) //Greeter
wrapper(bla.greet3) //undefined
But there is another difference that the first method is on the prototype of class while other two are not. They are the method of instance of object.
class Greeter {
constructor() {
}
greet() {
console.log('greet1', this);
}
greet2 = () => {
console.log('greet2', this);
}
greet3 = function() {
console.log('greet3', this);
}
}
let bla = new Greeter();
console.log(Object.getOwnPropertyNames(Greeter.prototype))
If I have in the class -> str = "my string"; and in all the 3 methods I can say console.log(this.str) and it outputs the "my string". But I wonder - is this really actually the same thing
No they are not same things. As I mentioned that greet2 and greet3 will not be on Greeter.prototype instead they will be on the instance itself. It mean that if you create 1000 instances of Greeter their will be 1000 different method(greet2 and greet3) stored in memory for 1000 different instances. But there will a single greet method for all the instances.
See the below snippet with two instances of Greeter()

What does "SomeName => {}" mean?

I'm new to react coming from a .Net background and I was trying to create a class, I tried numerous ways of doing so but in this instance I was unable to create a constructor in this variation and came to the conclusion that this maybe isn't a class, I've searched around the web but haven't found any info
Here is an example:
export default ViewTestStuff => {
constructor(){
// errors
}
return (
<div>
<p>Hello</p>
</div>
)
}
so my question is what is the "=> {}" in this example, is this a class? and why can't I create a constructor in it if it is indeed a class
It is a Arrow Function from es6, and has nothing to do with React.js
const add = (a, b) => a+b;
it is just a function.
calling add(2, 3) returns 5
One important thing to remember is, that arrow functions do not have the prototype chain. You also cannot call them with new.
Another thing to notice is, that this is bound to the context where the arrow function is defined.
const obj = {
name: "Lukas",
method: function() {
var self = this;
console.log(this.name === "Lukas");
return [
function() {
console.log(this !== self)
},
() => {
console.log(this === self)
}
];
}
}
const [func, arrow] = obj.method();
func();
arrow();
see the docs
It is an arrow function! A nice feature on ES6, that is already implemented on most modern browsers.
Something => {} Means a function with Something as it's parameter and an empty body. It is similar to:
function (Something) {
}
In your case, it's the same as:
export default function (ViewTestStuff) {
constructor(){
// errors
}
return (
<div>
<p>Hello</p>
</div>
)
}
And it's indeed invalid.
This is not a React thing... arrow functions are new in es6 javascript. More info can be found here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Protractor: functions overloading

I try to extend ElementFinder library. I wondering how I can require different methods with the same names?
I want to make something like:
// spec.js
var ef1 = require('./ef_extend1.js');
var ef2 = require('./ef_extend2.js');
expect(column_resizer.ef1.getWidth()).toEqual(18);
expect(column_resizer.ef2.getWidth()).toEqual(18);
Now I have an error:
TypeError: Cannot read property 'getWidth' of undefined
My required libraries:
// ef_extend1.js
var ElementFinder = $('').constructor;
ElementFinder.prototype.getWidth = function() {
return this.getSize().then(function(size) {
return size.width + 1;
});
};
And the second one:
// ef_extend2.js
var ElementFinder = $('').constructor;
ElementFinder.prototype.getWidth = function() {
return this.getSize().then(function(size) {
return size.width;
});
};
I guess you've used a solution from Protractor issue #1102, but now it can be accomplished a bit easier after PR#1633, because ElementFinder is now exposed in protractor global variable:
protractor.ElementFinder.prototype.getWidth = function () {
return this.getSize().then(function (size) {
return size.width;
});
};
expect($('body').getWidth()).toBe(100);
Update:
As I said in the comment, ElementFinder can only be extended again and again. If you already had a method getWidth, and you extend ElementFinder with one more getWidth implementation, then the first one will be overriden, there should not be any conflict. But you'll have to keep them in strict order depending on when do you want to use appropriate set of methods:
require('./ef_extend1.js');
expect(column_resizer.getWidth()).toEqual(18);
require('./ef_extend2.js');
expect(column_resizer.getWidth()).toEqual(18);
Actually I've came with some alternative approach, but I do not think it will be nice to use, but anyway. Here is a sample module with extension methods:
// ef_extend1.js
// shortcut
var EF = protractor.ElementFinder;
// holds methods you want to add to ElementFinder prototype
var extend = {
getWidth: function () {
return this.getSize().then(function (size) {
return size.width;
});
}
};
// will hold original ElementFinder methods, if they'll get overriden
// to be able to restore them back
var original = {};
// inject desired methods to prototype and also save original methods
function register() {
Object.keys(extend).forEach(function (name) {
original[name] = EF.prototype[name]; // save original method
EF.prototype[name] = extend[name]; // override
});
}
// remove injected methods and return back original ones
// to keep ElementFinder prototype clean after each execution
function unregister() {
Object.keys(original).forEach(function (name) {
if (typeof original[name] === 'undefined') {
// if there was not such a method in original object
// then get rid of meaningless property
delete EF.prototype[name];
} else {
// restore back original method
EF.prototype[name] = original[name];
}
});
original = {};
}
// pass a function, which will be executed with extended ElementFinder
function execute(callback) {
register();
callback();
unregister();
}
module.exports = execute;
And you will use them like that, being able to run protractor commands in "isolated" environments, where each of them has it's own set of methods for ElementFinder:
var ef1 = require('./ef_extend1.js');
var ef2 = require('./ef_extend2.js');
ef1(function () {
expect(column_resizer.getWidth()).toEqual(18);
});
ef2(function () {
expect(column_resizer.getWidth()).toEqual(18);
});
I'm not quire sure about it, maybe I am over-engineering here and there are solutions much easier than that.

this point set to null using afterSelectionChange in ngGrid

I'm writing an application using angular and typescript.
I'm using ng-grid and I have to handle the afterSelectionChange event.
I tried to set the event handler in two ways
this.$scope.settoriGridOptions.afterSelectionChange = this.afterSelectionChange;
where this.afterSelectionChange is a method of the controller class,
and
this.$scope.settoriGridOptions.afterSelectionChange = (... ) => {};
including the code inside, but in both cases the this pointer is incorrect and I cannot access to the services of the controller.
how can I fix this?
after a more tests and reading a few articles I see that the problem is the implicit passing of the this pointer as parameter in the function call.
if I write
$scope.filtroSoluzione = this.filtroSoluzione;
when called the this pointer is set to null, but if I write
$scope.filtroSoluzione = () => { return this.filtroSoluzione() };
or
$scope.filtroSoluzione = () => { .. inline code ... };
the this pointer I set correctly.
How can I have a more consistent behavior? I don't like to write always the code inside because this makes the class harder to read and navigate
thanks,
Luca
Thanks for the extra information in your edits, I now see the problem.
class foo {
public afterSelectionChange = () => {
console.log(this);
}
}
When you declare your function like I did above, your this is the instance instead of what you are seeing know because it captures the this variable. It comes with a cost though, because now it creates a new afterSelectionChange function for every instance of your class. In this case I think it is still what you want though.
var foo = (function () {
function foo() {
var _this = this;
this.afterSelectionChange = function () {
console.log(_this);
};
}
foo.prototype.baz = function () {
console.log(this);
};
return foo;
})();
In the above code-gen you can see the difference when declaring the function with name = () => {} and the normal way.
Another solutions might be this:
this.$scope.settoriGridOptions.afterSelectionChange = this.afterSelectionChange.bind(this);
But I don't find that really nice either... (this should work with the normal public afterSelectionChange() {} declaration you are used to.

Can I alias a key in an object literal? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Self-references in object literal declarations
I have an object literal which is used as a configuration element and is looked up for keys.
customRendering:{
key1: func(){....},
key2: func(){....}
}
I have a situation where key2 and key3 can use the same function. Is there a way to assign the same function to both key2 and key3 without having to declare the function outside the object literal and without having to declare an extra key?
I was hoping I could do something like:
key2: key3: func(){....}
A safe way:
I don't know what I was thinking earlier. If you're fine with using a more verbose "literal" you can instantiate a custom function:
o = new function () {
this.foo = function () { console.log('works'); };
this.bar = this.foo;
};
This is a dirty nasty hack:
you could use a temporary variable to store the reference to the function while setting the object. Be careful to use a closure and to call var before using it so that you don't pollute the global namespace:
(function () {
var o, baz;
o = {
foo: baz = function () {console.log('works')},
bar: baz
}
//more code
}());
The reason I'm calling this a dirty nasty hack is that it makes the code less readable, it's harder to tell examining this code (especially if the object literal declaration was longer) where baz was set.
Better to just write the alias outside the object literal so that it's explicitly visible that it is an alias.
Note: the named function format doesn't work:
o = { //THIS WON'T WORK
foo: function baz() {/* code */},
bar: baz
}
There's no way within an object literal to define an alias using a shared reference.
You can use an aliasing function, but it wont be an identical reference:
o = {
foo: function...
bar: function () { return this.foo() } //even better if you use `apply` or `call`
}
The typical way to share a reference is after the object literal, which sounds like what you wanted to avoid:
o = {
foo: function...
}
o.bar = o.foo;
Alternatively as you pointed out in your question (and for completeness) you could define the function outside of the object literal:
func = function () {/* code */};
o = {
foo: func,
bar: func
}
In response to #Peter about returning an object from a function
Using a self-executing anonymous function is another way of instantiating an object inline, and would make this entire question moot:
o = (function () {
var o = {
foo: function () {/*code*/}
}
o.bar = o.foo;
return o;
}());
Or like this:
var o = (function () {
var shared = function() { console.log("shared") };
return {
foo: shared,
bar: shared
}
}());
without having to declare the function outside the object literal
I think this part makes it impossible. However, while I use JavaScript all the time, I am not a professional JS ninja, so perhaps I am wrong.
Code for how I would do this (although it seems you already know you can do this, I thought it might be best to say it anyway):
customRendering = {};
customRendering.key1 = func(){....};
customRendering.key2 = customRendering.key1;
Define the function aside from the object:
var func = function() { ... };
...
customRendering: {
key1: func,
key2: func
}
Sorry I understood your question incorrectly.
Here is a possible solution:
var obj = {
func1: function() {},
func2: obj.func1
}

Resources