Skip to content

fix set Set, add toList Tally #3770

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

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open

Conversation

pzinn
Copy link
Contributor

@pzinn pzinn commented May 2, 2025

this is another (minor) fix of #3574: the definition of set Set didn't work since set is defined at d level.
Instead we let set be equivalent to set @@ keys on hash tables. We also add a missing toList Tally.

@@ -19,6 +19,7 @@ makeSet(e:Expr):Expr := (
is v:Sequence do makeSet(v)
is w:List do if ancestor(w.Class,visibleListClass) then makeSet(w.v)
else WrongArg("a visible list")
is h:HashTable do makeSet(keys(h))
Copy link
Member

@mahrud mahrud May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a typical value comment so methods set also lists (set, HashTable)? Also this should be documented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, actually, this is worse than set Set := identity because it allocates new memory, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I'll rewrite it more cleanly, more like top-level applyValues(h,x->1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, an easier solution might be to make it so people can install methods on set!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I don't know about that. we've been doing that a lot (superseding the d function, e.g., toList has suffered this fate) but I don't think it's great, it's not very clean. I'd rather basic functions like set be at d level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's not clean is having a d function, then renaming it at the m2 level, then introducing a new m2 function which shares the same name as the original d function but which potentially behaves differently. it's not good practice and can make debugging confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another common approach is to give the d function a slightly different name, often appending "0" to the name. So set could be the method function, and some of the installed methods could be the compiled function set0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppose you could declare methods in the interpreter and directly install new method functions on them in the top level. Would this be confusing? I agree that renaming the function and assigning a method is kind of hacky (and the set0 trick is not much better), but the solution to that is to make it possible to declare methods in the interpreter, not prevent set from becoming a method in the top level!

Copy link
Contributor Author

@pzinn pzinn May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppose you could declare methods in the interpreter and directly install new method functions on them in the top level.

yeah that'd be nice... but unless I'm mistaken this isn't currently possible. I was trying to keep this PR to a minimum.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's not possible. My point was that what you called unclean is a kludge until we have this feature, not that you should implement it now :)

Anyway, I think I'd like set to become a method, either in this PR or another time.

@@ -15,7 +15,7 @@ tally String :=
tally VisibleList := Tally => tally

elements = method()
elements Tally := x -> splice apply(pairs x, (k,v) -> v:k)
elements Tally := toList Tally := x -> splice apply(pairs x, (k,v) -> v:k)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you document (toList, Tally) (perhaps just adding it to the documentation of (elements, Tally)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decided to add it to toList... but why does the doc say that the input can be an integer??

A, a set, a string, a basic list, *or an integer*, or an instance of a class with the iterator method installed

@pzinn
Copy link
Contributor Author

pzinn commented May 6, 2025

I think Set entries be sorted when printed, just like HashTable -- I really don't like

i1 : set {a,b,c}

o1 = set {c, a, b}

o1 : Set

@@ -1240,7 +1240,7 @@ texMath MapExpression := x -> texMath x#0 | "\\," | (if #x>2 then "\\xleftarrow{
expressionValue MapExpression := x -> map toSequence apply(x,expressionValue)

-- moved from set.m2 because of loadsequence order
expression Set := x -> Adjacent {set, expression keys x}
expression Set := x -> Adjacent {set, expression sortByName keys x}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you want to sort for two reasons:

  1. it's slow, for no reason other than aesthetics.
  2. it can be misleading if the order of keys S and net S are different.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then why do we do it for HashTable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably shouldn't, it's misleading.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so should I just revert the sorting for Set, or also remove the sorting for HashTable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just remove it here for now, but separately we should discuss whether both should be sorted or unsorted.

@d-torrance d-torrance added under discussion Core Issues involving the Core scripts. Interpreter labels May 8, 2025
@mahrud mahrud mentioned this pull request May 11, 2025
@n-m-g
Copy link
Contributor

n-m-g commented May 21, 2025

I don't know too much about the background on this specific topic but I agree that it shouldn't matter if hashTable keys are sorted or not. (At least all checks seem to have passed so it is probably OK.) However, a situation where this might be used (and which might cause bugs that are difficult to detect) is the case of a hash table with integer keys. One would need to look into that further and some methods may implicitly assume the keys to be sorted. A related topic concerns the "spots" function (which I learned from Dan Grayson's ChainComplex code many years ago) and which I think should be part of the core. But this "spots" function and its need has caused some controversy. The aim of the sports function is to output the sorted integer keys (if any) of a hashTable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submodules were inadvertently changed.

This comment was marked as off-topic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can I revert the submodule change? this is driving me crazy.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following should get you back to where it's supposed to be (possibly replacing origin with whatever remote you use for the main M2 repo):

git checkout origin/development -- M2/submodules/googletest

@pzinn
Copy link
Contributor Author

pzinn commented Jun 4, 2025

Rereading the changes in this PR, was toList ZZ supposed to be like

toList ZZ := n -> toList(0..n-1)

that would be pretty useful

@mahrud
Copy link
Member

mahrud commented Jun 4, 2025

Rereading the changes in this PR, was toList ZZ supposed to be like

toList ZZ := n -> toList(0..n-1)

that would be pretty useful

I would be worried about people using apply(toList N, ...) instead of just apply(N, ...).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Issues involving the Core scripts. Interpreter under discussion
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants