Coffeescript - reassign upper-scope variable using a function - coffeescript

fun=->
views = []
views = 123
fun()
console.log views
Which compiles to
var fun, views;
fun = function() {
var views;
return views = [];
};
views = 123;
fun();
console.log(views);
And logs 123 whereas I want it to return [].
Declaring views before fun would produce required result, but my code style requires that I first declare all functions and then assign variables.
What can be done in this case? Particularly I want coffeescript to not produce var views; in javascript inside fun.

Another possibility - while a bit more compex - would be to use a class and bind the function and the fun function to the class scope.
class muchFun
views: 123
fun: =>
#views = []
return
soMuchFun = new muchFun()
console.log( soMuchFun.views )
soMuchFun.fun()
console.log( soMuchFun.views )

If you want fun to know about the outer views then you have to define views before fun:
views = 123
fun = ->
views = []

Related

Why does this function application generate a runtime error in purescript?

I have the following PureScript snippets; note parseXMLFromString is partially applied:
parseXMLFromString ∷ String → DOMParser → Effect Document
parseXMLFromString s d =
parseFromString "application/xml" s d
parseNoteDoc :: DOMParser -> Effect Document
parseNoteDoc = parseXMLFromString TD.noteXml
note <- parseNoteDoc domParser
The following code is generated:
// Generated by purs version 0.12.4
"use strict";
var Effect_Console = require("../Effect.Console/index.js");
var Test_Data = require("../Test.Data/index.js");
var Web_DOM_DOMParser = require("../Web.DOM.DOMParser/index.js");
var parseNoteDoc = Web_DOM_DOMParser.parseXMLFromString(Test_Data.noteXml);
var main = function __do() {
var v = Web_DOM_DOMParser.makeDOMParser();
var v1 = parseNoteDoc(v)();
return Effect_Console.log("TODO: You should add some tests.")();
};
module.exports = {
parseNoteDoc: parseNoteDoc,
main: main
};
The line var v1 = parseNoteDoc(v)(); gives the error TypeError: parseNoteDoc(...) is not a function.
I'm not sure where the extra () is coming from on parseNoteDoc but that is the issue. When I manually remove the () in the generated source, it works works as expected.
Update: Added the code to reproduce this on this branch. After the usual formalities, npm run testbrowser and open dist/index.html in a browser.
TL;DR: your FFI code is incorrect, you need to add an extra function().
Longer explanation:
The extra empty parens come from Effect.
This is how effectful computations are modeled in PureScript: an effectful computation is not a value, but a "promise" of a value that you can evaluate and get the value as a result. A "promise" of a value may be modeled as a function that returns a value, and this is exactly how it's modeled in PureScript.
For example, this:
a :: Effect Unit
is compiled to JavaScript as:
function a() { return {}; }
and similarly, this:
f :: String -> Effect Unit
is compiled to JavaScript as:
function f(s) { return function() { return {}; } }
So it takes a string as a parameter, and then returns Effect Unit, which is itself a parameterless function in JS.
In your FFI module, however, you are defining parseFromString as:
exports.parseFromString = function (documentType) {
return function (sourceString) {
return function (domParser) {
return domParser.parseFromString(sourceString, documentType);
};
};
};
Which would be equivalent to parseFromString :: String -> String -> DOMParser -> Document - i.e. it takes three parameters, one by one, and returns a parsed document.
But on the PureScript side you're defining it as parseFromString :: String -> String -> DOMParser -> Effect Document - which means that it should take three parameters, one by one, and then return an Effect Document - which should be, as described above, a parameterless function. And it is exactly this extra parameterless call that fails when you try to evaluate that Effect Unit, which in reality is not an Effect at all, but a Document.
So, in order to fix your FFI, you just need to insert an extra parameterless function, which will model the returned Effect:
exports.parseFromString = function (documentType) {
return function (sourceString) {
return function (domParser) {
return function() {
return domParser.parseFromString(sourceString, documentType);
}
};
};
};
(it is interesting to note that makeDOMParser :: Effect DOMParser is correctly modeled in your FFI module as a parameterless function)
But there is a better way
These pyramids of nested functions in JS do look quite ugly, you have to agree. So it's no surprise that there is an app for that - EffectFn1, runEffectFn1, and friends. These are wrappers that "translate" JavaScript-style functions (i.e. taking all parameters at once) into PureScript-style curried effectful functions (i.e. taking parameters one by one and returning effects).
You can declare your JS side as a normal JS function, then import it into PureScript as EffectFnX, and call it using runEffectFnX where needed:
// JavaScript:
exports.parseFromString = function (documentType, sourceString, domParser) {
return domParser.parseFromString(sourceString, documentType);
};
-- PureScript:
foreign import parseFromString ∷ EffectFn3 String String DOMParser Document
parseHTMLFromString ∷ String → DOMParser → Effect Document
parseHTMLFromString s d =
runEffectFn3 parseFromString "text/html" s d
P.S. People who purchased EffectFn1 also liked Fn1 and friends - same thing, but for pure (non-effectful) functions.

Define a static variable in a function like c++

