Skip to content
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

Add several pairs-related methods #3617

Merged
merged 9 commits into from
Dec 28, 2024
11 changes: 8 additions & 3 deletions M2/Macaulay2/d/actors2.dd
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ values(e:Expr):Expr := (
else WrongArg("a hash table or dictionary"));
setupfun("values",values);

pairs(e:Expr):Expr := (
export pairs(e:Expr):Expr := (
when e
is oc:DictionaryClosure do ( -- # typical value: pairs, Dictionary, List
o := oc.dictionary.symboltable;
Expand Down Expand Up @@ -142,8 +142,13 @@ pairs(e:Expr):Expr := (
while i < length(o) do (
provide Expr(Sequence(toExpr(i),o.i));
i = i+1;)))
is o:List do pairs(Expr(o.v)) -- # typical value: pairs, BasicList, List
else WrongArg("a hash table, a sequence, a list, or a raw polynomial"));
-- # typical value: pairs, BasicList, List
is o:List do (
r := pairs(Expr(o.v));
when r
is s:Sequence do list(o.Class, s, o.Mutable)
else buildErrorPacket("internal error; expected a sequence"))
Copy link
Member

Choose a reason for hiding this comment

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

when would pairs(Expr(o.v)) with o:List fail?

Copy link
Member Author

Choose a reason for hiding this comment

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

It shouldn't -- we should always get a sequence here. I don't expect we'll ever raise this error.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, unless pairs raises an error... I'll look into this more.

else applyEE(getGlobalVariable(pairsIteratorS), e)); -- # typical value: pairs, Thing, Iterator
Copy link
Member

Choose a reason for hiding this comment

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

fwiw I think putting the typical value tag on its own line would be better.

setupfun("pairs",pairs);

-- operators
Expand Down
33 changes: 32 additions & 1 deletion M2/Macaulay2/d/actors3.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use evaluate;
use actors;
use actors2;
use ballarith;

