Skip to content
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

reconstruction feature #1617

Closed
mark-hahn opened this issue Aug 20, 2011 · 23 comments
Closed

reconstruction feature #1617

mark-hahn opened this issue Aug 20, 2011 · 23 comments

Comments

@mark-hahn
Copy link

I have asked for this before but I have now run into about a dozen places in my app where I have code like this (production code) ...

view = 
    id: doc._id
    thread: doc.thread
    lastEdited: doc.lastEdited
    name: doc.name
    posted: doc.posted
    html: doc.html
    ptrNum: ptrNum
    okToEdit: (doc.author is userId)

... and I would really like to shorten it to ...

view = {id, thread, lastEdited, name, posted, html, 
        ptrNum:ptrNum, okToEdit: (doc.author is userId)} = doc

This allows one to select a subset of an object to create a new object. I do this all the time. In this particular example it is doing deconstruction and then reconstruction in one operation.

I don't really care what the syntax is, I just don't want to repeat the source object over and over. Another syntax option would be something like this (just replace the right = with "in") ...

view = {name, id, age}  in  doc

The token "in" could be any token/operator that doesn't break the language. The token means "use the following as the default object for this constructor instead of the local scope".

Each time I write code like this I pine for the feature more and more. How hard would it be to add this feature? I would be willing to spend whatever time it takes to code this for a pull request.

@MichaelBlume
Copy link

+1

@benekastah
Copy link

To fix this in the near-term, you could do something like this:

@mix = (obj, keys) ->
  if keys
    @[key] = obj[key] for key in keys
  else
    @[key] = value for own key, value in obj
  this

view = 
  some: "stuff"

# copy certain properties
mix.call view, doc, ["name", "id", "age"]

# copy all direct properties
someObj = mix.call {}, doc

@mark-hahn
Copy link
Author

That's funny. I was thinking about this exact same thing about an hour ago. I was thinking of extending the underscore extend function. If a param on the right was an array it would use the first item as the object and the rest as allowed property names. This way you could have multiple docs on the right as _.extend normally does.

_.extend view, [doc, "name", "id", "age"]

@benekastah
Copy link

That's good, too. I'm glad I came across this. I hadn't thought much of "selective mixins" until I read over your problem. This would be a great CS feature.

@mark-hahn
Copy link
Author

I just put this in my production code ...

oldExtend = _.extend

_.extend = (dest, sources...) ->
    for source in sources
        if _.isArray(source)
            srcObj = source[0]
            for key in source[1..]
                dest[key] = srcObj[key]
        else oldExtend dest, source
    dest

@satyr
Copy link
Collaborator

satyr commented Aug 31, 2011

$ coco -bpe 'view = doc{name, id, age}'
var view;
view = {
  name: doc.name,
  id: doc.id,
  age: doc.age
};

@linus
Copy link

linus commented Sep 1, 2011

I second this. I often do things like:

{id, title, content} = req.body
post = {id, title, content}

I would love to be able to shorten it to:

post = {id, title, content} = req.body

Concise and clear, IMO.

The coco syntax is almost better, though. No extraneous variables.

@michaelficarra
Copy link
Collaborator

I'm fond of that coco syntax as well.

edit: I mean, with the .: doc.{name, id, age}

@satyr
Copy link
Collaborator

satyr commented Sep 2, 2011

confusion with fn {...}

Inevitable as long as we have implicit call:

$ coffee -bpe 'a[b]; a [b]'
a[b];
a([b]);

Avoiding it by using longhand is possible though:

$ coco -bpe 'doc . {id}; a . [b]'
({
  id: doc.id
});
a[b];

@TrevorBurnham
Copy link
Collaborator

Yeah, the Coco syntax

doc.{name, id, age}

is really nice. Provides DRY for a very common use case. I'd expect rave reviews if it were added in 1.2.

@cpryland
Copy link

cpryland commented Sep 6, 2011

That would just expand into:

[doc.name, doc.id, doc.age]

?

@TrevorBurnham
Copy link
Collaborator

@cpryland No, try it out in the Coco console: http://satyr.github.com/cup/

You can write

doc1 = {name: 'blah', id: 'asfg', age: 33}
doc2 = {}
doc2.{name, id, age} = otherDoc

and that last line is equivalent to doc2.name = doc1.name; doc2.id = doc1.id; doc2.age = doc1.age. You can also write

doc3 = doc2.{name, id, age}

and doc3 is a new object with those properties.

So, it's a nicely symmetric form of the extends syntax that's been requested so many times.

@michaelficarra
Copy link
Collaborator

#1632 is slightly related

@michaelficarra
Copy link
Collaborator

#1708 is much more related

@erisdev
Copy link

erisdev commented Sep 23, 2011

@accelware but it's using the curlies! If we had a similar syntax for returning an array of multiple properties, I'd expect it to use square brackets.

array = doc2.[name, id, age]
doc3.[name, id, age] = array

As it turns out, coco has this feature as well and I really like it.

@bigeasy
Copy link

bigeasy commented Dec 10, 2011

I recently tried:

subset = { a, b } = set

And was disappointed when it didn't do what I expected, which was to create subset as a hash slice of set. I'd like to see this feature in CoffeeScript, so +1.

@michaelficarra
Copy link
Collaborator

@bigeasy: Wouldn't you prefer the syntax from #1708? subset = set.{a, b}

@erisdev
Copy link

erisdev commented Dec 10, 2011

@michaelficarra I sure would. In fact, I thought I had commented on that issue saying as much, but it seems I must have 👍ed that syntax in another, related issue. 8|

@bigeasy
Copy link

bigeasy commented Dec 11, 2011

@michaelficarra I didn't mean to state a syntax preference. Only noting that I'd been hoping for a way to do hash slicing.

@aseemk
Copy link
Contributor

aseemk commented Nov 20, 2012

+1 fo' sho'!

@danschumann
Copy link

i suggested this a while ago, for use of something like

run_function( { key1, key2 } = object )

for now, I've been using

run_function( _.pick object, 'key1', 'key2' )

@epidemian
Copy link
Contributor

I like the sub = object.{key1, key2} expression syntax :)

It is very confusing how sub = {key1, key2} = object works in my opinion. But i think both possible behaviours of that statement are confusing (i.e. assigning sub to object or to {key1, key2}); i'd prefer that destructuing assignment would not be an expression, so that statement is invalid (just like foo = return is invalid).

@GeoffreyBooth
Copy link
Collaborator

Closing this request as it’s not a priority at the moment. That said, if someone feels like implementing this as a PR that doesn’t introduce any breaking changes, it would be considered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests