Skip to content

Commit 115272d

Browse files
committed
fix: fixed Hold function evaluation
1 parent cd3f66d commit 115272d

File tree

3 files changed

+21
-35
lines changed

3 files changed

+21
-35
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
## [Unreleased]
22

33
- Correctly serialize nested superscripts, e.g. `x^{y^z}`.
4+
- The result of evaluation a `Hold` expression is now the expression itself.
5+
- To prevent evaluation of an expression temporarily, use the `Unevaluated`
6+
function. The result of evaluating an `Unevaluated` expression is its
7+
argument.
8+
- The type of a `Hold` expression was incorrectly returned as `string`. It now
9+
return the type of its argument.
410

511
## 0.26.4 _2024-10-17_
612

src/compute-engine/boxed-expression/boxed-function.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,36 +1004,6 @@ function type(expr: BoxedExpression): Type | undefined {
10041004
// The value is a function expression
10051005
//
10061006
if (expr.ops) {
1007-
// If we're a Hold operator, the type is a `function`
1008-
if (expr.operator === 'Hold') {
1009-
const [op] = expr.ops!;
1010-
if (op.symbol) return 'symbol';
1011-
if (op.string !== undefined) return 'string';
1012-
if (op.isNumberLiteral) return op.type;
1013-
1014-
if (op.isFunctionExpression) {
1015-
const def = op.functionDefinition;
1016-
if (def) {
1017-
const type = def.signature;
1018-
1019-
if (typeof type !== 'string' && type.kind === 'signature') {
1020-
// Compute the result type based on the arguments
1021-
// Return a signature modified with the computed result type
1022-
return {
1023-
...type,
1024-
result:
1025-
parseType(def.type?.(op.ops!, { engine: expr.engine })) ??
1026-
type.result,
1027-
};
1028-
}
1029-
return type;
1030-
}
1031-
}
1032-
1033-
// For a Hold function, the default type is 'function'
1034-
return 'function';
1035-
}
1036-
10371007
const def = expr.functionDefinition;
10381008
if (!def) return 'function';
10391009

src/compute-engine/library/core.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,18 @@ export const CORE_LIBRARY: IdentifierDefinitions[] = [
248248
},
249249
},
250250

251+
Unevaluated: {
252+
description: 'Prevent an expression from being evaluated',
253+
// Unlike Hold, the argume is canonicalized
254+
hold: false,
255+
signature: 'any -> any',
256+
type: ([x]) => x.type,
257+
evaluate: ([x]) => x,
258+
},
259+
251260
Hold: {
252-
description: 'Hold an expression, preventing it from being evaluated',
261+
description:
262+
'Hold an expression, preventing it from being canonicalized or evaluated',
253263
hold: true,
254264
signature: 'any -> any',
255265
type: ([x]) => {
@@ -259,11 +269,11 @@ export const CORE_LIBRARY: IdentifierDefinitions[] = [
259269
if (x.ops) return functionSignature(x.type) ?? 'function';
260270
return 'expression';
261271
},
262-
// By definition, arguments of the canonical expression of
272+
// By definition, the argument of the canonical expression of
263273
// `Hold` are not canonicalized.
264-
canonical: (args, { engine: ce }) =>
265-
args.length !== 1 ? null : ce.hold(args[0]),
266-
evaluate: ([x]) => x,
274+
canonical: (args, { engine }) =>
275+
args.length !== 1 ? null : engine.hold(args[0]),
276+
evaluate: ([x], { engine }) => engine.hold(x),
267277
},
268278

269279
HorizontalSpacing: {

0 commit comments

Comments
 (0)