Coffeescript iteration over array of objects does not compile as expected - coffeescript

I would like to perform an iteration over an array of objects. Instead of writing
for item in items
for k, v in item
# Do Something
I would like to do something similar to this
for k,v of item in items
# Do something
Which based on the compiled output is not supported:
var k, ref, ref1, v, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
ref1 = (ref = indexOf.call(items, item) >= 0) != null ? ref : [];
for (k in ref1) {
v = ref1[k];
# Do something
}
Is there any other comprehension-like operation through which I can perform this shortcut?
EDIT: I can refer to specific keys in the object by doing
for { k1, k2 }, i in items
# Do something
For the sake of the question, assume the keys are dynamic

No you can't. Following coffeescript's golden rule “it's just JavaScript”, consider looking at the source where a for loop gets translated. You will need two Javascript fors and you only can get one from a coffescript for (the for gets inserted in line 2079).
The javascript result you want to have is something like this:
for(_i…;…;…){
var _x = items[_i];
for(k in _x){
var v = _x[k]
…
}}
There are only two ways to get a javascript for loop (apart from the prewritten ones, like in class definitions): On “Range compilation”, which always gives a for(…;…;…) loop (which contructs an array inside a closure that will be returned) and for the for construct.
Your example to access single keys works because you are using some very special case of destructuring assignment. What you would need is a destructuring that extracts key-value pairs and there is none. If you look at the compiled example constructs like this get translated into a=items[i].a so such that there is no iteration. You even can omit the ,i:
for {a} in items
#iterate over the .a values of items
If your #Do something is just one line, you can put your fors on one line, but I personally think it doesn't increase the readability.
console.log [k,v] for k,v of i for i in items

Related

ObservableBuffer giving IndexOutOfBounds in Scala

I am mesmerized. The below code is giving me an indexoutofbound error. But if I were to delete the slashes enabling for(j <- i until tmpArray.length) it would work. I really do not understand why it is happening, and would appreciate an explanation.
for(i <- 0 until tmpArray.length)
{
// for(j <- i until tmpArray.length)
// {
if( date.getValue != null && tmpArray(i).date != date.getValue )
{
tmpArray.remove(i)
}
// }
}
You're modifying the array as you "iterate" over it.
You are actually iterating over the range 0 until tmpArray.length, which is calculated up front. At some point, you reduce the length of the array (or, I assume so, as I can't find remove on the Array class). But it's still going to continue the iteration up to whatever the last index was when you created the range.
When you uncomment the inner for block, you're making it recompute the range for each step of the outer for. And it just so happens that the j range will simply have nothing in it if i >= tmpArray.length. So it inadvertently guards against that failure.
This is very C-style (imperative) code. It looks like all you're trying to do is remove some items from an array. That's what filter is for.
val result = tmpArray.filter { d =>
if(date.getValue != null && d != date.getValue) false else true
}
This creates a new array (result) by passing an anonymous function to tmpArray.filter. It will pass each item in the array to your "predicate", and if it returns true, it'll keep that item in result, otherwise it will omit it.
You should note that I avoided saying "loop". Scala's for isn't for making loops. It's actually syntax sugar for calling methods like foreach and map. Google "scala for comprehensions" for more detail.
If you insist on creating a C-style loop using indexes and a loop variable, you'll want to use while, so that you can check if i < tmpArray.length each time.

Strange behavior in coffeescript for loop

I'm trying to iterate over array in CoffeeScript but there is some kind of strange behavior.
For example look on this code:
kapa = [1]
for i in kapa
console.log 't'
kapa.push 1
I expect that this code produce an infinite sequence of 't' symbols in console. But in reality it prints only one 't'.
What is the logic behind this behavior?
And how can I achieve expected behavior?
Explanation:
elements= [1]
for i in elements
proccess(element)
if someCond
newElement = ...
element.push(newElement) #
I want to achieve behavior when all newElements will be processed
The reason it only prints it out once is because that coffeescript compiles to this JS:
var i, kapa, _i, _len;
kapa = [1];
for (_i = 0, _len = kapa.length; _i < _len; _i++) {
i = kapa[_i];
console.log('t');
kapa.push(1);
}
So it calculates the length of the array in the beginning and doesn't get updated when you kapa.push(1). I would say this is expected behavior and moreover, modifying an array while you are iterating over it sounds like a bad idea. In other languages like Java, you would get an Exception if you tried to do that.
If you really want it to print infinite t and push 1 onto the array every time, you would need an infinite loop:
kapa = [1]
while true
console.log( 't' )
kapa.push( 1 )
(but thats obviously discouraged and I'm not sure why you would want that behavior)
UPDATE
Based on the updated question, you could use the array as a queue-like structure
elements= [1]
while nextElem = elements.shift()
proccess(nextElem)
if someCond
newElement = ...
elements.push(newElement)
Given your added explanation, maybe you are using your array as a queue:
elements= [1]
while elements.length
proccess(elements.shift())
if someCond
newElement = ...
element.push(newElement)
Notice the use of a while loop (whose end condition is evaluated at each iteration), and elements.shift that removes the first element of the queue.

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.

query to detect ISP violations

I am trying to create a special query with NDepend, but cannot figure it out.
Here's what I'd like to query in a more procedural pseudocode:
var list
foreach type t
foreach i = t.attribute that is an interface
var nm = i.numberOfMethods
var mu = numberOfMethods that t actually uses
if mu / nm < 1
list.Add(t)
end foreach
end foreach
return list
It's supposed to list types that don't comply with the Interface Segregation Principle.
Thanks!
So the query you ask can be written this way:
from t in JustMyCode.Types where !t.IsAbstract
from i in t.TypesUsed where i.IsInterface
// Here collect methods of i that are not used
let methodsOfInterfaceUnused = i.Methods.Where(m => !m.IsUsedBy(t))
where methodsOfInterfaceUnused.Count() > 0
select new { t, methodsOfInterfaceUnused }
This query has the peculiarity to match several time a same type, one for each time methodsOfInterfaceUnused is not empty. The result is then nicely presented and understandable:

Iterating over an array in a function

For my Google Docs spreadsheet module, I'd like a function to be able to accept an array of values and iterate over them, adding them to a hash. The spreadsheet submission form wants values in a format like this:
{"entry.0.single": value0,
"entry.1.single": value1,
"entry.2.single": value2}
If the function accepts an array like the following,
[value0, value1, value2]
is it possible to loop over them, keep a running counter, and create a hash? This would be a simple task in other languages. Python suffices for illustration:
hash = dict()
i = 0
for val in values:
hash["entry.%s.single" % i] = val
i += 1
Can that be done in KRL?
Recursive functions are your friend:
a = ['value0', 'value1', 'value2'];
r = function(a, h, n){
top = a.head();
newhash = h.put({'entry.#{n}.single':top});
a.length() > 1 => r(a.tail(), newhash, n+1) | newhash;
};
out = r(a, {}, 0);
out has the value of {'entry.1.single' :'value1','entry.0.single' :'value0','entry.2.single' :'value2'};
A recursive function is needed here because you are doing a structure conversion. If you wanted an array back, you could have used the map() method.
Also, watch your base case writing recursive functions. KNS does enforce a recursion limit.