-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Style guide for base library #8
Comments
Thanks @chenyan-dfinity for starting this discussion. I agree. I think OO vs procedural is the most difficult question to answer. Previously I would have tended towards OO, not because I particularly like it (I don't), but because it's a much better fit for our target audience. And because it's the only way currently to provide encapsulation. But stable variables may change this picture, since we cannot currently allow objects in there. OTOH, it is too early to change directions for the sake of stable (we need some practical proof of their viability first). A compromise might be to have classes as wrappers around procedural interfaces for everything, but the duplication may also be confusing. What does everybody think? |
A few more random thoughts, independent of OO vs PP: Naming:
Types:
Data structures:
Should we take clues from Scala's collection library? Minus the overengineering, of course, more wrt to conventions. |
I think that we do need a style guide, and that sometime soon, the base library should conform to it. However, as we are discussing and realizing, the best style is not always so clear. Thankfully, in many cases above, it is. All of the stuff that Andreas lists above as "Naming" and "Types" seems reasonable to me, and to be consistent with what we've been doing (or aiming to do). However, for "Data structures", things are less clear, at least to me, currently. I agree with the first point (sometimes we want both FP and OO interfaces, and sometimes we only want an OO interface). For things that seem more like functors but that are not classes (so, not In those cases, we often want a type with associated operations, like the param to a functor. I have not tried writing a function that accepts a module, but I have tried doing some things this week (with Claudio's help) involving this pattern, where one module is parameterized by the types and operations of another. (I'm trying to make the Adapton graph code separate from the "CleanSheets" DSL evaluator). Even using a |
If I understand this suggestion, then the Red Black tree module follows it, within a single module. Perhaps we should do a merging of |
Ah, you are right about the type capture issue. Damn, I think we need to get back to and improve our nested types semantics... I don't necessarily think that the OO and PP interface need to be in the same module. It's probably less confusing if they aren't. |
I never quite understand Following the discussion, I have a PR to refactor Heap: #11. And I feel the Heap class I am writing there looks like a functor. I also left some questions there, feel free to leave comments. |
@chenyan-dfinity I also want to discuss this question ("how do we do functors in Motoko?, always with a I'm creating a companion issue to this one for that tangent #13 |
@chenyan-dfinity, classes are intended to mirror typical OO-classes (in as simple a way as possible). Emulating functors doesn't really work with them until we relax our restriction on free type vars in type defs. But classes aren't meant to be functors anyway. True functors would take and return a module. They would require dependent type paths and abstract type members. Not currently a priority. :) |
@rossberg One clarification: All such orderings are total (not partial?), right? (So that |
@matthewhammer, yes, I would e.g. define it as In cases where partial orders arise, maybe the natural type to use would be |
hmm, Also for priority queue, I assume we want to take a partial order, so that heapsort becomes a topological sort. |
@chenyan-dfinity, I don't understand, why is |
ah, okay. Total order has the same problem: if For partial order, if we return |
Well, the type system also cannot prevent an order that isn't transitive. Or not reflexive. Or one that returns true one time and false the next. So I don't know if symmetry is a property particularly worth worrying about. The problem with a Bool is that you typically need twice as many comparisons to figure out the case you're in. If they are expensive that's undesirable. |
Okay, I switched back from |
I think we need a style guide for base library. There are already some inconsistencies in the existing modules.
Several items I would like to discuss here:
List
doesn't have a class interface.Trie
provides a class interface in a separate fileTrieMap
.We use
public class Container<T>(ord : (T, T) -> Bool)
for taking theord
relation. Does this mean that all the methods should stay inside the class. Because methods outside of the class will need to take bothord
andContainer
as arguments, and this can lead to inconsistency.type Container<T> = ...; public class MakeContainer<T>(eq)
. The usual convention is to uset
for value type andmkContainer
for constructor. Butt<T>
looks odd, and we usually name the constructor as a type name.The code then looks like
let buf : Buf.Buf<Int> = Buf.Buf<Int>(10)
. Doeslet buf : Buf.t<Int> = Buf.mkBuf<Int>(10)
feel better?add
vsinsert
;remove
vsdelete
; doesadd
return a value; doesremove
trap for empty container; doesremove
return the removed elements; etc.The text was updated successfully, but these errors were encountered: