diff --git a/mathics/builtin/functional/apply_fns_to_lists.py b/mathics/builtin/functional/apply_fns_to_lists.py
index b70fc06e3..fdfa31da4 100644
--- a/mathics/builtin/functional/apply_fns_to_lists.py
+++ b/mathics/builtin/functional/apply_fns_to_lists.py
@@ -15,7 +15,7 @@
from typing import Iterable
from mathics.builtin.base import BinaryOperator, Builtin
-from mathics.builtin.lists import List
+from mathics.builtin.list.constructing import List
from mathics.core.atoms import Integer
from mathics.core.convert.expression import to_mathics_list
from mathics.core.evaluation import Evaluation
diff --git a/mathics/builtin/layout.py b/mathics/builtin/layout.py
index f918bd061..2883b0513 100644
--- a/mathics/builtin/layout.py
+++ b/mathics/builtin/layout.py
@@ -14,7 +14,6 @@
from mathics.builtin.base import BinaryOperator, Builtin, Operator
from mathics.builtin.box.layout import GridBox, RowBox, to_boxes
-from mathics.builtin.lists import list_boxes
from mathics.builtin.makeboxes import MakeBoxes
from mathics.builtin.options import options_to_rules
from mathics.core.atoms import Real, String
@@ -22,6 +21,7 @@
from mathics.core.list import ListExpression
from mathics.core.symbols import Symbol
from mathics.core.systemsymbols import SymbolMakeBoxes
+from mathics.eval.lists import list_boxes
from mathics.eval.makeboxes import format_element
SymbolSubscriptBox = Symbol("System`SubscriptBox")
diff --git a/mathics/builtin/list/associations.py b/mathics/builtin/list/associations.py
index 74281bb93..d88b5f65f 100644
--- a/mathics/builtin/list/associations.py
+++ b/mathics/builtin/list/associations.py
@@ -11,7 +11,6 @@
from mathics.builtin.base import Builtin, Test
from mathics.builtin.box.layout import RowBox
-from mathics.builtin.lists import list_boxes
from mathics.core.atoms import Integer
from mathics.core.attributes import A_HOLD_ALL_COMPLETE, A_PROTECTED
from mathics.core.convert.expression import to_mathics_list
@@ -19,11 +18,14 @@
from mathics.core.expression import Expression
from mathics.core.symbols import Symbol, SymbolTrue
from mathics.core.systemsymbols import SymbolAssociation, SymbolMakeBoxes, SymbolMissing
+from mathics.eval.lists import list_boxes
class Association(Builtin):
"""
- :WMA link:https://reference.wolfram.com/language/ref/Association.html
+
+ :WMA link:
+ https://reference.wolfram.com/language/ref/Association.html
- 'Association[$key1$ -> $val1$, $key2$ -> $val2$, ...]'
diff --git a/mathics/builtin/list/constructing.py b/mathics/builtin/list/constructing.py
index 23acf9185..953a09aad 100644
--- a/mathics/builtin/list/constructing.py
+++ b/mathics/builtin/list/constructing.py
@@ -11,8 +11,9 @@
from itertools import permutations
from mathics.builtin.base import Builtin, IterationFunction, Pattern
+from mathics.builtin.box.layout import RowBox
from mathics.core.atoms import Integer
-from mathics.core.attributes import A_HOLD_FIRST, A_LISTABLE, A_PROTECTED
+from mathics.core.attributes import A_HOLD_FIRST, A_LISTABLE, A_LOCKED, A_PROTECTED
from mathics.core.convert.expression import to_expression
from mathics.core.convert.sympy import from_sympy
from mathics.core.element import ElementsProperties
@@ -21,7 +22,7 @@
from mathics.core.list import ListExpression
from mathics.core.symbols import Atom
from mathics.core.systemsymbols import SymbolNormal
-from mathics.eval.lists import get_tuples
+from mathics.eval.lists import get_tuples, list_boxes
class Array(Builtin):
@@ -141,6 +142,45 @@ class ConstantArray(Builtin):
}
+class List(Builtin):
+ """
+ :WMA link:https://reference.wolfram.com/language/ref/List.html
+
+
+ - 'List[$e1$, $e2$, ..., $ei$]'
+
- '{$e1$, $e2$, ..., $ei$}'
+
- represents a list containing the elements $e1$...$ei$.
+
+
+ 'List' is the head of lists:
+ >> Head[{1, 2, 3}]
+ = List
+
+ Lists can be nested:
+ >> {{a, b, {c, d}}}
+ = {{a, b, {c, d}}}
+ """
+
+ attributes = A_LOCKED | A_PROTECTED
+ summary_text = "form a list"
+
+ def eval(self, elements, evaluation):
+ """List[elements___]"""
+ # Pick out the elements part of the parameter elements;
+ # we we will call that `elements_part_of_elements__`.
+ # Note that the parameter elements may be wrapped in a Sequence[]
+ # so remove that if when it is present.
+ elements_part_of_elements__ = elements.get_sequence()
+ return ListExpression(*elements_part_of_elements__)
+
+ def eval_makeboxes(self, items, f, evaluation):
+ """MakeBoxes[{items___},
+ f:StandardForm|TraditionalForm|OutputForm|InputForm|FullForm]"""
+
+ items = items.get_sequence()
+ return RowBox(*list_boxes(items, f, evaluation, "{", "}"))
+
+
class Normal(Builtin):
"""
diff --git a/mathics/builtin/list/eol.py b/mathics/builtin/list/eol.py
index 8b40325b2..79c9c0176 100644
--- a/mathics/builtin/list/eol.py
+++ b/mathics/builtin/list/eol.py
@@ -11,7 +11,6 @@
from mathics.builtin.base import BinaryOperator, Builtin
from mathics.builtin.box.layout import RowBox
-from mathics.builtin.lists import list_boxes
from mathics.core.atoms import Integer, Integer0, Integer1, String
from mathics.core.attributes import (
A_HOLD_FIRST,
@@ -44,7 +43,7 @@
SymbolSequence,
SymbolSet,
)
-from mathics.eval.lists import delete_one, delete_rec
+from mathics.eval.lists import delete_one, delete_rec, list_boxes
from mathics.eval.parts import (
_drop_span_selector,
_take_span_selector,
@@ -1276,15 +1275,18 @@ class Position(Builtin):
>> Position[{1, 2, 2, 1, 2, 3, 2}, 2]
= {{2}, {3}, {5}, {7}}
- Find positions upto 3 levels deep
+ Find positions upto 3 levels deep:
+
>> Position[{1 + Sin[x], x, (Tan[x] - y)^2}, x, 3]
= {{1, 2, 1}, {2}}
- Find all powers of x
+ Find all powers of x:
+
>> Position[{1 + x^2, x y ^ 2, 4 y, x ^ z}, x^_]
= {{1, 2}, {4}}
- Use Position as an operator
+ Use Position as an operator:
+
>> Position[_Integer][{1.5, 2, 2.5}]
= {{2}}
"""
@@ -1327,7 +1329,9 @@ def callback(level, pos):
class Prepend(Builtin):
"""
- :WMA link:https://reference.wolfram.com/language/ref/Prepend.html
+
+ :WMA link:
+ https://reference.wolfram.com/language/ref/Prepend.html
- 'Prepend[$expr$, $item$]'
diff --git a/mathics/builtin/lists.py b/mathics/builtin/lists.py
deleted file mode 100644
index ed37c8869..000000000
--- a/mathics/builtin/lists.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-List Functions - Miscellaneous
-
-Functions here will eventually get moved to more suitable subsections.
-"""
-
-from mathics.builtin.base import Builtin, Test
-from mathics.builtin.box.layout import RowBox
-from mathics.core.attributes import A_LOCKED, A_PROTECTED
-from mathics.core.exceptions import InvalidLevelspecError
-from mathics.core.list import ListExpression
-from mathics.eval.lists import list_boxes
-from mathics.eval.parts import python_levelspec
-
-
-class LevelQ(Test):
- """
-
- :WMA link:
- https://reference.wolfram.com/language/ref/LevelQ.html
-
-
- - 'LevelQ[$expr$]'
-
- tests whether $expr$ is a valid level specification.
-
-
- >> LevelQ[2]
- = True
- >> LevelQ[{2, 4}]
- = True
- >> LevelQ[Infinity]
- = True
- >> LevelQ[a + b]
- = False
- """
-
- summary_text = "test whether is a valid level specification"
-
- def test(self, ls):
- try:
- start, stop = python_levelspec(ls)
- return True
- except InvalidLevelspecError:
- return False
-
-
-class List(Builtin):
- """
- :WMA link:https://reference.wolfram.com/language/ref/List.html
-
-
- - 'List[$e1$, $e2$, ..., $ei$]'
-
- '{$e1$, $e2$, ..., $ei$}'
-
- represents a list containing the elements $e1$...$ei$.
-
-
- 'List' is the head of lists:
- >> Head[{1, 2, 3}]
- = List
-
- Lists can be nested:
- >> {{a, b, {c, d}}}
- = {{a, b, {c, d}}}
- """
-
- attributes = A_LOCKED | A_PROTECTED
- summary_text = "specify a list explicitly"
-
- def eval(self, elements, evaluation):
- """List[elements___]"""
- # Pick out the elements part of the parameter elements;
- # we we will call that `elements_part_of_elements__`.
- # Note that the parameter elements may be wrapped in a Sequence[]
- # so remove that if when it is present.
- elements_part_of_elements__ = elements.get_sequence()
- return ListExpression(*elements_part_of_elements__)
-
- def eval_makeboxes(self, items, f, evaluation):
- """MakeBoxes[{items___},
- f:StandardForm|TraditionalForm|OutputForm|InputForm|FullForm]"""
-
- items = items.get_sequence()
- return RowBox(*list_boxes(items, f, evaluation, "{", "}"))
-
-
-class NotListQ(Test):
- """
- :WMA link:https://reference.wolfram.com/language/ref/NotListQ.html
-
-
- - 'NotListQ[$expr$]'
-
- returns true if $expr$ is not a list.
-
- """
-
- summary_text = "test if an expression is not a list"
-
- def test(self, expr):
- return expr.get_head_name() != "System`List"
diff --git a/mathics/builtin/patterns.py b/mathics/builtin/patterns.py
index d1d0fe571..677a635e2 100644
--- a/mathics/builtin/patterns.py
+++ b/mathics/builtin/patterns.py
@@ -49,7 +49,6 @@
PatternObject,
PostfixOperator,
)
-from mathics.builtin.lists import InvalidLevelspecError
from mathics.core.atoms import Integer, Number, Rational, Real, String
from mathics.core.attributes import (
A_HOLD_ALL,
@@ -60,6 +59,7 @@
)
from mathics.core.element import EvalMixin
from mathics.core.evaluation import Evaluation
+from mathics.core.exceptions import InvalidLevelspecError
from mathics.core.expression import Expression, SymbolVerbatim
from mathics.core.list import ListExpression
from mathics.core.pattern import Pattern, StopGenerator
diff --git a/mathics/builtin/testing_expressions/list_oriented.py b/mathics/builtin/testing_expressions/list_oriented.py
index 2513370f7..f8f4ec031 100644
--- a/mathics/builtin/testing_expressions/list_oriented.py
+++ b/mathics/builtin/testing_expressions/list_oriented.py
@@ -5,15 +5,19 @@
from mathics.builtin.base import Builtin, Test
from mathics.core.atoms import Integer, Integer1, Integer2
from mathics.core.evaluation import Evaluation
+from mathics.core.exceptions import InvalidLevelspecError
from mathics.core.expression import Expression
from mathics.core.rules import Pattern
from mathics.core.symbols import Atom, SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolSubsetQ
+from mathics.eval.parts import python_levelspec
class ArrayQ(Builtin):
"""
- :WMA: https://reference.wolfram.com/language/ref/ArrayQ.html
+
+ :WMA:
+ https://reference.wolfram.com/language/ref/ArrayQ.html
- 'ArrayQ[$expr$]'
@@ -114,6 +118,57 @@ class IntersectingQ(Builtin):
summary_text = "test whether two lists have common elements"
+class LevelQ(Test):
+ """
+
+ - 'LevelQ[$expr$]'
+
- tests whether $expr$ is a valid level specification. This function \
+ is primarily used in function patterns for specifying type of a \
+ parameter.
+
+
+ >> LevelQ[2]
+ = True
+ >> LevelQ[{2, 4}]
+ = True
+ >> LevelQ[Infinity]
+ = True
+ >> LevelQ[a + b]
+ = False
+
+ We will define MyMap with the "level" parameter as a synonym for the \
+ Builtin Map equivalent:
+
+ >> MyMap[f_, expr_, Pattern[levelspec, _?LevelQ]] := Map[f, expr, levelspec]
+
+ >> MyMap[f, {{a, b}, {c, d}}, {2}]
+ = {{f[a], f[b]}, {f[c], f[d]}}
+
+ >> Map[f, {{a, b}, {c, d}}, {2}]
+ = {{f[a], f[b]}, {f[c], f[d]}}
+
+ But notice that when we pass an invalid level specification, MyMap \
+ does not match and therefore does not pass the arguments through to 'Map'. \
+ So we do not see the error message that 'Map' would normally produce
+
+ >> Map[f, {{a, b}, {c, d}}, x]
+ : Level specification x is not of the form n, {n}, or {m, n}.
+ = Map[f, {{a, b}, {c, d}}, x]
+
+ >> MyMap[f, {{a, b}, {c, d}}, {1, 2, 3}]
+ = MyMap[f, {{a, b}, {c, d}}, {1, 2, 3}]
+ """
+
+ summary_text = "test whether is a valid level specification"
+
+ def test(self, ls):
+ try:
+ start, stop = python_levelspec(ls)
+ return True
+ except InvalidLevelspecError:
+ return False
+
+
class MatrixQ(Builtin):
"""
@@ -183,6 +238,42 @@ class MemberQ(Builtin):
summary_text = "test whether an element is a member of a list"
+class NotListQ(Test):
+ """
+
+ - 'NotListQ[$expr$]'
+
- returns 'True' if $expr$ is not a list. This function is primarily \
+ used in function patterns for specifying type of a parameter.
+
+
+ Consider this definition for taking the deriviate 'Sin' of a function:
+
+ >> MyD[Sin[f_],x_?NotListQ] := D[f,x]*Cos[f]
+ =
+
+ We use "MyD" above to distinguish it from the Builtin 'D'. Now let's try it:
+
+ >> MyD[Sin[2 x], x]
+ = 2 Cos[2 x]
+
+ And compare it with the Builtin deriviative function 'D':
+
+ >> D[Sin[2 x], x]
+ = 2 Cos[2 x]
+
+ Note however the pattern only matches if the $x$ parameter is not a list:
+
+ >> MyD[{Sin[2], Sin[4]}, {1, 2}]
+ = MyD[{Sin[2], Sin[4]}, {1, 2}]
+
+ """
+
+ summary_text = "test if an expression is not a list"
+
+ def test(self, expr):
+ return expr.get_head_name() != "System`List"
+
+
class SubsetQ(Builtin):
"""
@@ -244,7 +335,7 @@ class SubsetQ(Builtin):
}
summary_text = "test if a list is a subset of another list"
- def eval(self, expr, subset, evaluation):
+ def eval(self, expr, subset, evaluation: Evaluation):
"SubsetQ[expr_, subset___]"
if isinstance(expr, Atom):