Counting length of repetition in macro - macros

I'm trying to implement a macro to allow MATLAB-esque matrix creation. I've got a basic working macro but I still have a long way to go.
I want to be able to enforce the right structure (same number of elements in each row) but I'm not sure how to do this within the macro. I think I want to enforce that each internal repetition has the same length - is this something I can do?
Here is my code so far:
pub struct Matrix<T> {
pub cols: usize,
pub rows: usize,
pub data: Vec<T>
}
macro_rules! mat {
( $($( $x:expr ),*);* ) => {
{
let mut vec = Vec::new();
let mut rows = 0;
$(
$(
vec.push($x);
)*
rows += 1;
)*
Matrix { cols : vec.len()/rows, rows: rows, data: vec}
}
};
}
It works but as you can see isn't very safe. It has no restrictions on the structure.
I want to do a lot more with this macro but I think this is a good start!
Update:
Here is some playground code for a crappy implementation I worked out. If anyone has any better suggestions please let me know! Otherwise I'll close this myself.

macro_rules! count {
() => (0usize);
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
}
macro_rules! mat {
( $( $x:expr ),* ) => { {
let vec = vec![$($x),*];
Matrix { cols : vec.len(), rows: 1, data: vec }
} };
( $( $x0:expr ),* ; $($( $x:expr ),*);* ) => { {
let mut _assert_width0 = [(); count!($($x0)*)];
let mut vec = Vec::new();
let rows = 1usize;
let cols = count!($($x0)*);
$( vec.push($x0); )*
$(
let rows = rows + 1usize;
let _assert_width = [(); count!($($x)*)];
_assert_width0 = _assert_width;
$( vec.push($x); )*
)*
Matrix { cols : cols, rows: rows, data: vec }
} }
}
playground
The count! macro expands to a constant expression that represents the number of arguments it got as input. It's just a helper for the mat! macro. If you need to count a lot of items and the compiler can't cope with it, see the Counting chapter in The Little Book of Rust Macros, which has more complex macros for counting.
My version of the macro uses dummy variables and assignments to verify that the width of all rows are the same. First off, I changed the macro's pattern to handle the first row separately from the subsequent rows. The first variable, _assert_width0, is initialized with an array of units ((), which makes the array take no memory), with the size of the array being the number of items in the first row. Then, _assert_width is also initialized with an array of units, with the size of the array being the number of items in each subsequent row. Then, _assert_width is assigned to _assert_width0. The magic here is that this line will raise a compiler error if the width of a row doesn't match the width of the first row, since the types of the array won't match (you might have e.g. [(); 3] and [(); 4]). The error isn't super clear if you don't know what's going on in the macro, though:
<anon>:38:24: 38:37 error: mismatched types:
expected `[(); 3]`,
found `[(); 4]`
(expected an array with a fixed size of 3 elements,
found one with 4 elements) [E0308]
<anon>:38 _assert_width0 = _assert_width;
^~~~~~~~~~~~~
<anon>:47:13: 47:44 note: in this expansion of mat! (defined in <anon>)
<anon>:38:24: 38:37 help: see the detailed explanation for E0308

First, to quickly address the title of your question: see the Counting chapter in The Little Book of Rust Macros. To summarise: there is no direct way, you need to write a macro that expands to something you can count in regular code.
Now, to address your actual question: hoo boy.
It's not so much counting that you want, it's to fail at compile time if the sub-sequences have different lengths.
First of all, there's no clean way to trigger a compilation failure from a macro. You can trigger some other pre-existing error, but you can't control the actual error message.
Secondly, there's no easy way to do "variable" comparisons in macros at all. You can sometimes compare against a fixed token sequence, but you're not doing that here.
So it's doubly not-really-doable.
The simplest thing to do is check the lengths during construction at runtime, and return an error or panic if they don't match.
Is it actually impossible? I don't believe so. If you're willing to accept inscrutable error messages and a massive jump in complexity, you can check for length equality between two token sequences like so:
macro_rules! tts_equal_len {
(($_lhs:tt $($lhs_tail:tt)*), ($_rhs:tt $($rhs_tail:tt)*)) => {
tts_equal_len!(($($lhs_tail)*), ($($rhs_tail)*))
};
(($($_lhs_tail:tt)+), ()) => { do_something_bad!() };
((), ($($_rhs_tail:tt)+)) => { do_something_bad!() };
((), ()) => { do_something_good!() };
}
macro_rules! do_something_bad { () => { { println!("kaboom!") } } }
macro_rules! do_something_good { () => { { println!("no kaboom!") } } }
fn main() {
tts_equal_len!((,,,), (,,,));
tts_equal_len!((,,,), (,,));
tts_equal_len!((,), (,,));
}
Again, the real problem is finding some way to fail at compile time such that the user will understand why compilation failed.

