New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

why does _.each create a pair for object containers? #2

Closed
pmuellr opened this Issue Oct 29, 2009 · 7 comments

Comments

Projects
None yet
4 participants
@pmuellr

pmuellr commented Oct 29, 2009

It seems odd that _.each creates a pair [key, value] as the items passed to the function parameter. Why not just send the (value, key) instead of ([value,key], index)? I guess that's why _.keys and _.values exist. It seems more consistent in that you can always think of the parameters as value/key instead of having to mentally translate for objects.

If someone really did want the key/value pairs, it would be easy to do this with _.map(function(value,key) { return [key, value] /* or {key:key, value:value} */ }) . Note that incantation wouldn't work today, because _.map uses _.each

@jashkenas

This comment has been minimized.

Owner

jashkenas commented Oct 29, 2009

I like it. I was following along after the fashion in which Prototype does it -- which tries to make iterating over objects as similar to iterating over arrays as possible. Your way is much nicer -- I've made the change, and added it to 0.3.1, which is out now.

@kriskowal

This comment has been minimized.

Contributor

kriskowal commented Oct 30, 2009

I actually disagree. In previous work, including Narwhal's util module and Chiron's base modules, It's been my design to preserve "mutual idempotence". For example, these are identities:

object(x) = object(array(object(x)))
array(x) = array(object(array(x)))

This works by making an object constructible from an array of pairs, and an array of pairs constructible from an object.

@kriskowal

This comment has been minimized.

Contributor

kriskowal commented Oct 30, 2009

oh, and with regard to the decomposition of pairs, I always provide .forEachApply and .mapApply.

@ghost

This comment has been minimized.

ghost commented Oct 30, 2009

Interesting. Can you talk a little about how you use inter-conversion between array pairs and objects in practice? An example perhaps.

While it's nice to keep as much information as possible, retaining the key and value glued together, there's just something too appealing about the symmetry of (element, index, array), and (value, key, object), as the arguments that you would expect for an iterator function. In this fashion, your function could more easily work on both arrays and objects, without having to special-case on either end.

@kriskowal

This comment has been minimized.

Contributor

kriskowal commented Oct 30, 2009

Actually, I agree that the symmetry is quite appealing, and very much "in keeping with the rustic aesthetic". This I will have to consider further.

With Narwhal's util and Chiron's base, these are functioning idioms:

util.forEachApply(object, function (key, value) {
});

util.forEachApply(util.items(array), function (index, value) {
});

util.object([["a", 10], ["b", 20], ["c", 30]])

util.eq(util.object(util.enumerate("abc")), {"0": "a", "1": "b", "2": "c"})

util.eq(util.object(util.zip("abc", util.range(3))), {"a": 0, "b": 1, "c": 2})

That kind of thing.

@ghost

This comment has been minimized.

ghost commented Oct 30, 2009

Nice. Taking a stroll through the util.js source -- have you thought about releasing a version of it for the browser? If not, are there functions in there that you think Underscore would be better off including?

@kriskowal

This comment has been minimized.

Contributor

kriskowal commented Oct 31, 2009

I have not considered writing a version that works both as a global script in the browser and as a CommonJS module, but as your library and some others demonstrate, this is not really difficult to do, especially if you have no dependencies. It's my hope that people will use util in the browser, but through CommonJS browser deployment strategies.

As much as underscore is a subset of util, util is a subset that I pared out of Chiron, which does all the same stuff except also has a type system. I took pared out the type system, used the same names, and some of the same behaviors. The benefit of doing this is that these functions make even low level code much more expressive, but in Narwhal we strive not to "bless" any particular type system, sticking to prototypical inheritance, because, at the end of the day, type systems in JavaScript are controversial.

http://github.com/kriskowal/chiron/tree/master/lib/chiron/

See: base.js, type.js, operator.js, iter.js, list.js, set.js, dict.js, range.js, string.js, each.js

So, there's a certain value in being lighter than Chiron, and I think there's another value in being lighter than util.js. So, I do not think that you need to go out of your way to bring in the kitchen sink. In fact, you probably should not.

Kris

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment