Skip to main content

gantz_core/node/
apply.rs

1//! A node that applies a function to a list of arguments.
2
3use crate::node;
4use gantz_ca::CaHash;
5use gantz_nodetag::NodeTag;
6use serde::{Deserialize, Serialize};
7
8/// A node that applies a function to arguments.
9///
10/// In other words, this node "calls" the function received on the first input
11/// with the arguments received on the second input.
12///
13/// The node is stateless and evaluates immediately when a function is received.
14#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Deserialize, Serialize, CaHash, NodeTag)]
15#[cahash("gantz.apply")]
16pub struct Apply;
17
18impl node::Node for Apply {
19    /// Two inputs:
20    ///
21    /// 1. A function value. Receiving this triggers evaluation.
22    /// 2. A list of arguments. Assumed `'()` if unconnected.
23    fn n_inputs(&self, _ctx: node::MetaCtx) -> usize {
24        2
25    }
26
27    /// The result of function application.
28    fn n_outputs(&self, _ctx: node::MetaCtx) -> usize {
29        1
30    }
31
32    fn expr(&self, ctx: node::ExprCtx<'_, '_>) -> node::ExprResult {
33        let inputs = ctx.inputs();
34
35        // Get function and arguments from inputs
36        let function = inputs.get(0).and_then(|opt| opt.as_ref());
37        let arguments = inputs.get(1).and_then(|opt| opt.as_ref());
38        let args = arguments.map_or("'()", |s| &s[..]);
39        let expr = function
40            .map(|f| format!("(apply {f} {args})"))
41            .unwrap_or_else(|| "'()".to_string());
42        node::parse_expr(&expr)
43    }
44}