In my function, can I have a variable that
Retains its value between function calls.
Is only visible inside that function
Is unique for each thread i.e. if I'm calling the function from two threads then there are two variables that are static with regard to each thread.
Why I want that:
I have a function in which I fill in a list and return that list. The problem is that if I declare a variable normally, then I will have to allocate memory for it every time I call the function. I want to avoid that and allocate only once then every time I call the function it would fill in that variable with the proper values then return it.
I can do the following inside a class:
class MyClass {
val __readLineTemp = mutable.IndexedSeq.fill[Int](5)(-1)
def readLine() = {
var i = 0
while (i < __readLineTemp.length)
{
__readLineTemp(i) = Random.nextInt()
i += 1
}
__readLineTemp
}
}
My problems with this approach is that it doesn't satisfy the points 2 and 3 namely visibility only inside the method and being unique for each thread. However, for point 3 I can simply make each thread initialise its own object of MyClass.
I understand there is probably no way of achieving exactly what I want, but sometimes people come up with clever ideas to overcome this, specially that Scala seems quite deep and there is a lot of tricks you can do
You can use a closure to satisfy 1 and 2:
def foo = {
var a = 5
() => {
a = a + 1
a
}
}
i.e. create a closure that will contain the static variable (in your case, this is __readLineTemp) and return a function that's the only thing with access to the variable.
Then use it like this to satisfy the thread requirement:
val t1 = new Thread(new Runnable {
def run = {
val f = new DynamicVariable(foo)
println(f.value())
println(f.value())
}
})

Extending list pseudo methods in Specman

Is there a way I could extend the given pseudo methods for lists in e, to add some specific implementation?
Thanks
"pseudo method" is not really a method, it just looks as if it was. So it cannot be extended with "is also/only/etc".
but you can define any "pseudo method" of your own, using macro.
for example - pseudo method that adds only even items -
(do note the \ before the () )
define <my_pseudo_method'action> "<input1'exp>.add_if_even\(<input2'num>\)"
as computed {
result = append("if ", <input2'num>, " %2 == 0 then { ", <input1'exp>, ".add(", <input2'num>, ")};");
}
then can be called from another file -
extend sys {
run() is also {
var my_list : list of int;
for i from 0 to 10 {
my_list.add_if_even(i);
};
print my_list;
};
};
Using a macro, you can even "override" an existing pseudo-method. For example, let's say you want to modify add() so that it will add an element to the list only if it is not already in the list. (In other words, you want to keep all elements in the list unique).
You can do something like this:
define <my_add'action> "<list'exp>.add\(<exp>\)" as {
if not <list'exp>.has(it == <exp>) then {
var new_size<?>: int = <list'exp>.size() + 1;
<list'exp>.resize(new_size<?>, TRUE, <exp>, TRUE);
};
};
Note that I use another pseudo-method here - resize() - to implement the actual addition of the new element to the list. If I tried to use the add() pseudo-method itself, it wouldn't work, and would lead to an infinite recursion. This is because add() used inside the macro would again call the macro itself, and not the pre-defined pseudo-method being overridden.
You can also use templates to add/modify list pseudo-methods. e.g.
<'
template struct MyList of (<T1'type>) {
items: list of <T1'type>;
keep soft items.size()==10;
pop_index(i:int):<T1'type> is {
result = items[i];
items.delete(i);
};
};
extend sys {
list1: MyList of (byte);
// somehwere
var foo:= list1.pop_index(3);
};
'>

Coffeescript class shares properties

I've detected a very weird behavior in coffeescript.
class Foo
list: []
add: (val)->
#list.push(val)
x = new Foo()
x.add(1)
console.log(x.list.length) // 1
y = new Foo()
y.add(1)
console.log(y.list.length) // 2
So as you see the #list property got shared between the two class instances in a strange way.
I've never faced similar issue before, in coffeescript.
Convert it to JavaScript:
var Foo, x, y;
Foo = (function() {
function Foo() {}
Foo.prototype.list = [];
Foo.prototype.add = function(val) {
return this.list.push(val);
};
return Foo;
})();
As you can see, Foo.prototype.list is a property of the prototype, not of an instance of your class. There's only one array and it will be shared across all of the instances of your class.
To make list an instance variable, add it to the constructor:
class Foo
constructor: ->
#list = []
add: (val)->
#list.push(val)

#function in CoffeeScript does not work as advertised

Rails 3.2.8. In converting some of my JS functions over to CoffeeScript, I have come across several questions that say declaring a function like so:
#foo = (bar) ->
puts foo in the global namespace. But it doesn't, because my function calls elsewhere in the application, especially ones that are in .js.erb files.
Here's what does work:
foo = (bar) ->
window.foo = foo
With that, all my calls in .js.erb files work fine.
What is the reason that the #foo = notation doesn't work as I am expecting it to? That would be a lot easier than having to remember to add an extra line to expose the function to the global namespace.
#foo translates to this.foo
foo translates to var foo
There is a big difference between the two of those.
For example:
bar = (baz) ->
#bar = 5
lemon = #bar + baz
#foo = (bar) ->
lemon
return #
Bar = new bar(12)
Translates to:
var Bar, bar;
bar = function(baz) {
var lemon;
this.bar = 5;
lemon = this.bar + baz;
this.foo = function(bar) {
return lemon;
};
return this;
};
Bar = new bar(12);
See fiddle demo of generated code: http://jsfiddle.net/maniator/rXWw2/
Here is a link showing you the CoffeeScript and it's generated code
I just wanted to add something that seems important to understanding why the initial
#foo = () -> "abc"
doesn't add to the global window object.
Coffeescript wraps - once compiled, it wraps all contents of every .coffee-file into a surrounding anonymous function that is immediately executed.
Thusly, and explicitely for that reason, the global namespace is not polluted, thereby implicitely protecting the dev from creating "evil" globals.
So, your foo becomes a member function of an anonymous wrapper function - how seriously useless gg ...
I guess what you want anyway is your global config object or something, to which you simply add your definitions --- you surely didn't mean to really create globals just for quick and easy access now, did you?? :)