Update: there's a new way of doing things
As of the day on which this was written, the feature of rust which enables the following (count) to be done, in still unstable and is available in nightly builds.
You can check out the github issues and test cases for further understanding of what's given below
To enable this feature, you need to add the line #![feature(macro_metavar_expr)] to the top of the crate's root module (usually main.rs or lib.rs), and also set your repo to use nightly builds, which is easily done by creating a file rust-toolchain.toml in the root directory (alongside Cargo.toml) and add the folllowing lines to it:
[toolchain]
channel = "nightly"
Now, instead of providing a solution to you specific problem, I'd like to share a generic solution I created to better illustrate most situations.
I highly recommend studying the code AND the comments, by pasting the following two code blocks in a file (main.rs).
The macro_rules
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
struct SumLen {
sum: i32,
len: u32
}
/// currently one `i32` type is available
///
/// # Examples
///
/// The output of the following:
/// ```ignore
/// sumnarr!(i32 => 5 ; 6, 7, 8)
/// ```
/// will be `[(5, 1), (21, 3)]`
macro_rules! sumnarr {
( $type:ty => $( $( $x: expr ),* );* ) => {
{
// `${count(x,0)}` will give you "length" (number of iterations)
// in `$( )*` loop that you are IMMEDIATELY OUTSIDE OF (e.g.: the `$( )*` loop below)
// `${count(x,1)}` will give you TOTAL number of iterations that the `$( )*` loop
// INSIDE of the IMMEDIATE `$( )*` loop will make. i.e. it is similar to converting
// [ [i1,i2], [i1,i2,i3] ] TO [ i1,i2,i3,i4,i5 ] i.e. flatten the nested iteration.
// In case of `[ [i1,i2], [i1,i2,i3] ]`, `${count(x,0)}` is 2 and `${count(x,1)}` is 5
let mut arr: [SumLen; ${count(x,0)}] = [SumLen{ sum:0, len:0}; ${count(x,0)}];
$(
// `${index()}` refers to the iteration number within the `$( )*` loop
arr[${index()}] = {
let mut sum = 0;
//let mut len = 0;
// THe following will give us length is the loop it is IMMEDIATELY OUTSIDE OF
// (the one just below)
let len = ${count(x,0)};
$(
sum += $x;
// If you were NOT using `$x` somewhere else inside `$( )*`,
// then you should use `${ignore(x)};` to inform the compiler
//You could use the below method, where `${length()}` will give you
//"length" or "number of iterations" in current loop that you are in
// OR
// you could go with my method of `${count(x,0)}` which is explained above
//len = ${length()};
)*
SumLen {
sum,
len
}
};
)*
arr
}
};
}
The #[test] (unit test)
#[test]
fn sumnarr_macro() {
let (a, b, c, d, e) = (4, 5, 6, 9, 10);
let sum_lens = [
SumLen {
sum: a + e,
len: 2
},
SumLen {
sum: b + c + d,
len: 3
}
];
assert_eq!(sum_lens, sumnarr!(i32 => a,e;b,c,d));
}
I hope this helps

Related

When to use keyword return in Scala

