<p>I'm working on a stack based lang that has &quot;wraps&quot;, essentially lambdas, that by default run with an isolated stack (though some commands can push things to a wrap's stack, effectively partially applying it)</p>
<p>Is this common design, or do lambdas usually share the same stack as the code that calls them?</p>
<p>Would there be a point in adding syntax for a wrap that captures (duplicates into its own stack) automatically some of its surroundings, and how could it look like?</p>
<p>For reference, wraps look like <code>(commands...)</code>, so like the first 10 even numbers are <code>1 10 range (2 *) map</code>, but I think this question extends to all languages that try to combine stack-based and functional concepts.</p>
<p>I'm essentially asking for suggestions on syntax for duplicating part of the outside stack inside a lambda's own stack, as well as the meta-question of if that is even needed or if <code>7 (+) flip bind</code> is enough.</p>

<syntax><functions><functional-programming><stack-based-languages>
Capturing from outer stack to lambda in a stack-based language?
CC BY-SA 4.0
2023-05-17T05:41:10.837Z
Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
Community Compiler
<h1>The Factor approach</h1>
<p>Factor doesn't give functions an isolated stack, but it still has enough control to prevent functions from clobbering (accidentally or maliciously) the stack. A function must declare the number of input and output arguments it takes (and, if any of those are <em>themselves</em> functions, it must also declare their arity).</p>
<pre><code>:add1 ( x -- y )
  1 + ;
</code></pre>
<p>Basically, Factor has a really weak static type system where the only types are &quot;any value&quot; and &quot;function from X to Y&quot; where X and Y are lists of (possibly higher-order function) types.</p>
<p>In this way, if you want to politely peek at a value from the outer stack (such as inside of a list <code>map</code> if you know what's immediately beneath you on the stack), you can do so, but you can't destroy it or push additional data on, since the arity of each function is still checked.</p>
<p>Factor also provides <code>curry</code>, which sounds like your <code>bind</code> and comes in handy when you're doing more complex stack manipulation, but often you can get by without it.</p>

CC BY-SA 4.0
2023-05-17T16:19:40.077Z
2023-05-17T16:19:40.077Z
Silvio Mayolo
<p><em>This answer comes from an experience of using stack-based <a href="https://en.wikipedia.org/wiki/Code_golf" rel="nofollow noreferrer">golfing languages</a> like <a href="https://github.com/Adriandmen/05AB1E" rel="nofollow noreferrer">05AB1E</a> and <a href="https://github.com/Vyxal/Vyxal" rel="nofollow noreferrer">Vyxal - a programming language I've made</a>.</em></p>
<p>Both isolated and outer stack usage have their advantages and disadvantages, but I'll give my experience with both:</p>
<h2>Using an isolated stack</h2>
<p>Generally speaking, isolated stacks are more useful - it's most analogous to how functional programming works (you get the value you're mapping/filtering/whatvering over as a neat reference) and makes sure that the outer stack doesn't get inadvertently modified. It also means that there's no unexpected behaviour if an operation uses up all references of the initial item - it can simply error out (or do some other behaviour like re-push the current iteration item).</p>
<h2>Using the outer stack</h2>
<p>Sometimes, there are situations in which you want to succinctly refer to values in the outer stack (whether they be inputs you've pushed or some other values you've calculated). However, this approach requires more explicit stack management, as well as caution to make sure the outer stack does not have too many values taken off.</p>
<h2>Recommendation</h2>
<p>Have wraps/lambdas work on an isolated stack by default. However, do give the option for wraps to work on the outer stack.</p>
<p>For example:</p>
<pre><code>1 10 range (2 *) map
</code></pre>
<p>Would use an isolated stack while</p>
<pre><code>1 10 range &gt;(2 *) map
</code></pre>
<p>Would use the outer stack. The <code>&gt;(</code> would mark that the outer stack values are being piped into the wrap.</p>

CC BY-SA 4.0
2023-05-17T05:51:00.827Z
2023-05-17T11:47:38.577Z
2023-05-17T11:47:38.577Z
lyxal
CC BY-SA 4.0
2023-05-17T05:54:23.320Z
For another example, you might want to check out [Vyxal 3's literate mode](https://github.com/Vyxal/Vyxal/blob/version-3/documentation/Literate%20Mode.md), which has similar aspects to what's been described here. The syntax for a lambda to use the outer stack is `lambda stack! | code end` and an isolated stack lambda is `lambda code end` or `{code}`
lyxal
CC BY-SA 4.0
2023-05-17T06:09:24.110Z
would an outer stack wrap be linked to the stack where it was first pushed to, or just read whatever is around? I currently have two ways to call wraps, `call`, that allows to read whatever is around when popping from an empty inner stack, and `call!` (what's used internally in, say, `map`) which disallows leaking implementation details by failing when popping an empty inner stack. How would these combine with these options? Would `7 1 10 range >(pop io.println 0) map` not leak implementation details, instead of the maybe expected printing 7 ten times and then pushing a list of 10 zeroes?
RubenVerg
CC BY-SA 4.0
2023-05-17T06:11:39.943Z
Well in the example code you give, assuming your language errors on popping from an empty stack, only one 7 would be printed. The function would read from the stack(s) it's called in
lyxal
CC BY-SA 4.0
2023-05-17T06:14:21.513Z
If it was something like `7 1 10 range >(dup io.println 0) map` it would print `7` ten times and return a list of 0s. That's generally what I would expect from a stack language/functional programming
lyxal
CC BY-SA 4.0
2023-05-17T06:22:40.390Z
right, so `>()` should copy the outer stack somewhere else inside the function? I wonder how nested `>()`s would play with each other. What would `>(pop) 7 bind` do? Should it even be allowed?
RubenVerg
CC BY-SA 4.0
2023-05-17T06:24:25.317Z
Nested `>()`s would expand out to either the global stack or the first isolated stack
lyxal
CC BY-SA 4.0
2023-05-17T06:45:13.307Z
Alright, I'll try implementing that and see how it plays with different constructs I have. Thanks a lot!
RubenVerg
# Capturing from outer stack to lambda in a stack-based language?
Posted by: username_0 on 2023-05-17
I'm working on a stack based lang that has "wraps", essentially lambdas, that by default run with an isolated stack (though some commands can push things to a wrap's stack, effectively partially applying it)

Is this common design, or do lambdas usually share the same stack as the code that calls them?

Would there be a point in adding syntax for a wrap that captures (duplicates into its own stack) automatically some of its surroundings, and how could it look like?

For reference, wraps look like `(commands...)`, so like the first 10 even numbers are `1 10 range (2 *) map`, but I think this question extends to all languages that try to combine stack-based and functional concepts.

I'm essentially asking for suggestions on syntax for duplicating part of the outside stack inside a lambda's own stack, as well as the meta-question of if that is even needed or if `7 (+) flip bind` is enough.
**Tags:** syntax functions functional-programming stack-based-languages
> **Comments:**
> **username_1**: Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.  
---
## 2 answers
### Answer by username_3 on 2023-05-17. Score: 6 | Accepted answer
This answer comes from an experience of using stack-based golfing languages like 05AB1E and Vyxal - a programming language I've made.
Both isolated and outer stack usage have their advantages and disadvantages, but I'll give my experience with both:
Using an isolated stack
Generally speaking, isolated stacks are more useful - it's most analogous to how functional programming works (you get the value you're mapping/filtering/whatvering over as a neat reference) and makes sure that the outer stack doesn't get inadvertently modified. It also means that there's no unexpected behaviour if an operation uses up all references of the initial item - it can simply error out (or do some other behaviour like re-push the current iteration item).
Using the outer stack
Sometimes, there are situations in which you want to succinctly refer to values in the outer stack (whether they be inputs you've pushed or some other values you've calculated). However, this approach requires more explicit stack management, as well as caution to make sure the outer stack does not have too many values taken off.
Recommendation
Have wraps/lambdas work on an isolated stack by default. However, do give the option for wraps to work on the outer stack.
For example:
1 10 range (2 *) map

Would use an isolated stack while
1 10 range >(2 *) map

Would use the outer stack. The >( would mark that the outer stack values are being piped into the wrap.
> **Comments:**
> **username_3** (2023-05-17): For another example, you might want to check out [Vyxal 3's literate mode](https://github.com/Vyxal/Vyxal/blob/version-3/documentation/Literate%20Mode.md), which has similar aspects to what's been described here. The syntax for a lambda to use the outer stack is `lambda stack! | code end` and an isolated stack lambda is `lambda code end` or `{code}`  
> **username_0** (2023-05-17): would an outer stack wrap be linked to the stack where it was first pushed to, or just read whatever is around? I currently have two ways to call wraps, `call`, that allows to read whatever is around when popping from an empty inner stack, and `call!` (what's used internally in, say, `map`) which disallows leaking implementation details by failing when popping an empty inner stack. How would these combine with these options? Would `7 1 10 range >(pop io.println 0) map` not leak implementation details, instead of the maybe expected printing 7 ten times and then pushing a list of 10 zeroes?  
> **username_3** (2023-05-17): Well in the example code you give, assuming your language errors on popping from an empty stack, only one 7 would be printed. The function would read from the stack(s) it's called in  
> **username_3** (2023-05-17): If it was something like `7 1 10 range >(dup io.println 0) map` it would print `7` ten times and return a list of 0s. That's generally what I would expect from a stack language/functional programming  
> **username_0** (2023-05-17): right, so `>()` should copy the outer stack somewhere else inside the function? I wonder how nested `>()`s would play with each other. What would `>(pop) 7 bind` do? Should it even be allowed?  
> **username_3** (2023-05-17): Nested `>()`s would expand out to either the global stack or the first isolated stack  
> **username_0** (2023-05-17): Alright, I'll try implementing that and see how it plays with different constructs I have. Thanks a lot!  
---
### Answer by username_2 on 2023-05-17. Score: 5
The Factor approach
Factor doesn't give functions an isolated stack, but it still has enough control to prevent functions from clobbering (accidentally or maliciously) the stack. A function must declare the number of input and output arguments it takes (and, if any of those are themselves functions, it must also declare their arity).
:add1 ( x -- y )
  1 + ;

Basically, Factor has a really weak static type system where the only types are "any value" and "function from X to Y" where X and Y are lists of (possibly higher-order function) types.
In this way, if you want to politely peek at a value from the outer stack (such as inside of a list map if you know what's immediately beneath you on the stack), you can do so, but you can't destroy it or push additional data on, since the arity of each function is still checked.
Factor also provides curry, which sounds like your bind and comes in handy when you're doing more complex stack manipulation, but often you can get by without it.
---
