Re: [racket-dev] Generics updates
On Oct 2, 2013, at 4:41 PM, Sam Tobin-Hochstadt wrote: I think I prefer separate unrelated data structures, +1 We need to look at other languages and what devs say about intermingling and/or separating applicative and stateful data types. Java and Scala seem to provide particularly bad examples, so perhaps we should not follow what they do :-) -- Matthias _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
On Fri, Oct 4, 2013 at 1:30 PM, Matthias Felleisen matth...@ccs.neu.edu wrote: Java and Scala seem to provide particularly bad examples, so perhaps we should not follow what they do :-) I know what you mean about Java, but I've heard lots of good things about the new Scala collections framework. Is there something specific you're thinking about? Sam _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev -- Jay McCarthy j...@cs.byu.edu Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay The glory of God is Intelligence - DC 93 _ Racket Developers list: http://lists.racket-lang.org/dev _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev -- Jay McCarthy j...@cs.byu.edu Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay The glory of God is Intelligence - DC 93 _ Racket Developers list: http://lists.racket-lang.org/dev -- Jay McCarthy j...@cs.byu.edu Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay The glory of God is Intelligence - DC 93 _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate
Re: [racket-dev] Generics updates
That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard
Re: [racket-dev] Generics updates
I agree. I think the important thing with generics is unlike mpair? the set? predicate only necessarily implies that the methods are available (which is the source of my original complaint). We need to design the meaning of predicates just like we design the interface. I think that if we want mset to be a set then set? cannot imply immutable? but since that is a valuable property, it is worth designing a predicate that gives it, if only as a human thing. Jay On Wed, Oct 2, 2013 at 2:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations
Re: [racket-dev] Generics updates
On Wed, Oct 2, 2013 at 4:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Unfortunately, this is only half-true, I think. In particular, a very large number of our data structures violate this rule: vectors, strings, byte strings boxes, hash tables, dictionaries, sequences, and so on, all provide the same operations on both mutable and immutable variants. This is also true in general of structs -- a substruct can be mutable when the superstruct is immutable. Ultimately, for the purpose of consistency, I think we should try to decide what the 'Rackety' style for this is. Should we follow the lead of hash tables, where `immutable?` is needed to determine anything? Or should we follow the lead of pairs, where there's a whole separate type? And how should this interact with subtyping, as in this discussion? Personally, I think I prefer separate unrelated data structures, with a generic interface [1]. Maybe this means we should make `immutable?` into a generic. [1] I think that part of the reason some of these are conflated is lack of generic operations. Sam Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient
Re: [racket-dev] Generics updates
This is a good message, but I have one quibble. I think it makes sense to separate data immutability and logical immutability. For instance, I may have a library for querying REST services where a server object is represented by an immutable string. The string is immutable? but the service behind it is not. I don't want the happenstance of which data was used to construct the object to give the wrong idea of its mutability. Jay On Wed, Oct 2, 2013 at 2:41 PM, Sam Tobin-Hochstadt sa...@cs.indiana.edu wrote: On Wed, Oct 2, 2013 at 4:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Unfortunately, this is only half-true, I think. In particular, a very large number of our data structures violate this rule: vectors, strings, byte strings boxes, hash tables, dictionaries, sequences, and so on, all provide the same operations on both mutable and immutable variants. This is also true in general of structs -- a substruct can be mutable when the superstruct is immutable. Ultimately, for the purpose of consistency, I think we should try to decide what the 'Rackety' style for this is. Should we follow the lead of hash tables, where `immutable?` is needed to determine anything? Or should we follow the lead of pairs, where there's a whole separate type? And how should this interact with subtyping, as in this discussion? Personally, I think I prefer separate unrelated data structures, with a generic interface [1]. Maybe this means we should make `immutable?` into a generic. [1] I think that part of the reason some of these are conflated is lack of generic operations. Sam Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers
Re: [racket-dev] Generics updates
Short(ish) answer until I get reliable internet in my new apartment -- gen:set is modeled after gen:dict. I don't want us to have a new design for each interface. Because methods are optional, we get by with one name for one or more related subinterfaces. That's the principle by which I justified set-add and set-add! In one interface. And if we separate them, we need one interface with just queries, then four more for add, remove, add!, and remove!, at the very least. It's a messy direction to go in. Carl Eastlund -- WARNING! Poorly-typed cell phone email precedes. On Oct 2, 2013 4:35 PM, Jay McCarthy jay.mccar...@gmail.com wrote: I agree. I think the important thing with generics is unlike mpair? the set? predicate only necessarily implies that the methods are available (which is the source of my original complaint). We need to design the meaning of predicates just like we design the interface. I think that if we want mset to be a set then set? cannot imply immutable? but since that is a valuable property, it is worth designing a predicate that gives it, if only as a human thing. Jay On Wed, Oct 2, 2013 at 2:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I think that sets with mutations are subclass of get:set and we should have a separate gen:mset (or something) interface for mutable versions. I dislike that an obvious implementation of sets, hash tables, are not sets to gen:set, because there are operations that cannot be performed on them. I think that X implements generic G should imply All functions of G work on X. But this is not the case with gen:set and hasheq sets, for instance. Jay On Tue, Jul 23, 2013 at 9:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies
Re: [racket-dev] Generics updates
On Wed, Oct 2, 2013 at 4:44 PM, Jay McCarthy jay.mccar...@gmail.com wrote: This is a good message, but I have one quibble. I think it makes sense to separate data immutability and logical immutability. For instance, I may have a library for querying REST services where a server object is represented by an immutable string. The string is immutable? but the service behind it is not. I don't want the happenstance of which data was used to construct the object to give the wrong idea of its mutability. I think what you're saying here is that part of what we want from immutability is knowing that doing the same thing again on the immutable data won't change the behavior. But of course, this is a property of _both_ the data and the operation -- `file-bytes` takes immutable input, but running it multiple times doesn't guarantee anything. I'm not sure where this leaves us in terms of API design, though. In a capability-based language, or in a language like Clean, `file-bytes` might take the filesystem as input, but that's not very Rackety. :) My inclination is that a dictionary implemented with immutable data structures but representing the results of `getenv` shouldn't be `immutable?`, whereas maybe one with mutable insides but a functional interface should be, but that really depends on what we're trying to say. Sam Jay On Wed, Oct 2, 2013 at 2:41 PM, Sam Tobin-Hochstadt sa...@cs.indiana.edu wrote: On Wed, Oct 2, 2013 at 4:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Unfortunately, this is only half-true, I think. In particular, a very large number of our data structures violate this rule: vectors, strings, byte strings boxes, hash tables, dictionaries, sequences, and so on, all provide the same operations on both mutable and immutable variants. This is also true in general of structs -- a substruct can be mutable when the superstruct is immutable. Ultimately, for the purpose of consistency, I think we should try to decide what the 'Rackety' style for this is. Should we follow the lead of hash tables, where `immutable?` is needed to determine anything? Or should we follow the lead of pairs, where there's a whole separate type? And how should this interact with subtyping, as in this discussion? Personally, I think I prefer separate unrelated data structures, with a generic interface [1]. Maybe this means we should make `immutable?` into a generic. [1] I think that part of the reason some of these are conflated is lack of generic operations. Sam Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates Regarding a point from RacketCon, I don't like that gen:set includes functions like set-add! and set-remove!. I
Re: [racket-dev] Generics updates
Totally agree. On Wed, Oct 2, 2013 at 2:53 PM, Sam Tobin-Hochstadt sa...@cs.indiana.edu wrote: On Wed, Oct 2, 2013 at 4:44 PM, Jay McCarthy jay.mccar...@gmail.com wrote: This is a good message, but I have one quibble. I think it makes sense to separate data immutability and logical immutability. For instance, I may have a library for querying REST services where a server object is represented by an immutable string. The string is immutable? but the service behind it is not. I don't want the happenstance of which data was used to construct the object to give the wrong idea of its mutability. I think what you're saying here is that part of what we want from immutability is knowing that doing the same thing again on the immutable data won't change the behavior. But of course, this is a property of _both_ the data and the operation -- `file-bytes` takes immutable input, but running it multiple times doesn't guarantee anything. I'm not sure where this leaves us in terms of API design, though. In a capability-based language, or in a language like Clean, `file-bytes` might take the filesystem as input, but that's not very Rackety. :) My inclination is that a dictionary implemented with immutable data structures but representing the results of `getenv` shouldn't be `immutable?`, whereas maybe one with mutable insides but a functional interface should be, but that really depends on what we're trying to say. Sam Jay On Wed, Oct 2, 2013 at 2:41 PM, Sam Tobin-Hochstadt sa...@cs.indiana.edu wrote: On Wed, Oct 2, 2013 at 4:29 PM, Robby Findler ro...@eecs.northwestern.edu wrote: That sounds right. But just in case there is any confusion on the larger point: predicates as way we check properties to ensure good properties of our abstractions is one of the important things that we have mostly gotten right in Racket. Chaperones, separate pair? and mpair? predicates, and presumably lots of other stuff are the way they are for this kind of reason. Unfortunately, this is only half-true, I think. In particular, a very large number of our data structures violate this rule: vectors, strings, byte strings boxes, hash tables, dictionaries, sequences, and so on, all provide the same operations on both mutable and immutable variants. This is also true in general of structs -- a substruct can be mutable when the superstruct is immutable. Ultimately, for the purpose of consistency, I think we should try to decide what the 'Rackety' style for this is. Should we follow the lead of hash tables, where `immutable?` is needed to determine anything? Or should we follow the lead of pairs, where there's a whole separate type? And how should this interact with subtyping, as in this discussion? Personally, I think I prefer separate unrelated data structures, with a generic interface [1]. Maybe this means we should make `immutable?` into a generic. [1] I think that part of the reason some of these are conflated is lack of generic operations. Sam Robby On Wed, Oct 2, 2013 at 3:21 PM, Jay McCarthy jay.mccar...@gmail.com wrote: Even if we were to remove set-add! from gen:set and not great gen:mset then that would not be a vaild property. Generics are a lower bound on the interface, not an upper bound, so there could be other functions on the data structure that implement mutation. For instance, a gen:set could be made for an external resource that was set-like. I think what you want is something like gen:fset that has no methods, but is used for set authors to tag their set as having this property for the benefit of consumers (which cannot be enforced.) Your library would then consume fsets and not sets. Jay On Wed, Oct 2, 2013 at 2:09 PM, Robby Findler ro...@eecs.northwestern.edu wrote: If we do go this way, we should be careful about the subtyping relationship since we want a predicate that means will not be mutated and I can rely on that to reason about my library's behavior and if mutable sets are a sub-thing of immutable ones, we might lose that (depending on how things are set up). Robby On Wed, Oct 2, 2013 at 2:57 PM, Jay McCarthy jay.mccar...@gmail.com wrote: No. Mutable sets would implement gen:set and then just have a few more methods in the gen:mset interface. Structs can implement any number of generics. Jay On Wed, Oct 2, 2013 at 1:31 PM, J. Ian Johnson i...@ccs.neu.edu wrote: This means I can't interchange between mutable and immutable sets for my functions that only need to read generic sets, unless we further subdivide and have gen:set-query gen:set-constructor gen:set-mconstruct. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Carl Eastlund c...@ccs.neu.edu Cc: Racket Developers dev@racket-lang.org Sent: Wednesday, October 2, 2013 3:23:07 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] Generics updates
Re: [racket-dev] Generics updates
At Fri, 2 Aug 2013 15:33:02 -0400, Carl Eastlund wrote: [1 text/plain; UTF-8 (7bit)] On Fri, Aug 2, 2013 at 1:47 PM, Stephen Chang stch...@ccs.neu.edu wrote: With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Oh yeah, I like that better than moving set-stream to primitives since they are more standard set operations. So the proposal for primitive methods is to pick one canonical set of methods from which all the others can be derived? I'm fairly sure there's more than one such set, and I'm not sure there's one choice that's clearly better than the others. I can understand the benefits of documenting a suggested set, but given that it is an arbitrary and pragmatic distinction, I'm not sure I'd want to set them off in a section any more. I'd just make a list in the gen:set description or something. Sounds good to me. As long as there's a clear easy starting point for someone implementing a new set type, I think we're good. Vincent _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
This whole discussion reminds me of the idea of specialization interface specification. The notion is due to Lamping, I think. Stevie and I read the paper and his class contracts provide some of the power of SIs but not all. In particular, they fail to provide the power that seems to be necessary here: specifying the cycles among methods that is required to be overridden wholesale specifying the 'what I get for free' methods As far as I know, there is no PL that actually supports such specs and everyone relies on plain old English docs to get this across. Then everyone gets it wrong the first time and plays until it works. It's quite likely to be a DLS-level research paper, possibly OOPSLA if we integrate it with a type system eventually. -- Matthias On Aug 1, 2013, at 7:30 PM, Carl Eastlund wrote: No, that doesn't work. If someone implements, say, an efficient subset? test, then set=? should use that rather than iterating using set-stream and set-member?. You should use the highest-level methods you can, in order to get the most out of an implementation. Which is why I made all the fallback implementations I did, to give implementers the best flexibility possible for getting a good implementation of all methods for the minimum possible effort on their part. Similarly, I don't want to make set-stream primitive, because if someone does implement set-first and set-rest, it should be derivable. Carl Eastlund On Thu, Aug 1, 2013 at 7:26 PM, Stephen Chang stch...@ccs.neu.edu wrote: Would it be better to just remove the primitve / derived distinction, since it's somewhat artificial, and leave it up to the individual method descriptions? Is there some better way I should be describing things? Ok I can see now that there's no easy way to organize the methods. I think we should keep some distinction, since as a programmer it's good to know exactly what methods I have to implement. However, to me fallback implies that I should get it for free, so it seems most intuitive if derived methods only depend on primitive methods. Then for some subset of primitive methods that I implement, I should get the derived methods that depend on those primitives. I'll have to think more about what should be derived and primitive, but for now I think the easiest thing is to edit the docs to move set-stream (or some equivalent) into the primitive list? Carl Eastlund On Thu, Aug 1, 2013 at 6:51 PM, Stephen Chang stch...@ccs.neu.edu wrote: For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. You did document the dependencies, but some of them are circular, ie some derived rely on other derived. I'd definitely be happy to patch things myself, but I guess I dont have a concrete complaint yet :), only that the distinctions feel somewhat arbitrary and did not match my initial intuition, which is why I'm looking for additional insight. Do you have examples of which ones don't come for free with the primitive methods? Very few of the derived come free because most rely on set-stream, but set-stream is not primitive which is why I thought there might be a distinction between iterable sets and non-iterable. Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history,
Re: [racket-dev] Generics updates
At Thu, 1 Aug 2013 18:56:08 -0400, Carl Eastlund wrote: Ah, yes, set-stream isn't primitive because it can be derived if you have set-first and either set-rest or set-remove. And I know there are dependency cycles, this is intentional so that you can implement any one of several related things, but most of them were supposed to go all the way down to primitive methods (in some sense) if all else failed. Would it be better to just remove the primitve / derived distinction, since it's somewhat artificial, and leave it up to the individual method descriptions? Is there some better way I should be describing things? I like the primitive / derived distinction, but I don't think that the distinction should be done based on the presence of fallback implementations. IMO, it makes more sense to interpret it like Stephen did: what do I need to write to get a minimum viable set type and get the rest for free. Presence or absence of fallbacks is just an implementation detail. If we take that view, then basic (or something) may make more sense than primitive, though. With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Vincent _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Oh yeah, I like that better than moving set-stream to primitives since they are more standard set operations. Carl, I dont see how guaranteeing some fallback implementations affects allowing more efficient versions. I think most programmers understand that the default implementation is probably not very efficient. Vincent _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
On Fri, Aug 2, 2013 at 1:47 PM, Stephen Chang stch...@ccs.neu.edu wrote: With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Oh yeah, I like that better than moving set-stream to primitives since they are more standard set operations. So the proposal for primitive methods is to pick one canonical set of methods from which all the others can be derived? I'm fairly sure there's more than one such set, and I'm not sure there's one choice that's clearly better than the others. I can understand the benefits of documenting a suggested set, but given that it is an arbitrary and pragmatic distinction, I'm not sure I'd want to set them off in a section any more. I'd just make a list in the gen:set description or something. Carl, I dont see how guaranteeing some fallback implementations affects allowing more efficient versions. I think most programmers understand that the default implementation is probably not very efficient. Yes, but a default implementation doesn't have to be inefficient. Right now the fallback implementation of set=? and proper-subset? will be efficient if the implementation of subset? is efficient. Your proposal to make fallbacks depend only on primitive methods would prevent that. I don't understand why we'd want to prevent intelligent fallbacks like I've made the effort to write, just to draw a line in the sand. --Carl _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Actually, I am realizing that every derived method depends on set-stream, even the ones that don't document it (ie set-union, set-union!, set-intersect, set-intersect!, etc), since they use in-set. I was in the process of creating a patch for the docs to add the missing dependencies but I ran into an issue that I think warrants discussion. When the docs specifies dependencies for derived methods, there are actually two kinds that are being conflated. *** The first kind of dependency is stricter and requires the programmer to explicitly implement the required methods, and fallbacks do not count. In the code, this dependency is enforced with a call to the #:defined-predicated supplied to define-generics. Example: set-copy says it depends on set-clear and set-add!. Below is a set implementation that implements all the primitive methods plus set-stream. There exist set-clear and set-add! functions but set-clear is a fallback so set-copy wont work. Only if I explicitly implement set-clear will I get set-copy. (struct lstset (lst) #:transparent #:methods gen:set [(define (set-member? s x) (match s [(lstset lst) (member x lst)])) (define (set-add s x) (match s [(lstset lst) (lstset (cons x (filter (λ (y) (not (equal? y x))) lst)))])) (define (set-remove s x) (match s [(lstset lst) (lstset (remove x lst))])) (define (set-add! s x) (void)) (define (set-remove! s x) (void)) (define (set-stream s) (lstset-lst s))]) (set-add (lstset '(1 2)) 4) (lstset '(4 1 2)) (set-clear (lstset '(1 2))) (lstset '()) (set-copy (lstset '(1 2 3))) . . set-copy: not implemented for (lstset '(1 2 3)) *** The second kind of dependency is looser and allows fallbacks. For example set-count requires set-stream, but if I implement in-set, that is good enough. I guess my question is, is this a docs issue, or should the code have more calls to set-implements? On Fri, Aug 2, 2013 at 1:47 PM, Stephen Chang stch...@ccs.neu.edu wrote: With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Oh yeah, I like that better than moving set-stream to primitives since they are more standard set operations. Carl, I dont see how guaranteeing some fallback implementations affects allowing more efficient versions. I think most programmers understand that the default implementation is probably not very efficient. Vincent _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Yes, this is an issue. I kind of vaguely hint at it in the documentation, and didn't get around to making it an explicit point -- I use the phrase implements for things that have to be directly implemented, and supports for sort of transitive implements. I use in-set and things like it in some of the fallbacks because the dependencies for set-stream are somewhat complex, and I didn't want to repeat the logic in each and every case; I wanted to just call set-stream. At some point I tried to make an indirect helper that did dependency checking and reported errors in terms of the primary method being called, but it got a bit cumbersome. I probably should have seen through the better code and docs, but I sort of hit a point of I need to just push this and see how it goes. So, for documenting this, off the top of my head I'd define tech terms implemented method and supported method in the documentation for define-generics, and refer to them as necessary in methods for gen:set and so on. That way, saying that, for instance, set-count is a supported method whenever set-stream is a supported method, allows the documentation to imply all the direct dependencies of set-stream on things that need to be implemented methods, without having to restate them all. For the implementation, what we have would fit the docs, and it might also be possible to slightly improve the error messages with some refactoring. Carl Eastlund On Fri, Aug 2, 2013 at 3:43 PM, Stephen Chang stch...@ccs.neu.edu wrote: Actually, I am realizing that every derived method depends on set-stream, even the ones that don't document it (ie set-union, set-union!, set-intersect, set-intersect!, etc), since they use in-set. I was in the process of creating a patch for the docs to add the missing dependencies but I ran into an issue that I think warrants discussion. When the docs specifies dependencies for derived methods, there are actually two kinds that are being conflated. *** The first kind of dependency is stricter and requires the programmer to explicitly implement the required methods, and fallbacks do not count. In the code, this dependency is enforced with a call to the #:defined-predicated supplied to define-generics. Example: set-copy says it depends on set-clear and set-add!. Below is a set implementation that implements all the primitive methods plus set-stream. There exist set-clear and set-add! functions but set-clear is a fallback so set-copy wont work. Only if I explicitly implement set-clear will I get set-copy. (struct lstset (lst) #:transparent #:methods gen:set [(define (set-member? s x) (match s [(lstset lst) (member x lst)])) (define (set-add s x) (match s [(lstset lst) (lstset (cons x (filter (λ (y) (not (equal? y x))) lst)))])) (define (set-remove s x) (match s [(lstset lst) (lstset (remove x lst))])) (define (set-add! s x) (void)) (define (set-remove! s x) (void)) (define (set-stream s) (lstset-lst s))]) (set-add (lstset '(1 2)) 4) (lstset '(4 1 2)) (set-clear (lstset '(1 2))) (lstset '()) (set-copy (lstset '(1 2 3))) . . set-copy: not implemented for (lstset '(1 2 3)) *** The second kind of dependency is looser and allows fallbacks. For example set-count requires set-stream, but if I implement in-set, that is good enough. I guess my question is, is this a docs issue, or should the code have more calls to set-implements? On Fri, Aug 2, 2013 at 1:47 PM, Stephen Chang stch...@ccs.neu.edu wrote: With that in mind, I think it would make sense to move `set-first' and `set-empty?' to the primitive set (making it clear that they are optional, and can be derived from `set-stream' if need be). With those two in the primitive set, anything that implements all the primitives should get all the derived for free, right? Oh yeah, I like that better than moving set-stream to primitives since they are more standard set operations. Carl, I dont see how guaranteeing some fallback implementations affects allowing more efficient versions. I think most programmers understand that the default implementation is probably not very efficient. Vincent _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Hmm. Well, partially, I wasn't sure how to document the methods, because the relationships are complex, and because we don't have existing terminology or documentation patterns for this. I'm open to other suggestions, and especially (though not exclusively) to patches. For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. I can't remember, now, if I thought I had made the primitive ones sufficient, or if I knew there were others you needed to implement, or if I just forgot to think that whole thing through. Do you have examples of which ones don't come for free with the primitive methods? Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. You did document the dependencies, but some of them are circular, ie some derived rely on other derived. I'd definitely be happy to patch things myself, but I guess I dont have a concrete complaint yet :), only that the distinctions feel somewhat arbitrary and did not match my initial intuition, which is why I'm looking for additional insight. Do you have examples of which ones don't come for free with the primitive methods? Very few of the derived come free because most rely on set-stream, but set-stream is not primitive which is why I thought there might be a distinction between iterable sets and non-iterable. Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Ah, yes, set-stream isn't primitive because it can be derived if you have set-first and either set-rest or set-remove. And I know there are dependency cycles, this is intentional so that you can implement any one of several related things, but most of them were supposed to go all the way down to primitive methods (in some sense) if all else failed. Would it be better to just remove the primitve / derived distinction, since it's somewhat artificial, and leave it up to the individual method descriptions? Is there some better way I should be describing things? Carl Eastlund On Thu, Aug 1, 2013 at 6:51 PM, Stephen Chang stch...@ccs.neu.edu wrote: For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. You did document the dependencies, but some of them are circular, ie some derived rely on other derived. I'd definitely be happy to patch things myself, but I guess I dont have a concrete complaint yet :), only that the distinctions feel somewhat arbitrary and did not match my initial intuition, which is why I'm looking for additional insight. Do you have examples of which ones don't come for free with the primitive methods? Very few of the derived come free because most rely on set-stream, but set-stream is not primitive which is why I thought there might be a distinction between iterable sets and non-iterable. Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to
Re: [racket-dev] Generics updates
Would it be better to just remove the primitve / derived distinction, since it's somewhat artificial, and leave it up to the individual method descriptions? Is there some better way I should be describing things? Ok I can see now that there's no easy way to organize the methods. I think we should keep some distinction, since as a programmer it's good to know exactly what methods I have to implement. However, to me fallback implies that I should get it for free, so it seems most intuitive if derived methods only depend on primitive methods. Then for some subset of primitive methods that I implement, I should get the derived methods that depend on those primitives. I'll have to think more about what should be derived and primitive, but for now I think the easiest thing is to edit the docs to move set-stream (or some equivalent) into the primitive list? Carl Eastlund On Thu, Aug 1, 2013 at 6:51 PM, Stephen Chang stch...@ccs.neu.edu wrote: For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. You did document the dependencies, but some of them are circular, ie some derived rely on other derived. I'd definitely be happy to patch things myself, but I guess I dont have a concrete complaint yet :), only that the distinctions feel somewhat arbitrary and did not match my initial intuition, which is why I'm looking for additional insight. Do you have examples of which ones don't come for free with the primitive methods? Very few of the derived come free because most rely on set-stream, but set-stream is not primitive which is why I thought there might be a distinction between iterable sets and non-iterable. Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior
Re: [racket-dev] Generics updates
No, that doesn't work. If someone implements, say, an efficient subset? test, then set=? should use that rather than iterating using set-stream and set-member?. You should use the highest-level methods you can, in order to get the most out of an implementation. Which is why I made all the fallback implementations I did, to give implementers the best flexibility possible for getting a good implementation of all methods for the minimum possible effort on their part. Similarly, I don't want to make set-stream primitive, because if someone does implement set-first and set-rest, it should be derivable. Carl Eastlund On Thu, Aug 1, 2013 at 7:26 PM, Stephen Chang stch...@ccs.neu.edu wrote: Would it be better to just remove the primitve / derived distinction, since it's somewhat artificial, and leave it up to the individual method descriptions? Is there some better way I should be describing things? Ok I can see now that there's no easy way to organize the methods. I think we should keep some distinction, since as a programmer it's good to know exactly what methods I have to implement. However, to me fallback implies that I should get it for free, so it seems most intuitive if derived methods only depend on primitive methods. Then for some subset of primitive methods that I implement, I should get the derived methods that depend on those primitives. I'll have to think more about what should be derived and primitive, but for now I think the easiest thing is to edit the docs to move set-stream (or some equivalent) into the primitive list? Carl Eastlund On Thu, Aug 1, 2013 at 6:51 PM, Stephen Chang stch...@ccs.neu.edu wrote: For the other part, I either should have made it as you say -- implement the primitive ones and you get the others -- or else I should have clearly documented the relationship somewhere. You did document the dependencies, but some of them are circular, ie some derived rely on other derived. I'd definitely be happy to patch things myself, but I guess I dont have a concrete complaint yet :), only that the distinctions feel somewhat arbitrary and did not match my initial intuition, which is why I'm looking for additional insight. Do you have examples of which ones don't come for free with the primitive methods? Very few of the derived come free because most rely on set-stream, but set-stream is not primitive which is why I thought there might be a distinction between iterable sets and non-iterable. Carl Eastlund On Thu, Aug 1, 2013 at 6:27 PM, Stephen Chang stch...@ccs.neu.edu wrote: Just played a bit with gen:set. It looks great and in particular the fallback implementations are very convenient. One comment: the distinction between primitive methods and derived methods confused me somewhat. Can you explain the reasoning for determining which is which? For example, when I first read the docs, I thought that if I implemented the primitives, I would get the derived, but that's not the case since some of the derived methods depend on each other. Reading the docs more thoroughly, it sort of seems like there's an implicit separation along the lines of iterability, ie, derived sets are iterable since many of the derived methods require set-stream, but that's not exactly right either. On Thu, Jul 25, 2013 at 1:58 PM, Carl Eastlund c...@ccs.neu.edu wrote: After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types
Re: [racket-dev] Generics updates
After some fixes, mostly to contracts and documentation, I've pushed the new generics and set features to the master branch. Carl Eastlund On Tue, Jul 23, 2013 at 11:37 AM, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
I really like the new set features, especially mutable sets and lists as sets. Two things i have notices: * The docs for set-intersect seem a bit mixed up with set-union stuff * I could not get set-intersect on lists working, what i've tried - (set-intersect '(1 2 3) '(2 3 4)) ; set-add: contract violation ; expected: set? ; given: 2 - (set-intersect (list-set '(1 2 3)) '(2 3 4)) ; set-intersect: set arguments have incompatible equivalence predicates ; first set: (set 1 2 3) ; incompatible set: '(2 3 4) Tobias On Tue, 23 Jul 2013 17:37:15 +0200, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund -- - Tobias Hammer DLR / Robotics and Mechatronics Center (RMC) Muenchner Str. 20, D-82234 Wessling Tel.: 08153/28-1487 Mail: tobias.ham...@dlr.de _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] Generics updates
Thanks for those pointers, Tobias, I'll get those fixed. Carl Eastlund On Wed, Jul 24, 2013 at 1:34 PM, Tobias Hammer tobias.ham...@dlr.de wrote: I really like the new set features, especially mutable sets and lists as sets. Two things i have notices: * The docs for set-intersect seem a bit mixed up with set-union stuff * I could not get set-intersect on lists working, what i've tried - (set-intersect '(1 2 3) '(2 3 4)) ; set-add: contract violation ; expected: set? ; given: 2 - (set-intersect (list-set '(1 2 3)) '(2 3 4)) ; set-intersect: set arguments have incompatible equivalence predicates ; first set: (set 1 2 3) ; incompatible set: '(2 3 4) Tobias On Tue, 23 Jul 2013 17:37:15 +0200, Carl Eastlund c...@ccs.neu.edu wrote: My work on adding gen:set, and related changes to define-generics and gen:dict, is ready for review and (hopefully) to push to the master branch. The branch moved in the process of cleaning things up, it's now at: https://github.com/carl-**eastlund/racket/tree/generics-**from-scratchhttps://github.com/carl-eastlund/racket/tree/generics-from-scratch (The from scratch just refers to the process of rebuilding the git history, I didn't go out of my way to rewrite anything in the code base from scratch, although in some places a lot of code did move around.) What's new in the branch: - Generics now support a few new options - #:fallbacks specifies fallback method implementations for instances with no implementation - #:fast-defaults specifies instances on a fast path, useful for built-in types - #:defined-predicate gives a more intuitive and efficient interface than #:defined-table - #:derive-property allows generics to piggy-back on existing struct properties - Sets are now a generic datatype through gen:set - lists are now sets - the built-in set types are now documented as hash sets - there are mutable and weak hash sets - you can define new set types quickly with define-custom-set-types - most set operations are now methods with fallbacks - sets now support -copy and -clear operations, plus mutating [!] versions of operations - Dictionaries have a few changes - new macro define-custom-hash-types [*] - most dict operations are now methods with fallbacks - dicts now support -copy, -clear, -clear!, and -empty? operations I've run some benchmarks and performance of the various generic operations are comparable to the current HEAD, so there should be no major performance changes with this patch. [*] I've added define-custom-hash-types and define-custom-set-types rather than just adding make-custom-set akin to make-custom-hash because make-custom-hash is hard to use. The documented behavior -- that any custom hash is equal to any other created with the same bindings and predicates / hash functions -- was never true and can be expensive or at least tricky to implement. It seemed more sensible to just remove the erroneous documentation on make-custom-hash, and add the definition form to create constructors for new, explicitly-compatible dict and set types. Both definition forms bind predicates and constructors for new (set or dict) types with immutable, mutable, and weak variants that inter-operate. If there are no serious issues brought up in the next day or two, I'll push it to the development branch, since our current release process isn't following HEAD. Carl Eastlund -- --**--- Tobias Hammer DLR / Robotics and Mechatronics Center (RMC) Muenchner Str. 20, D-82234 Wessling Tel.: 08153/28-1487 Mail: tobias.ham...@dlr.de _ Racket Developers list: http://lists.racket-lang.org/dev