struct-maps and key removal

338 views
Skip to first unread message

Richard Newman

unread,
Dec 15, 2009, 2:23:02 AM12/15/09
to clo...@googlegroups.com
Something I keep bumping into: the SQL library returns rows as struct-
maps. Often I want to do things like rename keys (:foo_bar => :foo-
bar), strip out :id columns, etc.

Nope!

java.lang.Exception: Can't remove struct key

Any opinions on returning a hash-map after 'removing' (remember, these
are persistent data structures) a key from a struct-map? They print
the same, act the same... except in this instance.

ataggart

unread,
Dec 15, 2009, 5:05:10 AM12/15/09
to Clojure
So have (dissoc mystruct :akey) act like (dissoc (into {}
mystruct) :akey)? Sounds reasonable to me.

Garth Sheldon-Coulson

unread,
Dec 15, 2009, 5:21:58 AM12/15/09
to clo...@googlegroups.com
I wonder if the fact that this currently doesn't work the way you want it to is a necessary consequence of structural sharing and the desired performance guarantees of dissoc.

In other words: I wonder if, on account of how struct maps are implemented (sort of like a vector, right?), the only way to get a hash map with one key gone is to do a linear copy of the struct map.

If that's true (I have no idea if it is!), then there might be a reason for forcing you to do

(dissoc (into {} mystruct) :akey)

explicitly. Namely, it preserves the performance guarantees of dissoc.

Garth


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Sean Devlin

unread,
Dec 15, 2009, 9:41:38 AM12/15/09
to Clojure
Isn't the whole point of a struct that it guarantees that certain keys
are present? I think the current behavior is correct.

On Dec 15, 5:21 am, Garth Sheldon-Coulson <g...@mit.edu> wrote:
> I wonder if the fact that this currently doesn't work the way you want it to
> is a necessary consequence of structural sharing and the desired performance
> guarantees of dissoc.
>
> In other words: I wonder if, on account of how struct maps are implemented
> (sort of like a vector, right?), the only way to get a hash map with one key
> gone is to do a linear copy of the struct map.
>
> If that's true (I have no idea if it is!), then there might be a reason for
> forcing you to do
>
> (dissoc (into {} mystruct) :akey)
>
> explicitly. Namely, it preserves the performance guarantees of dissoc.
>
> Garth
>
> On Tue, Dec 15, 2009 at 5:05 AM, ataggart <alex.tagg...@gmail.com> wrote:
>
> > On Dec 14, 11:23 pm, Richard Newman <holyg...@gmail.com> wrote:
> > > Something I keep bumping into: the SQL library returns rows as struct-
> > > maps. Often I want to do things like rename keys (:foo_bar => :foo-
> > > bar), strip out :id columns, etc.
>
> > > Nope!
>
> > >    java.lang.Exception: Can't remove struct key
>
> > > Any opinions on returning a hash-map after 'removing' (remember, these
> > > are persistent data structures) a key from a struct-map? They print
> > > the same, act the same... except in this instance.
>
> > So have (dissoc mystruct :akey) act like (dissoc (into {}
> > mystruct) :akey)?  Sounds reasonable to me.
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clo...@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>

Richard Newman

unread,
Dec 15, 2009, 1:11:42 PM12/15/09
to clo...@googlegroups.com
> Isn't the whole point of a struct that it guarantees that certain keys
> are present?

Oh, I agree -- dissoc on a struct-map would return a non-struct-map.
I'm not suggesting that struct-maps should be able to be dissociated
from one of their keys, I'm wondering whether it's better to return an
array-map or hash-map from dissoc rather than blow up.

(Or whether there should be a `without-keys` function that behaves
much like dissoc but works on any map, and have rename-keys and other
"implicit dissoc" functions use that instead. rename-keys on a struct-
map's core keys implies an abandonment of struct-ness, no?)

I suppose the question is "are struct-maps 'structs' or
maps?" (speaking ontologically). If they're structs, then it's happy
coincidence that the map get/assoc functions work on them, and
slightly confusing that they print as ordinary maps. If they're maps,
where their struct-ness is an optimization, then dissoc should work in
the same way that assoc on an array-map can sometimes return a hash-map.

The main reason I bring this up is that I had no reason to suspect
that the maps returned from my SQL queries were actually struct-maps.
They printed like any other map, and work correctly for every non-
removing map operation. Having some subset of maps error on core API
operations seems opposed to abstraction-oriented programming. It trips
my disgust switch to see code like

(rename-keys
(if (struct-map? m)
(into {} m)
m)
{:foo :bar})

Rich Hickey

unread,
Dec 28, 2009, 1:17:30 PM12/28/09
to clo...@googlegroups.com

Yes. The behavior for the new deftypes, when used as maps, is as you
desire - a dissoc of a field key yields an ordinary map (no longer of
the deftype type).

Enhancements to structs are on hold pending analysis of their utility
in light of deftypes.

Rich

Reply all
Reply to author
Forward
0 new messages