Variable scope in coffeescript for loop? - coffeescript

array = [1,2,3,4]
for num in array
//do something
What is the value of num in the context of the rest of the function? Does num get scoped to the loop?

No, num doesn't get scoped to the loop. As you can see in compiled JS (as #epidemian pointed out) it is current scope variable, so you can access it also in the rest of the function (e.g. rest of the current scope).
But be careful in case of defining function callback inside the loop:
array = [1, 2, 3]
for num in array
setTimeout (() -> console.log num), 1
outputs
3
3
3
To capture current variable inside the callback, you should use do which simply calls the function:
for num in array
do (num) ->
setTimeout (() -> console.log num), 1

Related

How to count how many time a recursive function calls itself without using any vars

I have a function called collatz and I need to find how many times it calls itself, but I'm not allowed to use any vars.
The function works perfectly with vars but i have to use vals.
In case sinanspd's answer does not answer your question, here is some example code.
Let us say your function collatz has a signature as follows:
def collatz(input: Type1): Type2 = ???
The way to count how many times it is called is to either modify collatz itself, or else to use some wrapper function.
def counter(oldCount: Int, fun: Type1 => Type2, input: Type1): (Int, Type2) = {
val output = fun(input)
(oldCount + 1, output)
}
The first time you call counter, call it with oldCount set to 0. Every time you call counter, pass in the old version of count. The first value of your output tuple will be the new count.

Implementing the map function for a Pony array

