Skip to content

Commit

Permalink
ReplaceList.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Sep 19, 2017
1 parent 5f38203 commit 4cc0bed
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 22 deletions.
2 changes: 1 addition & 1 deletion expreduce/builtin_flowcontrol.go
Expand Up @@ -33,7 +33,7 @@ func applyWithFn(e *Expression, es *EvalState) (Ex, bool) {
setEx.Parts[2],
}))
}
return rulesReplace(e.Parts[2], rules, es), true
return rulesReplaceAll(e.Parts[2], rules, es), true
}

func GetFlowControlDefinitions() (defs []Definition) {
Expand Down
4 changes: 0 additions & 4 deletions expreduce/builtin_list.go
Expand Up @@ -578,9 +578,5 @@ func GetListDefinitions() (defs []Definition) {
defs = append(defs, Definition{Name: "Last"})
defs = append(defs, Definition{Name: "First"})
defs = append(defs, Definition{Name: "Rest"})
defs = append(defs, Definition{
Name: "ReplacePart",
OmitDocumentation: true,
})
return
}
58 changes: 56 additions & 2 deletions expreduce/builtin_replacement.go
Expand Up @@ -25,7 +25,7 @@ func getValidRules(ruleArg Ex) (rules []*Expression) {
return
}

func rulesReplace(e Ex, rules []*Expression, es *EvalState) Ex {
func rulesReplaceAll(e Ex, rules []*Expression, es *EvalState) Ex {
// TODO: fix the case where ReplaceAll[{x},{x->y,y->z}] returns incorrectly.
toReturn := e
for _, rule := range rules {
Expand All @@ -34,6 +34,39 @@ func rulesReplace(e Ex, rules []*Expression, es *EvalState) Ex {
return toReturn
}

func rulesReplace(e Ex, rules []*Expression, es *EvalState) (Ex, bool) {
for _, rule := range rules {
res, replaced := Replace(e, rule, es)
if replaced {
return res, true
}
}
return e, false
}

func replaceParts(e Ex, rules []*Expression, part *Expression, es *EvalState) Ex {
expr, isExpr := e.(*Expression)
if !isExpr {
return e.DeepCopy()
}
res := E(expr.Parts[0])
part.Parts = append(part.Parts, NewInt(0))
for i, p := range expr.Parts[1:] {
part.Parts[len(part.Parts)-1] = NewInt(int64(i+1))
repVal, replaced := rulesReplace(part, rules, es)
if !replaced && len(part.Parts) == 2 {
repVal, replaced = rulesReplace(part.Parts[1], rules, es)
}
if replaced {
res.Parts = append(res.Parts, repVal)
} else {
res.Parts = append(res.Parts, replaceParts(p, rules, part, es))
}
}
part.Parts = part.Parts[:len(part.Parts)-1]
return res
}

func getReplacementDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "ReplaceAll",
Expand All @@ -52,7 +85,7 @@ func getReplacementDefinitions() (defs []Definition) {
if len(rules) == 0 {
return this
}
return rulesReplace(this.Parts[1], rules, es)
return rulesReplaceAll(this.Parts[1], rules, es)
},
})
defs = append(defs, Definition{
Expand Down Expand Up @@ -125,5 +158,26 @@ func getReplacementDefinitions() (defs []Definition) {
return ToStringInfixAdvanced(this.Parts[1:], " :> ", true, "", "", form, context, contextPath)
},
})
defs = append(defs, Definition{
Name: "ReplacePart",
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
return this
}
rules, isList := HeadAssertion(this.Parts[2], "System`List")
if !isList {
return this
}
exprRules := [](*Expression){}
for _, rulesPart := range rules.Parts[1:] {
rule, isRule := HeadAssertion(rulesPart, "System`Rule")
if !isRule {
return this
}
exprRules = append(exprRules, rule)
}
return replaceParts(this.Parts[1], exprRules, E(S("List")), es)
},
})
return
}
4 changes: 4 additions & 0 deletions expreduce/ex_expression.go
Expand Up @@ -495,6 +495,10 @@ func NewExpression(parts []Ex) *Expression {
}
}

func E(parts ...Ex) *Expression {
return NewExpression(parts)
}

func NewHead(head string) *Expression {
return NewExpression([]Ex{&Symbol{head}})
}
Expand Down
4 changes: 4 additions & 0 deletions expreduce/ex_symbol.go
Expand Up @@ -262,3 +262,7 @@ func ContainsSymbol(e Ex, name string) bool {
}
return false
}

