pub struct Expr { /* private fields */ }Expand description
Wolfram Language expression.
§Example
Construct the expression {1, 2, 3}:
use wolfram_expr::{Expr, Symbol};
let expr = Expr::normal(Symbol::new("System`List"), vec![
Expr::from(1),
Expr::from(2),
Expr::from(3)
]);§Reference counting
Internally, Expr is an atomically reference-counted ExprKind. This makes cloning
an expression computationally inexpensive.
Implementations§
Source§impl Expr
impl Expr
Sourcepub fn try_as_normal(&self) -> Option<&Normal>
👎Deprecated: use <&Normal>::try_from(expr) instead
pub fn try_as_normal(&self) -> Option<&Normal>
use <&Normal>::try_from(expr) instead
Sourcepub fn try_as_bool(&self) -> Option<bool>
👎Deprecated: use bool::try_from(expr) instead
pub fn try_as_bool(&self) -> Option<bool>
use bool::try_from(expr) instead
If this is the True or False symbol, return that. Otherwise None.
§Migration
let is_true_or_false: Option<bool> = bool::try_from(&expr).ok();Sourcepub fn try_as_str(&self) -> Option<&str>
👎Deprecated: use <&str>::try_from(expr) instead
pub fn try_as_str(&self) -> Option<&str>
use <&str>::try_from(expr) instead
If this is an ExprKind::String expression, return that. Otherwise return None.
§Migration
let s: Option<&str> = <&str>::try_from(&expr).ok();Sourcepub fn try_as_symbol(&self) -> Option<&Symbol>
👎Deprecated: use <&Symbol>::try_from(expr) instead
pub fn try_as_symbol(&self) -> Option<&Symbol>
use <&Symbol>::try_from(expr) instead
Sourcepub fn try_as_number(&self) -> Option<Number>
👎Deprecated: use i64::try_from(expr) / f64::try_from(expr) instead
pub fn try_as_number(&self) -> Option<Number>
use i64::try_from(expr) / f64::try_from(expr) instead
pub fn try_normal(&self) -> Option<&Normal>
use <&Normal>::try_from(expr) instead
pub fn try_symbol(&self) -> Option<&Symbol>
use <&Symbol>::try_from(expr) instead
pub fn try_number(&self) -> Option<Number>
use i64::try_from(expr) / f64::try_from(expr) instead
Source§impl Expr
impl Expr
Sourcepub fn to_kind(self) -> ExprKind
pub fn to_kind(self) -> ExprKind
Consume self and return an owned ExprKind.
If the reference count of self is equal to 1 this function will not perform
a clone of the stored ExprKind, making this operation very cheap in that case.
Sourcepub fn kind(&self) -> &ExprKind
pub fn kind(&self) -> &ExprKind
Get the ExprKind representing this expression.
Examples found in repository?
54fn set_instance_value(args: Vec<Expr>) {
55 assert!(args.len() == 2, "set_instance_value: expected 2 arguments");
56
57 let id: u32 = unwrap_id_arg(&args[0]);
58 let value: String = match args[1].kind() {
59 ExprKind::String(str) => str.clone(),
60 _ => panic!("expected 2nd argument to be a String, got: {}", args[1]),
61 };
62
63 let mut instances = INSTANCES.lock().unwrap();
64
65 let instance: &mut MyObject =
66 instances.get_mut(&id).expect("instance does not exist");
67
68 instance.value = value;
69}
70
71/// Get the fields of the `MyObject` instance for the specified instance ID.
72#[wll::export(wstp)]
73fn get_instance_data(args: Vec<Expr>) -> Expr {
74 assert!(args.len() == 1, "get_instance_data: expected 1 argument");
75
76 let id: u32 = unwrap_id_arg(&args[0]);
77
78 let MyObject { value } = {
79 let instances = INSTANCES.lock().unwrap();
80
81 instances
82 .get(&id)
83 .cloned()
84 .expect("instance does not exist")
85 };
86
87 expr!({ "Value" -> value })
88}
89
90fn unwrap_id_arg(arg: &Expr) -> u32 {
91 match arg.kind() {
92 ExprKind::Integer(int) => u32::try_from(*int).expect("id overflows u32"),
93 _ => panic!("expected Integer instance ID argument, got: {}", arg),
94 }
95}More examples
176fn expr_string_join(link: &mut Link) {
177 let expr = link.get_expr().unwrap();
178
179 let ExprKind::Normal(list) = expr.kind() else {
180 panic!("expected a List, got: {:?}", expr);
181 };
182 assert!(list.has_head(&Symbol::new("System`List")));
183
184 let mut buffer = String::new();
185 for elem in list.elements() {
186 match elem.kind() {
187 ExprKind::String(str) => buffer.push_str(str),
188 _ => panic!("expected String argument, got: {:?}", elem),
189 }
190 }
191
192 link.put_str(buffer.as_str()).unwrap()
193}
194
195//======================================
196// Using `Vec<Expr>` argument list
197//======================================
198
199//------------------
200// total()
201//------------------
202
203#[wll::export(wstp)]
204fn total(args: Vec<Expr>) -> Expr {
205 let mut total = 0.0f64;
206 for (index, arg) in args.into_iter().enumerate() {
207 total += match arg.kind() {
208 ExprKind::Integer(n) => *n as f64,
209 ExprKind::Real(f) => f64::from(*f),
210 _ => panic!(
211 "expected argument at position {} to be a number, got {}",
212 index + 1,
213 arg
214 ),
215 };
216 }
217 Expr::from(total)
218}Sourcepub fn normal<H>(head: H, contents: Vec<Expr>) -> Expr
pub fn normal<H>(head: H, contents: Vec<Expr>) -> Expr
Construct a new normal expression from the head and elements.
Sourcepub fn number(num: Number) -> Expr
👎Deprecated since 0.6.0-alpha.3: use Expr::from(i64) or Expr::from(f64) instead
pub fn number(num: Number) -> Expr
use Expr::from(i64) or Expr::from(f64) instead
Construct a new expression from a Number.
§Migration
// Expr::number(Number::Integer(42))
let _int = Expr::from(42_i64);
// Expr::number(Number::real(3.14))
let _real = Expr::from(3.14_f64); // or Expr::real(3.14)
// Expr::number(Number::Real(f)) — when you already have an F64
let f = F64::new(3.14).unwrap();
let _real = Expr::new(ExprKind::Real(f));Sourcepub fn string<S>(s: S) -> Expr
pub fn string<S>(s: S) -> Expr
Construct a new expression from a String.
Examples found in repository?
More examples
81pub extern "C" fn demo_wstp_function_callback(
82 lib: WolframLibraryData,
83 mut link: WSLINK,
84) -> c_uint {
85 // Create a safe Link wrapper around the raw `WSLINK`. This is a borrowed rather than
86 // owned Link because the caller (the Kernel) owns the link.
87 let link: &mut Link = unsafe { Link::unchecked_ref_cast_mut(&mut link) };
88
89 // Skip reading the argument list packet.
90 if link.raw_get_next().and_then(|_| link.new_packet()).is_err() {
91 return LIBRARY_FUNCTION_ERROR;
92 }
93
94 let callback_link = unsafe { (*lib).getWSLINK.unwrap()(lib) };
95 let mut callback_link = callback_link as wstp::sys::WSLINK;
96
97 {
98 let safe_callback_link =
99 unsafe { Link::unchecked_ref_cast_mut(&mut callback_link) };
100
101 safe_callback_link
102 // EvaluatePacket[Print["Hello, World! --- WSTP"]]
103 .put_expr(&expr!(
104 System::EvaluatePacket[System::Print["Hello, World! --- WSTP"]]
105 ))
106 .unwrap();
107
108 unsafe {
109 (*lib).processWSLINK.unwrap()(
110 safe_callback_link.raw_link() as wll_sys::WSLINK
111 );
112 }
113
114 // Skip the return value packet. This is necessary, otherwise the link has
115 // unread data and the return value of this function cannot be processed properly.
116 if safe_callback_link
117 .raw_get_next()
118 .and_then(|_| safe_callback_link.new_packet())
119 .is_err()
120 {
121 return LIBRARY_FUNCTION_ERROR;
122 }
123 }
124
125 link.put_expr(&Expr::string("returned normally")).unwrap();
126
127 return LIBRARY_NO_ERROR;
128}
129
130/// This example makes use of the [`wstp`][wstp] crate to provide a safe wrapper around
131/// around the WSTP link object, which can be used to read the argument expression and
132/// write out the return expression.
133///
134/// ```wolfram
135/// function = LibraryFunctionLoad[
136/// "raw_wstp_function",
137/// "wstp_expr_function",
138/// LinkObject,
139/// LinkObject
140/// ];
141/// ```
142#[no_mangle]
143pub extern "C" fn wstp_expr_function(
144 _lib: WolframLibraryData,
145 mut unsafe_link: WSLINK,
146) -> c_uint {
147 let link: &mut Link = unsafe { Link::unchecked_ref_cast_mut(&mut unsafe_link) };
148
149 let expr = match link.get_expr() {
150 Ok(expr) => expr,
151 Err(err) => {
152 // Skip reading the argument list packet.
153 if link.raw_get_next().and_then(|_| link.new_packet()).is_err() {
154 return LIBRARY_FUNCTION_ERROR;
155 }
156
157 let msg = err.to_string();
158 let err = wolfram_library_link::expr::expr!(
159 System::Failure["WSTP Error", {"Message" -> msg}]
160 );
161 match link.put_expr(&err) {
162 Ok(()) => return LIBRARY_NO_ERROR,
163 Err(_) => return LIBRARY_FUNCTION_ERROR,
164 }
165 },
166 };
167
168 let expr_string = format!("Input: {}", expr.to_string());
169
170 match link.put_expr(&Expr::string(expr_string)) {
171 Ok(()) => LIBRARY_NO_ERROR,
172 Err(_) => LIBRARY_FUNCTION_ERROR,
173 }
174}Sourcepub fn real(real: f64) -> Expr
pub fn real(real: f64) -> Expr
Construct an expression from a floating-point number.
let expr = Expr::real(3.14159);§Panics
This function will panic if real is NaN.
Sourcepub fn tag(&self) -> Option<Symbol>
pub fn tag(&self) -> Option<Symbol>
Returns the outer-most symbol “tag” used in this expression.
To illustrate:
| Expression | Tag |
|---|---|
5 | None |
"hello" | None |
foo | foo |
f[1, 2, 3] | f |
g[x][y] | g |
Sourcepub fn normal_head(&self) -> Option<Expr>
pub fn normal_head(&self) -> Option<Expr>
If this represents a Normal expression, return its head. Otherwise, return
None.
Sourcepub fn normal_part(&self, index_0: usize) -> Option<&Expr>
pub fn normal_part(&self, index_0: usize) -> Option<&Expr>
Attempt to get the element at index of a Normal expression.
Return None if this is not a Normal expression, or the given index is out of
bounds.
index is 0-based. The 0th index is the first element, not the head.
This function does not panic.
Sourcepub fn has_normal_head(&self, sym: &Symbol) -> bool
pub fn has_normal_head(&self, sym: &Symbol) -> bool
Returns true if self is a Normal expr with the head sym.
Sourcepub fn rule<LHS>(lhs: LHS, rhs: Expr) -> Expr
pub fn rule<LHS>(lhs: LHS, rhs: Expr) -> Expr
Construct a new Rule[_, _] expression from the left-hand side and right-hand
side.
§Example
Construct the expression FontSize -> 16:
use wolfram_expr::{Expr, Symbol};
let option = Expr::rule(Symbol::new("System`FontSize"), Expr::from(16));Sourcepub fn rule_delayed<LHS>(lhs: LHS, rhs: Expr) -> Expr
pub fn rule_delayed<LHS>(lhs: LHS, rhs: Expr) -> Expr
Construct a new RuleDelayed[_, _] expression from the left-hand side and right-hand
side.
§Example
Construct the expression x :> RandomReal[]:
use wolfram_expr::{Expr, Symbol};
let delayed = Expr::rule_delayed(
Symbol::new("Global`x"),
Expr::normal(Symbol::new("System`RandomReal"), vec![])
);