I have been playing with Pony arrays to understand Pony better, and wanted to write the map function for any arrays.
I am talking about something like the standard map function most languages have nowadays for converting elements of collections, as in Clojure:
(map #(+ 1 %) [1 2 3]) ; => [2 3 4]
But I want it to actually modify the given array, not return a new one.
My current attempt so far runs into many errors due to capabilities:
// array is "iso" so I can give it to another actor and change it
let my_array: Array[U64] iso = [1; 2; 3; 4]
// other actor tries to recover arrays as "box" just to call pairs() on it
let a = recover box my_array end // ERROR: can't recover to this capability
for (i, item) in a.pairs() do
// TODO set item at i to some other mapped value
try my_array.update(i, fun(item))? end
end
Anyone knows how this can be done
Alright, took me a while, but I was able to get things working.
Here's my basic understanding of what's going on (please correct me if I'm wrong)!
The first step was to understand that we need to use aliases to change the capabilities of a variable in Pony.
So, in order to make an iso variable useable as a box, one must alias it by basically, consuming it into another variable:
let a: Array[U64] ref = consume array // array is "iso"
for (i, item) in a.pairs() do
try a.update(i, item + n)? end
end
This works!!
One more problem I had was that I couldn't do much with the resulting Array[U64] ref. Can't pass it to anyone, for example.
So I wrapped the whole thing into a recover block in order to end up with the same array, but as a val (immutable reference to the array) which is more useful as I can send it to other actors:
let result = recover val
let a: Array[U64] ref = consume array
for (i, item) in a.pairs() do
try a.update(i, item + n)? end
end
a
end
Now I can send result to anyone!

How to change the Value of a struct with a function in Matlab?

s= struct('Hello',0,'World',0);
for i = 1: 5
s_vec(i) = s;
end
I have definied a struct in Matlab within a script. Now i want to implement a function witch change the Value of the Parameters.
For example:
function s_struct = set_s (number, prop , value)
s_struct(number).prop = value;
But the function returns a new struct. It does not change my input struct.
Where is my mistake?
I'am not sure to totally understand your question, but if you want to update a parameter in a structure, you have to pass the structure to update as argument of your function.
Moreover, if prop is the parameter, you should use an dynamic allocation using a string in your function :
function [ s_struct ] = set_s( s_struct, number, prop, value )
s_struct(number).(prop) = value;
end
Using it this way :
s_vec = set_s(s_vec, 2, 'Hello', 5);
It will update the second value to the parameter 'Hello' to 5.
Although I think Romain's answer is better practice, you can modify parameters without passing them in and out of a function if you use Nested Functions.
However, I do not like to use them because in complicated large functions it can be quite confusing trying to follow where things are being set and modified.
That being said here is an example of using a nested function to do what you want.
function nestedTest()
%Define your struct
s= struct('Hello',0,'World',0);
for i = 1: 5
s_vec(i) = s;
end
disp('Pre-Nested Call')
disp(s_vec(1))
set_s(1, 'Hello' , 1);%Set the first element of s_vec without passing it in.
disp('Post-Nested Call')
disp(s_vec(1))
function set_s (number, prop , value)
% Nested can modify vars defined in parent
s_vec(number).(prop) = value;
end
end
Output:
Pre-Nested Call
Hello: 0
World: 0
Post-Nested Call
Hello: 1
World: 0
If you want changing data outside your function (aka side effects) use classes instead of structures. Class must be a handle.
classdef MutableStruct < handle
properties
field1;
field2;
end
methods
function this = MutableStruct(val1, val2)
this.field1 = val1;
this.field2 = val2;
end
end
end
There is more information about correct initialization of object arrays:
MATLAB: Construct Object Arrays

loop starting from given index

Considering the following javascript, what's the best way to write this loop in coffee script, given the initial index is greater than 0:
function mixin(target, source, methods) {
for (var i = 2, l = arguments.length; i < l; i++){
var method = arguments[i];
target[method] = source[method].bind(source)
}
}
Automatic code converters suggest use a while loop like this:
mixin = (target, source, methods) ->
i = 2
l = arguments.length
while i < l
method = arguments[i]
target[method] = source[method].bind(source)
i++
Is there a cleaner way to do this?
You'd usually use a splat in CoffeeScript when defining your mixing function:
The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
So you'd say:
mixin = (target, source, methods...) ->
# splat ----------------------^^^
for method in methods
target[method] = source[method].bind(source)
and your problem goes away. The splat in the argument list will collect all the arguments after source into a methods array for you so you won't have to worry about arguments at all; the splat also makes the function's signature nice and obvious.
Use an exclusive range (triple dot, excludes the number at the highest.
for i in [2...arguments.length]
method = arguments[i]
target[method] = source[method].bind(source)
If you have 5 things in your args, this will hit indexes 2, 3 and 4.

Passing anonymous vars in While loop syntax

Im just starting with Coffeescript and running the examples presented in "Programming in CoffeeScript book".
In the while loops section i got intrigued why the call to the times function has to declared as stated bellow.
times = (number_of_times, callback) ->
index = 0
while index++ < number_of_times
callback(index)
return null
times 5, (index) ->
console.log index
I was struggling a bit to read the code and when i've tried:
times (5, (index)) ->
console.log index
It returns an error.
Could you provide some help understanding this code please?
A standard function definition is structured like this:
name = (arg, ...) ->
body
so there's not much to say about your times definition. So let us look at your call to times:
times 5, (index) ->
console.log index
This part:
(index) ->
console.log index
is just another function definition but this one is anonymous. We can rewrite your call using a named function to help clarify things:
f = (index) -> console.log index
times 5, f
And we can fill in the optional parentheses to really spell it out:
f = (index) -> console.log(index)
times(5, f)
Once everything has been broken down you should see that the 5 and (index) in:
times 5, (index) ->
console.log index
have nothing to do with each other so grouping them in parentheses:
times (5, (index)) ->
console.log index
doesn't make sense. If you wanted to add parentheses to that times call to clarify the structure (which is quite useful when the callback function is longer) you need to know two things:
No space between the function name and the opening parenthesis around the arguments. If there is a space then CoffeeScript will think you're using the parentheses to group things within the argument list.
The parentheses need to surround the entire argument list and that includes the callback function's body.
Give that, you'd write:
times(5, (index) ->
console.log index
)
or perhaps:
times(5, (index) -> console.log(index))
With console.log was a non-native function you could even:
times(5, console.log)
but that will give you a TypeError in some browsers so don't go that far.