Skip to content

Commit 031aed6

Browse files
committed
Improve AssociateTo for Part(Symbol,...) argument
1 parent 2f7a2ac commit 031aed6

File tree

4 files changed

+59
-11
lines changed

4 files changed

+59
-11
lines changed

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/Arithmetic.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,9 @@ protected ISymbol getArithmeticSymbol() {
433433
}
434434

435435
private IExpr assignPart(IExpr part, IExpr value, EvalEngine engine) {
436-
IExpr oldResult = engine.evaluate(part);
436+
IExpr oldValue = engine.evaluate(part);
437437
IASTMutable operator = getAST(value);
438-
operator.set(1, oldResult);
438+
operator.set(1, oldValue);
439439
IExpr newResult = engine.evaluate(operator);
440440
engine.evaluate(F.Set(part, newResult));
441441
return newResult;

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/AssociationFunctions.java

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,16 +146,52 @@ public IExpr apply(final IExpr symbolValue) {
146146

147147
@Override
148148
public IExpr evaluate(final IAST ast, EvalEngine engine) {
149-
IExpr sym = Validate.checkSymbolType(ast, 1, engine);
150-
if (sym.isPresent()) {
151-
IExpr arg2 = engine.evaluate(ast.arg2());
152-
Function<IExpr, IExpr> function = new AssociateToFunction(arg2);
153-
IExpr[] results = ((ISymbol) sym).reassignSymbolValue(function, S.AssociateTo, engine);
154-
if (results != null) {
155-
return results[1];
149+
IExpr leftHandSide = ast.arg1();
150+
try {
151+
if (leftHandSide.isSymbol()) {
152+
ISymbol sym = (ISymbol) leftHandSide;
153+
IExpr arg2 = engine.evaluate(ast.arg2());
154+
Function<IExpr, IExpr> function = new AssociateToFunction(arg2);
155+
IExpr[] results = ((ISymbol) sym).reassignSymbolValue(function, S.AssociateTo, engine);
156+
if (results != null) {
157+
return results[1];
158+
}
159+
return F.NIL;
160+
}
161+
if (leftHandSide.isASTSizeGE(S.Part, 3) && leftHandSide.first().isSymbol()) {
162+
ISymbol sym = (ISymbol) leftHandSide.first();
163+
return assignPartTo(sym, (IAST) leftHandSide, ast, engine);
164+
}
165+
} catch (ValidateException ve) {
166+
if (FEConfig.SHOW_STACKTRACE) {
167+
ve.printStackTrace();
168+
}
169+
return engine.printMessage(ast.topHead(), ve);
170+
}
171+
// `1` is not a variable with a value, so its value cannot be changed.
172+
return IOFunctions.printMessage(ast.topHead(), "rvalue", F.List(leftHandSide), engine);
173+
}
174+
175+
private static IExpr assignPartTo(
176+
ISymbol symbol, IAST part, final IAST ast, EvalEngine engine) {
177+
if (symbol.hasAssignedSymbolValue()) {
178+
IExpr value = ast.arg2();
179+
if (value.isRuleAST() || value.isListOfRules() || value.isAssociation()) {
180+
IExpr oldValue = engine.evaluate(part);
181+
if (oldValue.isAssociation()) {
182+
IAssociation newResult = ((IAssociation) oldValue).copy();
183+
newResult.appendRules((IAST) value);
184+
engine.evaluate(F.Set(part, newResult));
185+
return symbol.assignedValue();
186+
}
187+
// The argument `1` is not a valid Association.
188+
return IOFunctions.printMessage(ast.topHead(), "invak", F.List(oldValue), EvalEngine.get());
156189
}
190+
// The argument is not a rule or a list of rules.
191+
return IOFunctions.printMessage(ast.topHead(), "invdt", F.List(), EvalEngine.get());
157192
}
158-
return F.NIL;
193+
// `1` is not a variable with a value, so its value cannot be changed.
194+
return IOFunctions.printMessage(ast.topHead(), "rvalue", F.List(symbol), engine);
159195
}
160196

161197
@Override

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/IOFunctions.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,10 @@ protected static void printExpression(
555555
"Positive machine-sized integer expected at position `2` in `1`.", //
556556
"intrange",
557557
"Integer expected in range `1` to `2`.", //
558-
"invdt",
558+
"invak",
559559
"The argument is not a rule or a list of rules.", //
560+
"invdt",
561+
"The argument `1` is not a valid Association.", //
560562
"invrl",
561563
"The argument `1` is not a valid Association or a list of rules.", //
562564
"iterb",

symja_android_library/matheclipse-io/src/test/java/org/matheclipse/io/system/AssociationTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ public void testAssociateTo() {
4646
check(
4747
"AppendTo(assoc, assoc2)", //
4848
"<|a->1,b->2,c->3|>");
49+
50+
check(
51+
"a = {Association({a -> 1, b -> 2}), Association({c -> 3, d -> 4})}", //
52+
"{<|a->1,b->2|>,<|c->3,d->4|>}");
53+
check(
54+
"AssociateTo(a[[2]], c->17)", //
55+
"{<|a->1,b->2|>,<|c->17,d->4|>}");
56+
check(
57+
"a", //
58+
"{<|a->1,b->2|>,<|c->17,d->4|>}");
4959
}
5060

5161
public void testAssociation() {

0 commit comments

Comments
 (0)