func S(name string) Ex {
return &Symbol{"System`" + name}
}
39 changes: 31 additions & 8 deletions expreduce/resources.go

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions expreduce/resources/list.m
Expand Up @@ -378,10 +378,3 @@
ESameTest[foo[a,b,c], Join[foo[a],foo[b,c]]]
]
};

ReplacePart[e_?((! AtomQ[#]) &), r_, i_Integer?Positive] :=

If[i <= Length[e] === True,
Join[e[[1 ;; i - 1]], Head[e][r], e[[i + 1 ;; Length[e]]]],
Print["Index too large for ReplacePart!"]];
ReplacePart[___] := Print["Invalid call to ReplacePart!"];
34 changes: 34 additions & 0 deletions expreduce/resources/replacement.m
Expand Up @@ -195,3 +195,37 @@
ESameTest[False, Equal @@ ({1, 1} /. 1 :> RandomReal[])]
]
};

ReplacePart::usage = "`ReplacePart[e, {loc1 -> newval1, ...}]` replaces the value at the locations with their corresponding new values in `e`.";
Attributes[ReplacePart] = {Protected};
ReplacePart[e_?((! AtomQ[#]) &), r_, i_Integer?Positive] :=

If[i <= Length[e] === True,
Join[e[[1 ;; i - 1]], Head[e][r], e[[i + 1 ;; Length[e]]]],
Print["Index too large for ReplacePart!"]];
ReplacePart[e_, r_Rule] := ReplacePart[e, {r}];
Tests`ReplacePart = {
ESimpleExamples[
ESameTest[{1,foo,3,4}, ReplacePart[Range[4],foo,2]],
ESameTest[{1,2,foo,4}, ReplacePart[Range[4],3->foo]],
ESameTest[{1,2,foo,4}, ReplacePart[Range[4],{3}->foo]],
ESameTest[{1,2,3,4}, ReplacePart[Range[4],{3,1}->foo]],
], EFurtherExamples[
ESameTest[{foo,foo,foo,foo}, ReplacePart[Range[4],i_->foo]],
ESameTest[{1,2,3,4}, ReplacePart[Range[4],7->foo]],
ESameTest[a+b^foo, ReplacePart[a+b^c,{2,2}->foo]],
ESameTest[a+b^c, ReplacePart[a+b^c,{2,2,1}->foo]],
], ETests[
ESameTest[a+foo^foo, ReplacePart[a+b^c,{2,_}->foo]],
ESameTest[a+b^foo, ReplacePart[a+b^c,{{2,2}->foo}]],
ESameTest[b^foo+foo, ReplacePart[a+b^c,{{2,2}->foo,{1}->foo}]],
ESameTest[b^foo+foo, ReplacePart[a+b^c,{{1}->foo,{2,2}->foo}]],
ESameTest[ReplacePart[a+b^c,{{1}->foo,bar}], ReplacePart[a+b^c,{{1}->foo,bar}]],
ESameTest[3, ReplacePart[a+b^c,{{a_}->a}]],
ESameTest[hi, ReplacePart[hi,{{a_}->a}]],
ESameTest[a+foo[1]^foo[2], ReplacePart[a+b^c,{{_,a_}->foo[a]}]],
], EKnownFailures[
ESameTest[foo[a,b^c], ReplacePart[a+b^c,{{0}->foo}]],
ESameTest[a+foo, ReplacePart[a+b^c,{{-1}->foo}]],
]
};
4 changes: 4 additions & 0 deletions expreduce/resources/rubi.m
Expand Up @@ -12,5 +12,9 @@
ESameTest[-((3/2+2 x)^2/(3 x^2)), Rubi`Int[(3/2+2 x)/x^3,x]],
], ETests[
ESameTest[x^3/3, Rubi`Int[x^2, x]],
], EKnownFailures[
(*Will not work until we add support for FixIntRules. Coefficients
will not distribute.*)
ESameTest[-(3/8) ArcTanh[Cos[a+x]]-3/8 Cot[a+x] Csc[a+x]-1/4 Cot[a+x] Csc[a+x]^3, Rubi`Int[csc[a+x]^5,x]],
]
};

0 comments on commit 4cc0bed

Please sign in to comment.