I learned early on that there is no reason to use the return keyword in Scala (as far as I'm aware). That being said I found an example where simply changing adding the return keyword made my function work, where it previously didn't.
The code in question comes from my solution to the Advent of Code day 7 challenge.
def containsShinyGoldBag(bagContents: Map[String, List[String]], currentBag: String): Boolean = {
val contents = bagContents(currentBag)
if (bagContents(currentBag).contains("shiny gold") ) {
// Base Case: Bag Found in list of bags
true
} else if (contents == List.empty){
// Base Case: Dead End
false
} else {
// Continue searching down list
// Ideal solution ( gives same result as the working solution without return keyword )
// for (b <- contents) containsShinyGoldBag(bagContents, b)
// Working solution
for (b <- contents) {
if (containsShinyGoldBag(bagContents, b)) {
println(s"Found one! $b inside a $currentBag")
return true // <--- culprit
}
else false
}
false
}
}
// In the main function
var count = 0
for (bag <- bagContents.keys) {
if (containsShinyGoldBag(bagContents, bag)) {
count = count + 1
}
}
println(s"There are $count way to bring a shiny gold bag!")
When I run the code without return I end up with count = 7, which is the number of bags directly containing a shiny gold bag, rather than the correct number which counts bags that contain a shiny gold bag somewhere inside of one of their other bags down the line.
A function returns the value of the last expression it evaluates; in your case that will be one of:
true after if (bagContents(currentBag).contains("shiny gold") );
false after else if (contents == List.empty);
the last false.
true is not in such a position, so you need return to, well, make the function return it. Otherwise it's evaluated and ignored because you don't do anything with it. So is else false in the same for, actually, it can be removed without changing the meaning.
The alternative to avoid return here is
contents.exists(b => containsShinyGoldBag(bagContents, b))

How to print fields with numeric names in mongo shell? [duplicate]

I'm trying to access a property of an object using a dynamic name. Is this possible?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
There are two ways to access properties of an object:
Dot notation: something.bar
Bracket notation: something['bar']
The value between the brackets can be any expression. Therefore, if the property name is stored in a variable, you have to use bracket notation:
var something = {
bar: 'foo'
};
var foo = 'bar';
// both x = something[foo] and something[foo] = x work as expected
console.log(something[foo]);
console.log(something.bar)
This is my solution:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
Usage examples:
resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject)
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})
In javascript we can access with:
dot notation - foo.bar
square brackets - foo[someVar] or foo["string"]
But only second case allows to access properties dynamically:
var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}
var name = "pName"
var num = 1;
foo[name + num]; // 1
// --
var a = 2;
var b = 1;
var c = "foo";
foo[name + a][b][c]; // bar
Following is an ES6 example of how you can access the property of an object using a property name that has been dynamically generated by concatenating two strings.
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
This is called computed property names
You can achieve this in quite a few different ways.
let foo = {
bar: 'Hello World'
};
foo.bar;
foo['bar'];
The bracket notation is specially powerful as it let's you access a property based on a variable:
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop];
This can be extended to looping over every property of an object. This can be seem redundant due to newer JavaScript constructs such as for ... of ..., but helps illustrate a use case:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop in foo.getOwnPropertyNames()) {
console.log(foo[prop]);
}
Both dot and bracket notation also work as expected for nested objects:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;
Object destructuring
We could also consider object destructuring as a means to access a property in an object, but as follows:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
let prop = 'last';
let { bar, baz, [prop]: customName } = foo;
// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
You can do it like this using Lodash get
_.get(object, 'a[0].b.c');
UPDATED
Accessing root properties in an object is easily achieved with obj[variable], but getting nested complicates things. Not to write already written code I suggest to use lodash.get.
Example
// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);
// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);
Lodash get can be used in different ways, the documentation lodash.get
To access a property dynamically, simply use square brackets [] as follows:
const something = { bar: "Foobar!" };
const userInput = 'bar';
console.log(something[userInput])
The problem
There's a major gotchya in that solution! (I'm surprised other answers have not brought this up yet). Often you only want to access properties that you've put onto that object yourself, you don't want to grab inherited properties.
Here's an illustration of this issue. Here we have an innocent-looking program, but it has a subtle bug - can you spot it?
const agesOfUsers = { sam: 16, sally: 22 }
const username = prompt('Enter a username:')
if (agesOfUsers[username] !== undefined) {
console.log(`${username} is ${agesOfUsers[username]} years old`)
} else {
console.log(`${username} is not found`)
}
When prompted for a username, if you supply "toString" as a username, it'll give you the following message: "toString is function toString() { [native code] } years old". The issue is that agesOfUsers is an object, and as such, automatically inherits certain properties like .toString() from the base Object class. You can look here for a full list of properties that all objects inherit.
Solutions
Use a Map data structure instead. The stored contents of a map don't suffer from prototype issues, so they provide a clean solution to this problem.
const agesOfUsers = new Map()
agesOfUsers.set('sam', 16)
agesOfUsers.set('sally', 2)
console.log(agesOfUsers.get('sam')) // 16
Use an object with a null prototype, instead of the default prototype. You can use Object.create(null) to create such an object. This sort of object does not suffer from these prototype issues, because you've explicitly created it in a way that it does not inherit anything.
const agesOfUsers = Object.create(null)
agesOfUsers.sam = 16
agesOfUsers.sally = 22;
console.log(agesOfUsers['sam']) // 16
console.log(agesOfUsers['toString']) // undefined - toString was not inherited
You can use Object.hasOwn(yourObj, attrName) to first check if the dynamic key you wish to access is directly on the object and not inherited (learn more here). This is a relatively newer feature, so check the compatibility tables before dropping it into your code. Before Object.hasOwn(yourObj, attrName) came around, you would achieve this same effect via Object.prototype.hasOwnProperty.call(yourObj, attrName). Sometimes, you might see code using yourObj.hasOwnProperty(attrName) too, which sometimes works but it has some pitfalls that you can read about here.
// Try entering the property name "toString",
// you'll see it gets handled correctly.
const user = { name: 'sam', age: 16 }
const propName = prompt('Enter a property name:')
if (Object.hasOwn(user, propName)) {
console.log(`${propName} = ${user[propName]}`)
} else {
console.log(`${propName} is not found`)
}
If you know the key you're trying to use will never be the name of an inherited property (e.g. maybe they're numbers, or they all have the same prefix, etc), you can choose to use the original solution.
I came across a case where I thought I wanted to pass the "address" of an object property as data to another function and populate the object (with AJAX), do lookup from address array, and display in that other function. I couldn't use dot notation without doing string acrobatics so I thought an array might be nice to pass instead. I ended-up doing something different anyway, but seemed related to this post.
Here's a sample of a language file object like the one I wanted data from:
const locs = {
"audioPlayer": {
"controls": {
"start": "start",
"stop": "stop"
},
"heading": "Use controls to start and stop audio."
}
}
I wanted to be able to pass an array such as: ["audioPlayer", "controls", "stop"] to access the language text, "stop" in this case.
I created this little function that looks-up the "least specific" (first) address parameter, and reassigns the returned object to itself. Then it is ready to look-up the next-most-specific address parameter if one exists.
function getText(selectionArray, obj) {
selectionArray.forEach(key => {
obj = obj[key];
});
return obj;
}
usage:
/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs));
/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs));
ES5 // Check Deeply Nested Variables
This simple piece of code can check for deeply nested variable / value existence without having to check each variable along the way...
var getValue = function( s, context ){
return Function.call( context || null, 'return ' + s )();
}
Ex. - a deeply nested array of objects:
a = [
{
b : [
{
a : 1,
b : [
{
c : 1,
d : 2 // we want to check for this
}
]
}
]
}
]
Instead of :
if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 ) // true
We can now :
if( getValue('a[0].b[0].b[0].d') == 2 ) // true
Cheers!
Others have already mentioned 'dot' and 'square' syntaxes so I want to cover accessing functions and sending parameters in a similar fashion.
Code jsfiddle
var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}
var str = "method('p1', 'p2', 'p3');"
var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);
var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
// clean up param begninning
parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
// clean up param end
parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}
obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values
I asked a question that kinda duplicated on this topic a while back, and after excessive research, and seeing a lot of information missing that should be here, I feel I have something valuable to add to this older post.
Firstly I want to address that there are several ways to obtain the value of a property and store it in a dynamic Variable. The first most popular, and easiest way IMHO would be:
let properyValue = element.style['enter-a-property'];
however I rarely go this route because it doesn't work on property values assigned via style-sheets. To give you an example, I'll demonstrate with a bit of pseudo code.
let elem = document.getElementById('someDiv');
let cssProp = elem.style['width'];
Using the code example above; if the width property of the div element that was stored in the 'elem' variable was styled in a CSS style-sheet, and not styled inside of its HTML tag, you are without a doubt going to get a return value of undefined stored inside of the cssProp variable. The undefined value occurs because in-order to get the correct value, the code written inside a CSS Style-Sheet needs to be computed in-order to get the value, therefore; you must use a method that will compute the value of the property who's value lies within the style-sheet.
Henceforth the getComputedStyle() method!
function getCssProp(){
let ele = document.getElementById("test");
let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}
W3Schools getComputedValue Doc This gives a good example, and lets you play with it, however, this link Mozilla CSS getComputedValue doc talks about the getComputedValue function in detail, and should be read by any aspiring developer who isn't totally clear on this subject.
As a side note, the getComputedValue method only gets, it does not set. This, obviously is a major downside, however there is a method that gets from CSS style-sheets, as well as sets values, though it is not standard Javascript.
The JQuery method...
$(selector).css(property,value)
...does get, and does set. It is what I use, the only downside is you got to know JQuery, but this is honestly one of the very many good reasons that every Javascript Developer should learn JQuery, it just makes life easy, and offers methods, like this one, which is not available with standard Javascript.
Hope this helps someone!!!
For anyone looking to set the value of a nested variable, here is how to do it:
const _ = require('lodash'); //import lodash module
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
Documentation: https://lodash.com/docs/4.17.15#set
Also, documentation if you want to get a value: https://lodash.com/docs/4.17.15#get
You can do dynamically access the property of an object using the bracket notation. This would look like this obj[yourKey] however JavaScript objects are really not designed to dynamically updated or read. They are intended to be defined on initialisation.
In case you want to dynamically assign and access key value pairs you should use a map instead.
const yourKey = 'yourKey';
// initialise it with the value
const map1 = new Map([
['yourKey', 'yourValue']
]);
// initialise empty then dynamically assign
const map2 = new Map();
map2.set(yourKey, 'yourValue');
console.log(map1.get(yourKey));
console.log(map2.get(yourKey));
demo object example
let obj = {
name: {
first_name: "Bugs",
last_name: "Founder",
role: "Programmer"
}
}
dotted string key for getting the value of
let key = "name.first_name"
Function
const getValueByDottedKeys = (obj, strKey)=>{
let keys = strKey.split(".")
let value = obj[keys[0]];
for(let i=1;i<keys.length;i++){
value = value[keys[i]]
}
return value
}
Calling getValueByDottedKeys function
value = getValueByDottedKeys(obj, key)
console.log(value)
output
Bugs
const getValueByDottedKeys = (obj, strKey)=>{
let keys = strKey.split(".")
let value = obj[keys[0]];
for(let i=1;i<keys.length;i++){
value = value[keys[i]]
}
return value
}
let obj = {
name: {
first_name: "Bugs",
last_name: "Founder",
role: "Programmer"
}
}
let key = "name.first_name"
value = getValueByDottedKeys(obj, key)
console.log(value)
I bumped into the same problem, but the lodash module is limited when handling nested properties. I wrote a more general solution following the idea of a recursive descendent parser. This solution is available in the following Gist:
Recursive descent object dereferencing
Finding Object by reference without, strings,
Note make sure the object you pass in is cloned , i use cloneDeep from lodash for that
if object looks like
const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]
path looks like
const objectPath = ['data',1,'person',name','last']
then call below method and it will return the sub object by path given
const child = findObjectByPath(obj, objectPath)
alert( child) // alerts "last"
const findObjectByPath = (objectIn: any, path: any[]) => {
let obj = objectIn
for (let i = 0; i <= path.length - 1; i++) {
const item = path[i]
// keep going up to the next parent
obj = obj[item] // this is by reference
}
return obj
}
You can use getter in Javascript
getter Docs
Check inside the Object whether the property in question exists,
If it does not exist, take it from the window
const something = {
get: (n) => this.n || something.n || window[n]
};
You should use JSON.parse, take a look at https://www.w3schools.com/js/js_json_parse.asp
const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)

