Skip to content

Commit 4050745

Browse files
committed
Start MapAt
1 parent e32dc23 commit 4050745

2 files changed

Lines changed: 47 additions & 19 deletions

File tree

mathics/builtin/lists.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
PartError, PartDepthError, PartRangeError, Predefined, SympyFunction)
1414
from mathics.builtin.scoping import dynamic_scoping
1515
from mathics.builtin.base import MessageException, NegativeIntegerException, CountableInteger
16-
from mathics.core.expression import Expression, String, Symbol, Integer, Number, Real, strip_context, from_python
16+
from mathics.core.expression import Expression, String, Symbol, SymbolNull, Integer, Number, Real, strip_context, from_python
1717
from mathics.core.expression import min_prec, machine_precision
1818
from mathics.core.expression import structure
1919
from mathics.core.evaluation import BreakInterrupt, ContinueInterrupt, ReturnInterrupt
@@ -37,8 +37,8 @@
3737
def deletecases_with_levelspec(expr, pattern, evaluation, levelspec=1, n=-1 ):
3838
"""
3939
This function walks the expression `expr` and deleting occurrencies of `pattern`
40-
41-
If levelspec specifies a number, only those positions with `levelspec` "coordinates" are return. By default, it just return occurences in the first level.
40+
41+
If levelspec specifies a number, only those positions with `levelspec` "coordinates" are return. By default, it just return occurences in the first level.
4242
If a tuple (nmin, nmax) is provided, it just return those occurences with a number of "coordinates" between nmin and nmax.
4343
n indicates the number of occurrences to return. By default, it returns all the occurences.
4444
"""
@@ -74,7 +74,7 @@ def deletecases_with_levelspec(expr, pattern, evaluation, levelspec=1, n=-1 ):
7474
break
7575
idx = curr_index[-1]
7676
changed = changed or changed_marks[-1][idx]
77-
changed_marks[-1][idx] = changed
77+
changed_marks[-1][idx] = changed
7878
if changed:
7979
head = tree[-1][curr_index[-1]].get_head()
8080
tree[-1][idx] = Expression(head, *leaves)
@@ -83,12 +83,12 @@ def deletecases_with_levelspec(expr, pattern, evaluation, levelspec=1, n=-1 ):
8383
curr_index[-1] = curr_index[-1] + 1
8484
continue
8585
curr_leave = tree[-1][curr_index[-1]]
86-
if (match(curr_leave, evaluation) and
87-
(len(curr_index) > lsmin) ):
86+
if (match(curr_leave, evaluation) and
87+
(len(curr_index) > lsmin) ):
8888
tree[-1][curr_index[-1]] = nothing
8989
changed_marks[-1][curr_index[-1]] = True
9090
curr_index[-1] = curr_index[-1] + 1
91-
n = n - 1
91+
n = n - 1
9292
continue
9393
if curr_leave.is_atom() or lsmax == len(curr_index):
9494
curr_index[-1] = curr_index[-1] + 1
@@ -104,7 +104,7 @@ def find_matching_indices_with_levelspec(expr, pattern, evaluation,levelspec=1,n
104104
"""
105105
This function walks the expression `expr` looking for a pattern `pattern`
106106
and returns the positions of each occurence.
107-
If levelspec specifies a number, only those positions with `levelspec` "coordinates" are return. By default, it just return occurences in the first level.
107+
If levelspec specifies a number, only those positions with `levelspec` "coordinates" are return. By default, it just return occurences in the first level.
108108
If a tuple (nmin, nmax) is provided, it just return those occurences with a number of "coordinates" between nmin and nmax.
109109
n indicates the number of occurrences to return. By default, it returns all the occurences.
110110
"""
@@ -130,11 +130,11 @@ def find_matching_indices_with_levelspec(expr, pattern, evaluation,levelspec=1,n
130130
curr_index[-1] = curr_index[-1] + 1
131131
continue
132132
curr_leave = tree[-1][curr_index[-1]]
133-
if (match(curr_leave, evaluation) and
133+
if (match(curr_leave, evaluation) and
134134
(len(curr_index) >= lsmin) ):
135135
found.append([from_python(i) for i in curr_index])
136136
curr_index[-1] = curr_index[-1] + 1
137-
n = n - 1
137+
n = n - 1
138138
continue
139139
if curr_leave.is_atom() or lsmax == len(curr_index):
140140
curr_index[-1] = curr_index[-1] + 1
@@ -1840,11 +1840,11 @@ class DeleteCases(Builtin):
18401840
<dd>returns the elements of $list$ that do not match $pattern$.
18411841
18421842
<dt>'DeleteCases[$list$, $pattern$, $levelspec$]'
1843-
<dd> removes all parts of $list on levels specified by $levelspec$
1843+
<dd> removes all parts of $list on levels specified by $levelspec$
18441844
that match pattern (not fully implemented).
18451845
18461846
<dt>'DeleteCases[$list$, $pattern$, $levelspec$, $n$]'
1847-
<dd> removes the first $n$ parts of $list$ that match $pattern$.
1847+
<dd> removes the first $n$ parts of $list$ that match $pattern$.
18481848
</dl>
18491849
18501850
>> DeleteCases[{a, 1, 2.5, "string"}, _Integer|_Real]
@@ -1861,16 +1861,16 @@ class DeleteCases(Builtin):
18611861
messages = {'level': 'Level specification `1` is not of the form n, {n}, or {m, n}.',
18621862
'innf': 'Non-negative integer or Infinity expected at position 4 in `1`',
18631863
}
1864-
1864+
18651865
# def apply(self, items, pattern, evaluation):
18661866
# 'DeleteCases[items_, pattern_]'
1867-
# return self.apply_ls_n(items, pattern, Integer(1), Symbol("System`Null"), evaluation)
1867+
# return self.apply_ls_n(items, pattern, Integer(1), SymbolNull, evaluation)
18681868

18691869

18701870
# def apply_ls(self, items, pattern, levelspec, evaluation):
18711871
# 'DeleteCases[items_, pattern_, levelspec_]'
1872-
# return self.apply_ls_n(items, pattern, levelspec, Symbol("System`Null"), evaluation)
1873-
1872+
# return self.apply_ls_n(items, pattern, levelspec, SymbolNull, evaluation)
1873+
18741874
def apply_ls_n(self, items, pattern, levelspec, n, evaluation):
18751875
'DeleteCases[items_, pattern_, levelspec_:1, n_:System`Infinity]'
18761876

@@ -1893,8 +1893,8 @@ def apply_ls_n(self, items, pattern, levelspec, n, evaluation):
18931893
evaluation.message('DeleteCases','innf',Expression("DeleteCases", items, pattern, levelspec, n))
18941894
else:
18951895
evaluation.message('DeleteCases','innf',Expression("DeleteCases", items, pattern, levelspec, n))
1896-
return Symbol('System`Null')
1897-
1896+
return SymbolNull
1897+
18981898
if levelspec[0] !=1 or levelspec[1] !=1:
18991899
return deletecases_with_levelspec(items, pattern, evaluation, levelspec, n)
19001900
else:

mathics/builtin/structure.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
)
1919
from mathics.core.rules import Pattern
2020

21-
from mathics.builtin.lists import python_levelspec, walk_levels, InvalidLevelspecError
21+
from mathics.builtin.lists import python_levelspec, walk_levels, InvalidLevelspecError, List
2222
from mathics.builtin.functional import Identity
2323

2424
import platform
@@ -517,6 +517,34 @@ def callback(level):
517517
return result
518518

519519

520+
class MapAt(Builtin):
521+
"""
522+
<dl>
523+
<dt>'MapAt[$f$, $expr$, $n$]'
524+
<dd>applies $f$ to the element at position $n$ in $expr$. If $n$ is negative, the position is counted from the end.
525+
</dl>
526+
527+
>> MapAt[f, {a, b, c, d}, 2]
528+
= {a, f[b], c, d}
529+
"""
530+
531+
def apply(self, f, expr, n, evaluation, options={}):
532+
"MapAt[f_, expr_, n_Integer]"
533+
i = n.get_int_value()
534+
m = len(expr.leaves)
535+
if 1 <= i <= m:
536+
j = i -1
537+
elif -m <= i <= -1:
538+
j = n - i + 1
539+
selected = expr.leaves[n - i + 1]
540+
else:
541+
evaluation.message('MapAt', 'normal')
542+
543+
new_leaves = list(expr.leaves)
544+
new_leaves[j] = Expression(f, new_leaves[j])
545+
return List(*new_leaves)
546+
547+
520548
class Scan(Builtin):
521549
"""
522550
<dl>

0 commit comments

Comments
 (0)