isOption(e:Expr):bool := (
Expand Down Expand Up @@ -82,7 +83,7 @@ override(e:Expr):Expr := (
if length(args) == 2 then (
when args.0
is h:HashTable do (
if h.Mutable then WrongArg("an immutable hash table")
if h.Mutable then WrongArgImmutableHashTable()
else when args.1 is v:Sequence do override(h,v,numOptions(v))
else override(h,Sequence(args.1),if isOption(args.1) then 1 else 0)
)
Expand Down Expand Up @@ -1895,6 +1896,22 @@ map(e:Expr):Expr := (
else WrongNumArgs(2,3));
setupfun("apply",map);

applyPairs(e:Expr):Expr := (
when e
is a:Sequence do (
if length(a) == 2 then (
when a.0
is o:HashTable do (
if o.Mutable then WrongArgImmutableHashTable(1)
else mappairs(a.1, o))
-- # typical value: applyPairs, BasicList, Function, List
-- # typical value: applyPairs, Dictionary, Function, List
-- # typical value: applyPairs, Thing, Function, Iterator
else map(pairs(a.0), a.1))
else WrongNumArgs(2))
else WrongNumArgs(2));
setupfun("applyPairs", applyPairs);

-- # typical value: scan, ZZ, Function, Thing
scan(n:int,f:Expr):Expr := (
if n <= 0 then return nullE;
Expand Down Expand Up @@ -2346,6 +2363,20 @@ scan(e:Expr):Expr := (
else WrongNumArgs(2));
setupfun("scan",scan);

-- # typical value: scanPairs, Thing, Function, Nothing
Copy link
Member

Choose a reason for hiding this comment

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

Since this line is for readability of documentation and doesn't have to be literally true, I wonder if it would be useful to use a dummy Iterable class instead of Thing for things like this. I know that practically anything with an iterator method defined on it can be iterable, so it may cause some confusion.

scanPairs(e:Expr):Expr := (
when e
is a:Sequence do (
if length(a) == 2 then (
when a.0
is o:HashTable do (
if o.Mutable then WrongArgImmutableHashTable(1)
else scanpairs(a.1, o))
else scan(pairs(a.0), a.1))
else WrongNumArgs(2))
else WrongNumArgs(2));
setupfun("scanPairs", scanPairs);

nextPrime(e:Expr):Expr := (
when e
is x:ZZcell do toExpr(nextPrime(x.v - oneZZ))
Expand Down
17 changes: 10 additions & 7 deletions M2/Macaulay2/d/actors4.d
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ select(e:Expr):Expr := (
else WrongNumArgs(2,5));
setupfun("select", select).Protected = false; -- will be overloaded in m2/lists.m2 and m2/regex.m2

-- # typical value: selectPairs, HashTable, Function, HashTable
-- # typical value: selectPairs, ZZ, HashTable, Function, HashTable
selectPairs(nval:int, obj:HashTable, f:Expr):Expr := (
Comment on lines +203 to 205
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 at some point we need to decide on a convention about where to place these lines. I don't find placing both of these here particularly useful. To me it either means one of them should be defined on the top level, or one of them is in the wrong place.

u := newHashTable(obj.Class,obj.parent);
u.beingInitialized = true;
Expand Down Expand Up @@ -228,18 +230,18 @@ selectPairs(nval:int, obj:HashTable, f:Expr):Expr := (
"expected predicate to yield true or false"));
p = p.next));
Expr(sethash(u,obj.Mutable)));
-- TODO: support iterators
selectPairs(e:Expr):Expr := (
when e
is a:Sequence do (
-- # typical value: selectPairs, HashTable, Function, HashTable
if length(a) == 2 then (
when a.0
is obj:HashTable do (
if obj.Mutable
then WrongArg(1, "an immutable hash table")
then WrongArgImmutableHashTable(1)
else selectPairs(obj.numEntries, obj, a.1))
else WrongArgHashTable(1))
-- # typical value: selectPairs, ZZ, HashTable, Function, HashTable
-- # typical value: selectPairs, BasicList, Function, List
else select(pairs(a.0), a.1))
else if length(a) == 3 then (
when a.0
is n:ZZcell do (
Expand All @@ -248,9 +250,10 @@ selectPairs(e:Expr):Expr := (
when a.1 is obj:HashTable
do (
if obj.Mutable
then WrongArg(2, "an immutable hash table")
then WrongArgImmutableHashTable(2)
else selectPairs(toInt(n), obj, a.2))
else WrongArgHashTable(2)))
-- # typical value: selectPairs, ZZ, BasicList, Function, List
else select(a.0, pairs(a.1), a.2, nullE, nullE)))
else WrongArgZZ(1))
else WrongNumArgs(2, 3))
else WrongNumArgs(2, 3));
Expand Down Expand Up @@ -298,7 +301,7 @@ any(f:Expr,e:Expr):Expr := (
is b:List do Expr(any(f,b.v))
is i:ZZcell do if isInt(i) then Expr(any(f,toInt(i))) else WrongArgSmallInteger(1)
is c:HashTable do
if c.Mutable then WrongArg(1,"an immutable hash table") else
if c.Mutable then WrongArgImmutableHashTable(1) else
Expr(any(f,c))
else WrongArg("a list or a hash table"));
any(f:Expr,a:Sequence,b:Sequence):Expr := (
Expand Down
41 changes: 9 additions & 32 deletions M2/Macaulay2/d/evaluate.d
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export iteratorS := setupvar("iterator", nullE);
export nextS := setupvar("next", nullE);
export applyIteratorS := setupvar("applyIterator", nullE);
export joinIteratorsS := setupvar("joinIterators", nullE);
export pairsIteratorS := setupvar("pairsIterator", nullE);

eval(c:Code):Expr;
applyEE(f:Expr,e:Expr):Expr;
Expand Down Expand Up @@ -1709,7 +1710,7 @@ setup(LeftArrowS,assigntofun);
idfun(e:Expr):Expr := e;
setupfun("identity",idfun);
-- # typical value: scanPairs, HashTable, Function, Nothing
scanpairs(f:Expr,obj:HashTable):Expr := ( -- obj is not Mutable
export scanpairs(f:Expr,obj:HashTable):Expr := ( -- obj is not Mutable
foreach bucket in obj.table do (
p := bucket;
while true do (
Expand All @@ -1719,22 +1720,10 @@ scanpairs(f:Expr,obj:HashTable):Expr := ( -- obj is not Mutable
p = p.next;
));
nullE);
scanpairsfun(e:Expr):Expr := (
when e is a:Sequence do
if length(a) == 2
then when a.0 is o:HashTable
do
if o.Mutable
then WrongArg("an immutable hash table")
else scanpairs(a.1,o)
else WrongArgHashTable(1)
else WrongNumArgs(2)
else WrongNumArgs(2));
setupfun("scanPairs",scanpairsfun);

mpre():Expr := buildErrorPacket("applyPairs: expected function to return null, a sequence of length 2, or an option x=>y");
-- # typical value: applyPairs, HashTable, Function, HashTable
mappairs(f:Expr,o:HashTable):Expr := ( -- o is not Mutable
export mappairs(f:Expr,o:HashTable):Expr := ( -- o is not Mutable
x := newHashTable(o.Class,o.parent);
x.beingInitialized = true;
foreach bucket in o.table do (
Expand Down Expand Up @@ -1762,18 +1751,6 @@ mappairs(f:Expr,o:HashTable):Expr := ( -- o is not Mutable
p = p.next;
));
Expr(sethash(x,o.Mutable)));
mappairsfun(e:Expr):Expr := (
when e is a:Sequence do
if length(a) == 2
then when a.0 is o:HashTable
do
if o.Mutable
then WrongArg("an immutable hash table")
else mappairs(a.1,o)
else WrongArgHashTable(1)
else WrongNumArgs(2)
else WrongNumArgs(2));
setupfun("applyPairs",mappairsfun);

-- # typical value: applyKeys, HashTable, Function, HashTable
export mapkeys(f:Expr,o:HashTable):Expr := ( -- o is not Mutable
Expand Down Expand Up @@ -1824,7 +1801,7 @@ mapkeysfun(e:Expr):Expr := (
then when a.0 is o:HashTable
do
if o.Mutable
then WrongArg("an immutable hash table")
then WrongArgImmutableHashTable()
else if length(a) == 2 then mapkeys(a.1,o) else mapkeysmerge(a.1,o,a.2)
else WrongArgHashTable(1)
else WrongNumArgs(2,3)
Expand Down Expand Up @@ -1864,7 +1841,7 @@ mapvaluesfun(e:Expr):Expr := (
then when a.0 is o:HashTable
do
if o.Mutable
then WrongArg("an immutable hash table")
then WrongArgImmutableHashTable()
else mapvalues(a.1,o)
else WrongArgHashTable(1)
else WrongNumArgs(2)
Expand Down Expand Up @@ -2066,18 +2043,18 @@ combine(e:Expr):Expr := (
is v:Sequence do
if length(v) == 5 then (
when v.0 is x:HashTable do
if x.Mutable then WrongArg(1,"an immutable hash table") else
if x.Mutable then WrongArgImmutableHashTable(1) else
when v.1 is y:HashTable do
if y.Mutable then WrongArg(2,"an immutable hash table") else
if y.Mutable then WrongArgImmutableHashTable(2) else
combine(v.2,v.3,v.4,x,y)
else WrongArgHashTable(2)
else WrongArgHashTable(1)
)
else if length(v) == 6 then (
when v.0 is x:HashTable do
if x.Mutable then WrongArg(1,"an immutable hash table") else
if x.Mutable then WrongArgImmutableHashTable(1) else
when v.1 is y:HashTable do
if y.Mutable then WrongArg(2,"an immutable hash table") else
if y.Mutable then WrongArgImmutableHashTable(2) else
twistCombine(v.2,v.3,v.4,v.5,x,y)
else WrongArgHashTable(2)
else WrongArgHashTable(1)
Expand Down
2 changes: 2 additions & 0 deletions M2/Macaulay2/d/expr.d
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ export WrongArgMatrix(n:int):Expr := WrongArg(n,"a raw matrix");
export WrongArgMatrix():Expr := WrongArg("a raw matrix");
export WrongArgHashTable():Expr := WrongArg("a hash table");
export WrongArgHashTable(n:int):Expr := WrongArg(n, "a hash table");
export WrongArgImmutableHashTable():Expr := WrongArg("an immutable hash table");
export WrongArgImmutableHashTable(n:int):Expr := WrongArg(n, "an immutable hash table");
Comment on lines 390 to +393
Copy link
Member

Choose a reason for hiding this comment

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

Seems to me like WrongArgHashTable should say immutable hash table and we should have a WrongArgMutableHashTable which says mutable hash table.

export ArgChanged(name:string,n:int):Expr := (
buildErrorPacket(quoteit(name) + " expected argument " + tostring(n)
+ " not to change its type during execution"));
Expand Down
20 changes: 11 additions & 9 deletions M2/Macaulay2/d/hashtables.dd
Original file line number Diff line number Diff line change
Expand Up @@ -255,17 +255,19 @@ export toHashTable(v:Sequence):Expr := (
Expr(sethash(o,false)));
toHashTable(e:Expr):Expr := (
when e
-- # typical value: hashTable, BasicList, HashTable
is w:List do toHashTable(w.v)
is s:Sequence do (
if length(s) != 2 then return WrongNumArgs(1,2);
when s.0
is FunctionClosure do nothing
is CompiledFunction do nothing
is CompiledFunctionClosure do nothing
else return WrongArg(1,"a function");
when s.1 is w:List do toHashTableWithCollisionHandler(w.v,s.0)
else WrongArg(2,"a list"))
else WrongArg("a list"));
if length(s) == 2 then (
if isFunction(s.0) then (
when s.1
-- # typical value: hashTable, Function, BasicList, HashTable
is w:Sequence do toHashTableWithCollisionHandler(w, s.0)
is w:List do toHashTableWithCollisionHandler(w.v, s.0)
else WrongArg(2, "a list or sequence"))
else toHashTable(s))
else toHashTable(s))
else WrongArg("a list or sequence"));
setupfun("hashTable",toHashTable);

copy(table:array(KeyValuePair)):array(KeyValuePair) := (
Expand Down
8 changes: 0 additions & 8 deletions M2/Macaulay2/d/pthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ startup(tb:TaskCellBody):null := (
compilerBarrier();
null());

isFunction(e:Expr):bool := (
when e
is CompiledFunction do true
is CompiledFunctionClosure do true
is FunctionClosure do true
is s:SpecialExpr do isFunction(s.e)
else false);

taskDone(tb:TaskCellBody):bool := tb.resultRetrieved || taskDone(tb.task);

cancelTask(tb:TaskCellBody):Expr := (
Expand Down
8 changes: 8 additions & 0 deletions M2/Macaulay2/d/util.d
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ export getSequenceOfMutableMatrices(e:Expr) : RawMutableMatrixArray := (
is a:RawMutableMatrixCell do RawMutableMatrixArray(a.p)
else RawMutableMatrixArray());

export isFunction(e:Expr):bool := (
when e
is CompiledFunction do true
is CompiledFunctionClosure do true
is FunctionClosure do true
is s:SpecialExpr do isFunction(s.e)
else false);

-----------------------------------------------------------------------------
-- helper routines for checking and converting return values

Expand Down
8 changes: 8 additions & 0 deletions M2/Macaulay2/m2/iterators.m2
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ joinIterators = a -> (
r))))

Iterator | Iterator := (x, y) -> joinIterators(x, y)

pairsIterator = x -> Iterator (
iter := iterator x;
i := 0;
() -> (
y := next iter;
if y === StopIteration then StopIteration
else (i, (i += 1; y))))
2 changes: 0 additions & 2 deletions M2/Macaulay2/m2/typicalvalues.m2
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ take(BasicList,ZZ) := take(BasicList,List) := BasicList => take
take(Thing,ZZ) := take(Thing,List) := List => take

isMutable(Thing) := Boolean => isMutable
hashTable List := HashTable => hashTable
hashTable(Function,List) := HashTable => hashTable
remove(MutableList,ZZ) := Nothing => remove
remove(Database,String) := Nothing => remove
remove(HashTable,Thing) := Nothing => remove
Expand Down
Loading
Loading