-
-
Notifications
You must be signed in to change notification settings - Fork 511
Add Map module & tests #715
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
Conversation
sledorze
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments regarding conservative operations in case of a noop
|
@joshburgess thanks for this PR Not sure I understand what's the problem with jest ( I propose the following changes:
Also looks like some functions could be optimized using an iterator instead of Example export const compact = <K, A>(fa: Map<K, Option<A>>): Map<K, A> => {
const m = new Map<K, A>()
const entries = fa.entries()
let e: IteratorResult<[K, Option<A>]>
while (!(e = entries.next()).done) {
const [k, oa] = e.value
if (oa.isSome()) {
m.set(k, oa.value)
}
}
return m
} |
I get 68 errors saying |
|
@joshburgess no |
Hmm, I'm not sure what the problem is. If you google for it, there are many issues about it on GitHub. They all suggest adding this I can't seem to run the tests without it. I'll make the other suggested changes tomorrow. |
|
@joshburgess Can you check your |
References to |
|
@joshburgess have you tried |
Just tried it. Yes, this fixed it. |
I'm not 100% sure, to be honest. I was just following what had already been done for |
|
@joshburgess Legacy. They predate the |
|
@gcanti Can you explain how I should be using the |
|
@joshburgess native So for example let's see /**
* Lookup the value for a key in a `Map`.
* If the result is a `Some`, the existing key is also returned.
*/
export function lookupWithKey<K>(S: Setoid<K>): <A>(k: K, m: Map<K, A>) => Option<[K, A]> {
return <A>(k: K, m: Map<K, A>) => {
const entries = m.entries()
let e: IteratorResult<[K, A]>
while (!(e = entries.next()).done) {
const [ka, a] = e.value
if (S.equals(ka, k)) {
return some(tuple(k, a))
}
}
return none
}
}
/**
* Lookup the value for a key in a `Map`.
*/
export function lookup<K>(S: Setoid<K>): <A>(k: K, m: Map<K, A>) => Option<A> {
const lookupWithKeyS = lookupWithKey(S)
return (k, m) => lookupWithKeyS(k, m).map(([_, a]) => a)
}and export function insertAt<K>(S: Setoid<K>): <A>(k: K, a: A, m: Map<K, A>) => Map<K, A> {
const lookupWithKeyS = lookupWithKey(S)
return (k, a, m) => {
const found = lookupWithKeyS(k, m)
if (found.isNone()) {
const r = new Map(m)
// add the value
r.set(k, a)
return r
} else if (found.value[1] !== a) {
const r = new Map(m)
// overwrite the existing key
r.set(found.value[0], a)
return r
}
return m
}
} |
|
@gcanti I think I addressed all of your feedback. The only thing I didn't change that you suggested was adding overloads to Also, I had to add an Also, I removed Could you look over the changes to see whether or not they look good before I go to update the tests? |
Sure, I need some time though. In the meanwhile..
see this PR |
|
Renaming
Group constraints
Optimizations There are many low hanging fruits like this: Current export const lookup = <K>(S: Setoid<K>) => <A>(k: K, m: Map<K, A>): Option<A> => {
const lookupWithKeyS = lookupWithKey(S) // <= created each time
return lookupWithKeyS(k, m).map(([_, a]) => a)
}Better export function lookup<K>(S: Setoid<K>): <A>(k: K, m: Map<K, A>) => Option<A> {
const lookupWithKeyS = lookupWithKey(S) // <= created once
return (k, m) => lookupWithKeyS(k, m).map(([_, a]) => a)
} |
This seems weird to me. The Array module doesn't currently do this. It uses I think I would prefer |
I made both of these changes. There are no longer any dependencies from Array or Set included in this Map module.
Actually, I think I may have misspoke. I'll think about this a bit and get back to you. I'll open an issue and/or PR if I think there's a way. |
|
@gcanti @texastoland List of new changes other than the above elimination of dependencies:
NOTE: The only odd thing about |
👍 @joshburgess to recap shouldn't be? (*)
EDIT: ^ this is wrong I think that we should establish once for all whether this module manages only "valid" maps (<= I strongly vote for this) or not.
|
|
Also, just added a new |
Hmm, I'm not sure. I was thinking that the I think it's okay that some of them would share the same type signature, because the implementation is different (a lookup based on the key vs a "lookup" based on the value). In other words, I was tying the name
Can you further elaborate on this? Sorry, I don't fully understand what you mean by "valid" here. |
|
Constraints and general assumptions
By "valid" I mean there's no duplicated keys. Let's consider Current signature: lookup = <K>(S: Setoid<K>): (<A>(k: K, m: Map<K, A>) => Option<A>)Now if we don't assume that there's no duplicate keys in lookup = <K>(S: Setoid<K>): (<A>(k: K, m: Map<K, A>) => Array<A>)since it may return EDIT: and since lookup = <K>(O: Ord<K>): (<A>(k: K, m: Map<K, A>) => Array<A>)I think that the general assumption we should make for this module is the following
As a consequence Drop Thinking twice, I'm not sure this function makes sense: values, as opposed to keys, may be duplicated. Let's drop it. |
@joshburgess ah that's right.. both EDIT: just noticed a |
|
Ok, I deleted those functions & their tests, but the build is failing now for some reason: |
|
@joshburgess Thanks! |
This PR does the following:
I want to help work on adding a String module next. :)