Is it possible to create a macro which counts the number of expanded items?

Is it possible to create a macro which counts the number of expanded items?
macro_rules! count {
($($name:ident),*) => {
pub enum Count {
$(
$name = 1 << $i // $i is the current expansion index
),*
}
}
}
count!(A, B, C);
Here is a macro that counts the number of matched items:
macro_rules! count_items {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_items!($($rest),*)
}
}
fn main() {
const X: usize = count_items!(a);
const Y: usize = count_items!(a, b);
const Z: usize = count_items!(a, b, c);
assert_eq!(1, X);
assert_eq!(2, Y);
assert_eq!(3, Z);
}
Note that the counting is computed at compile time.
For your example, you can do it using accumulation:
macro_rules! count {
($first:ident, $($rest:ident),*) => (
count!($($rest),+ ; 0; $first = 0)
);
($cur:ident, $($rest:ident),* ; $last_index: expr ; $($var:ident = $index:expr)+) => (
count!($($rest),* ; $last_index + 1; $($var = $index)* $cur = $last_index + 1)
);
($cur:ident; $last_index:expr ; $($var:ident = $index:expr)+) => (
#[repr(C)]
enum Count {
$($var = 1 << $index),*,
$cur = 1 << ($last_index + 1),
}
);
}
pub fn main() {
count!(A, B, C, D);
assert_eq!(1, Count::A as usize);
assert_eq!(2, Count::B as usize);
assert_eq!(4, Count::C as usize);
assert_eq!(8, Count::D as usize);
}
Yes, if you pack it as array of idents:
macro_rules! count {
($($name:ident),*) => {
{
let counter = [$(stringify!($name),)*];
counter.len()
}
}
}
Count, names, reverse order of names are available. After, you can use it to construct something. For enum building you have to join it with something like this.
In this context, no. A macro could create an expression that counts the number of identifiers passed to it, but it would only be evaluated at runtime. I created this example in just a few minutes, but I realized it would not work for what you're doing.
Compiler plugins, however, are particularly suited to this sort of work. While they're not trivial to implement, I don't think it would be overly difficult to create one for this purpose. Maybe take a look, try your hand at it, and come back if you get stuck?
Since this question is general, posting an example of counting where arguments are separated by white-space (not commas).
Although in retrospect it seems obvious, it took me a while to figure out:
/// Separated by white-space.
#[macro_export]
macro_rules! count_args_space {
($name:ident) => { 1 };
($first:ident $($rest:ident) *) => {
1 + count_args_space!($($rest) *)
}
}
/// Separated by commas.
#[macro_export]
macro_rules! count_args_comma {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_args_comma!($($rest),*)
}
}
Second example is from #malbarbo, just posting to so you can see the 2x changes that were needed.

