diff --git a/M2/Macaulay2/d/evaluate.d b/M2/Macaulay2/d/evaluate.d index 8c4629f4cb..503dc262b6 100644 --- a/M2/Macaulay2/d/evaluate.d +++ b/M2/Macaulay2/d/evaluate.d @@ -1236,16 +1236,37 @@ tryEval(c:Code):Expr := ( else tryEvalSuccess = true); p); +nullify(c:Code):Expr := ( + e := tryEval(c); + if tryEvalSuccess + then ( + when e + is Nothing do e + else ( + f := lookup(Class(e), QuestionQuestionS); + if f == nullE then e + else applyEE(f, e))) + else nullE); + +nullCoalescion(lhs:Code,rhs:Code):Expr := ( + e := nullify(lhs); + when e + is Nothing do eval(rhs) + else e); +setup(QuestionQuestionS, nullify, nullCoalescion); + augmentedAssignmentFun(x:augmentedAssignmentCode):Expr := ( when lookup(x.oper.word, augmentedAssignmentOperatorTable) is null do buildErrorPacket("unknown augmented assignment operator") is s:Symbol do ( -- evaluate the left-hand side first lexpr := nullE; - if s.word.name === "??" -- null coalescion; ignore errors + if s.word.name === "??" -- x ??= y is treated like x ?? (x = y) then ( - e := tryEval(x.lhs); - if tryEvalSuccess then lexpr = e) + e := nullify(x.lhs); + when e + is Nothing do nothing + else return e) else lexpr = eval(x.lhs); left := evaluatedCode(lexpr, dummyPosition); when left.expr is e:Error do return Expr(e) else nothing; @@ -2091,25 +2112,6 @@ export notFun(a:Expr):Expr := if a == True then False else if a == False then Tr -- to evaluate methods in hashtables.dd before it is defined. applyEEEpointer = applyEEE; -nullify(c:Code):Expr := ( - e := tryEval(c); - if tryEvalSuccess - then ( - when e - is Nothing do e - else ( - f := lookup(Class(e), QuestionQuestionS); - if f == nullE then e - else applyEE(f, e))) - else nullE); - -nullCoalescion(lhs:Code,rhs:Code):Expr := ( - e := nullify(lhs); - when e - is Nothing do eval(rhs) - else e); -setup(QuestionQuestionS, nullify, nullCoalescion); - -- Local Variables: -- compile-command: "echo \"make: Entering directory \\`$M2BUILDDIR/Macaulay2/d'\" && make -C $M2BUILDDIR/Macaulay2/d evaluate.o " -- End: diff --git a/M2/Macaulay2/packages/Macaulay2Doc/doc_augmented_assignment.m2 b/M2/Macaulay2/packages/Macaulay2Doc/doc_augmented_assignment.m2 index 963572217d..f782164e4b 100644 --- a/M2/Macaulay2/packages/Macaulay2Doc/doc_augmented_assignment.m2 +++ b/M2/Macaulay2/packages/Macaulay2Doc/doc_augmented_assignment.m2 @@ -112,7 +112,10 @@ doc /// The null coalescing operator can be combined with @TO "augmented assignment"@ as a shortcut for @M2CODE "if x === null then x = y"@ and - @M2CODE "if not x#?i then x#i = y"@. + @M2CODE "if not x#?i then x#i = y"@. Note that it behaves + slightly differently than other augmented assignment operators, + as @CODE "x ??= y"@ is treated like @CODE "x ?? (x = y)"@ rather + than @CODE "x = x ?? y"@. Example x = null x ??= 2 diff --git a/M2/Macaulay2/tests/normal/augmented-assignment.m2 b/M2/Macaulay2/tests/normal/augmented-assignment.m2 index 40532d68c5..d2255a056d 100644 --- a/M2/Macaulay2/tests/normal/augmented-assignment.m2 +++ b/M2/Macaulay2/tests/normal/augmented-assignment.m2 @@ -157,3 +157,7 @@ assert BinaryOperation(symbol ===, y ?? x, y) assert BinaryOperation(symbol ===, x ?? y, y) x ??= y assert BinaryOperation(symbol ===, x, y) + +-- issue #3612 +h = new HashTable from { symbol cache => new CacheTable }; +h.cache ??= new CacheTable