gpt4 book ai didi

wolfram-mathematica - 在 Mathematica 中安全地设置 "struct"

转载 作者:行者123 更新时间:2023-12-04 08:07:02 25 4
gpt4 key购买 nike

像Mathematica那样做记录的问题,在很少的地方讨论过,比如Struct data type in Mathematica? .

所有这些方法的问题在于,人们似乎失去了做
对每个参数进行特定的额外检查,如 x_?NumericQ .

我的问题是:在 Mathematica 中是否有一种方法可以创建记录或结构,并且能够对单个元素使用上述检查?

我正在尝试使用一种方法,因为我厌倦了使用 10 个参数调用函数(有时无法避免这种情况),即使我试图使每个函数都非常具体,以尽量减少参数,有些函数只需要很多参数就可以完成特定的工作。

首先,我展示了我所知道的三种方法。

方法一

foo[p_]:=Module[{},
Plot[Sin[x],{x,from/.p,to/.p}]
]
p={from->-Pi,to->Pi};
foo[p]

优点:安全,就像我将符号“从”更改为其他符号一样,它仍然可以工作。如下例。
foo[p_]:=Module[{},
Plot[Sin[x],{x,from/.p,to/.p}]
]
p={from->-Pi,to->Pi};
from=-1; (* By accident the symbol from was set somewhere. It will work*)
foo[p]

方法二
Clear[p,foo];
foo[p_]:=Module[{},
Print[p];
Plot[Sin[x],{x,p["from"],p["to"]}]
]
p["from"] = -Pi;
p["to"] = Pi;

foo[p]

优点:也安全,字符串是不可变的。不必担心“from”值的变化。但是到处都有字符串是不是太可读了?

方法三
Clear[p,to,from];
foo[p_]:=Module[{},
Plot[Sin[x],{x,p[from],p[to]}]
]
p[from] = -Pi;
p[to] = Pi;

foo[p]

缺点:如果任何符号“from”或“to”在某处被覆盖,都会导致问题,如
from=-4; (*accidentally the symbol from is assigned a value*)
foo[p]

所以。我认为方法(1)是最安全的。但现在我失去了这样做的能力:
foo[from_?NumericQ, to_?NumericQ] := Module[{},
Plot[Sin[x], {x, from, to}]
]
from = -Pi; to = Pi;
foo[from, to]

所以,我希望得到一个想法,能够结合制作“记录”之类的,但同时,仍然能够对记录中的各个元素使用参数检查?或者这个问题对于基于 Mathematica 函数/规则的编程风格来说不是很好?

这是我希望 Mathematica 拥有的一件事,它是帮助管理和组织程序中使用的所有变量的真实记录。

最佳答案

首先,我想提一下,您列出的所有方法都是 IMO 有缺陷和危险的。我不喜欢它们的主要原因是它们引入了对全局变量的隐式依赖(讨论了为什么不好的原因,例如 here ),并且还可能与范围界定困惑。它们的另一个问题是这些方法看起来不能很好地扩展到同时存在的结构的许多实例。您列出的第二种方法似乎最安全,但它也有其问题(字符串作为字段名称,无法对这样的结构进行类型检查,那里使用的符号也可能会意外地具有值)。

在我的帖子中 here我讨论了一种构建可变数据结构的可能方法,其中方法可以进行额外检查。我将在此处复制相关部分:

Unprotect[pair, setFirst, getFirst, setSecond, getSecond, new, delete];
ClearAll[pair, setFirst, getFirst, setSecond, getSecond, new, delete];
Module[{first, second},
first[_] := {};
second[_] := {};
pair /: new[pair[]] := pair[Unique[]];
pair /: new[pair[],fst_?NumericQ,sec_?NumericQ]:=
With[{p=new[pair[]]},
p.setFirst[fst];
p.setSecond[sec];
p];
pair /: pair[tag_].delete[] := (first[tag] =.; second[tag] =.);
pair /: pair[tag_].setFirst[value_?NumericQ] := first[tag] = value;
pair /: pair[tag_].getFirst[] := first[tag];
pair /: pair[tag_].setSecond[value_?NumericQ] := second[tag] = value;
pair /: pair[tag_].getSecond[] := second[tag];
];
Protect[pair, setFirst, getFirst, setSecond, getSecond, new, delete];

请注意,我在构造函数和 setter 中添加了检查,以说明如何做到这一点。有关如何使用以这种方式构建的结构的更多详细信息,您可以在我提到的帖子和那里找到的进一步链接中找到。

您的示例现在将阅读:
foo[from_?NumericQ, to_?NumericQ] :=
Module[{}, Plot[Sin[x], {x, from, to}]];
foo[p_pair] := foo[p.getFirst[], p.getSecond[]]
pp = new[pair[], -Pi, Pi];
foo[pp]

请注意,这种方法的主要优点是正确封装了状态,隐藏了实现细节,并且范围界定不会处于危险之中。

关于wolfram-mathematica - 在 Mathematica 中安全地设置 "struct",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7356691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com