rxjs zip is not lazy?

I 've removed the boilerplate to get to the point
// a.js
// My observables from stream and event
this.a = Rx.Node.fromStream(this.aStream());
this.itemSource = Rx.Observable.fromEvent(ee, 'addItem');
// Zip 'em
this.itemcombo = Rx.Observable.zip(this.a, this.itemSource, function (s1, s2) {
return {item: s2, a: s1.toString()};
});
// Streams the lowercase alphabet
rb.prototype.aStream = function aStream() {
var rs = Readable();
var c = 97;
rs._read = function () {
rs.push(String.fromCharCode(c++));
console.log('Hit!');
if (c > 'z'.charCodeAt(0)) {
rs.push(null);
}
};
return rs;
};
// b.js (requires the module exported above)
rb.enqueue('a'); // The method simply does an ee.emit('addItem', ...) in the module to trigger the itemSource observable
What I expected to see:
{item: 'a', a: 'a'} printed in the console
What happened:
Hit! was printed 24 times before {item: 'a', a: 'a'}. This means that zip took all the values from aStream, buffered them and then did what it was supposed to do.
How do I get the same functionality zip offers but lazily? My goal is to use an infinite stream/observable and zip it with a finite (async) one.
Edit
See/Edit it via runnable: RX Zip test Edit 2 Code updated based on answer -> no output now.
zip is indeed lazy. It just subscribes to a and b and does its work whenever either produces a new value.
Your problem is that fromStream is emitting all of its values synchronously as soon as zip subscribes to it. This is happening because your custom Readable is constantly saying "There is more data available!"
Make your Readable asynchronous and you'll get the desired behavior.
Try something like this (untested)
var rs = Readable();
var subscription = null;
rs._read = function () {
if (!subscription) {
// produce the values once per second
subscription = Rx.Observable
.generateWithRelativeTime(
97, // start value
function (c) { return c > 'z'.charCodeAt(0); }, // end condition
function (c) { return c + 1; }, // step function
function (c) { return String.fromCharCode(c); }, // result selector
function () { return 1000; }) // 1000ms between values
.subscribe(
function (s) {
rs.push(s);
console.log("Hit!");
},
function (error) { rs.push(null); },
function () { rs.push(null); });
}
};

Peculiar Map/Reduce result from CouchDB

I have been using CouchDB for quite sometime without any issues. That is up until now. I recently saw something in my map/reduce results which I had overlooked!
This is before performing a sum on the "avgs" variable. I'm basically trying to find the average of all values pertaining to a particular key. Nothing fancy. The result is as expected.
Note the result for timestamp 1308474660000 (4th row in the table):
Now I sum the "avgs" array. Now here is something that is peculiar about the result. The sum for the key with timestamp 1308474660000 is a null!! Why is CouchDB spitting out nulls for a simple sum? I tried with a custom addition function and its the same problem.
Can someone explain to me why is there this issue with my map/reduce result?
CouchDB version: 1.0.1
UPDATE:
After doing a rereduce I get a reduce overflow error!
Error: reduce_overflow_error
Reduce output must shrink more rapidly: Current output: '["001,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,101,1,1,1,1,1,1,11,1,1,1,1'... (first 100 of 396 bytes)
This is my modified reduce function:
function (key, values, rereduce) {
if(!rereduce) {
var avgs = [];
for(var i=values.length-1; i>=0 ; i--) {
avgs.push(Number(values[i][0])/Number(values[i][1]));
}
return avgs;
} else {
return sum(values);
};
}
UPDATE 2:
Well now it has gotten worse. Its selectively rereducing. Also, the ones it has rereduced show wrong results. The length of the value in 4th row for timestamp (1308474660000) should be 2 and not 3.
UPDATE 3:
I finally got it to work. I hadn't understood the specifics of rereduce properly. AFAIK, Couchdb itself decides how to/when to rereduce. In this example, whenever the array was long enough to process, Couchdb would send it to rereduce. So I basically had to sum twice. Once in reduce, and again in rereduce.
function (key, values, rereduce) {
if(!rereduce) {
var avgs = [];
for(var i=values.length-1; i>=0 ; i--) {
avgs.push(Number(values[i][0])/Number(values[i][1]));
}
return sum(avgs);
} else {
return sum(values); //If my understanding of rereduce is correct, it only receives only the avgs that are large enough to not be processed by reduce.
}
}
Your for loop in the reduce function is probably not doing what you think it is. For example, it might be throwing an exception that you did not expect.
You are expecting an array of 2-tuples:
// Expectation
values = [ [value1, total1]
, [value2, total2]
, [value3, total3]
];
During a re-reduce, the function will get old results from itself before.
// Re-reduce values
values = [ avg1
, avg2
, avg3
]
Therefore I would begin by examining how your code works if and when rereduce is true. Perhaps something simple will fix it (although often I have to log() things until I find the problem.)
function(keys, values, rereduce) {
if(rereduce)
return sum(values);
// ... then the same code as before.
}
I will elaborate on my count/sum comment, just in case you are curious.
This code is not tested, but hopefully you will get the idea. The end result is always a simple object {"count":C, "sum":S} and you know the average by computing S / C.
function (key, values, rereduce) {
// Reduce function
var count = 0;
var sum = 0;
var i;
if(!rereduce) {
// `values` stores actual map output
for(i = 0; i < values.length; i++) {
count += Number(values[i][1]);
sum += Number(values[i][0]);
}
return {"count":count, "sum":sum};
}
else {
// `values` stores count/sum objects returned previously.
for(i = 0; i < values.length; i++) {
count += values[i].count;
sum += values[i].sum;
}
return {"count":count, "sum":sum};
}
}
I use the following code to do average. Hope it helps.
function (key, values) {
return sum(values)/values.length;
}