Skip to main content
Bounty Ended with 100 reputation awarded by Michael Homer
added 2 characters in body
Source Link
alephalpha
  • 690
  • 5
  • 13
added 1000 characters in body
Source Link
alephalpha
  • 690
  • 5
  • 13

I tried some stack-based or concatenative languages to see how the following codes work:

1 [2 3 4] {add} map

1 [2 3 4] {swap} map

1 [2 3 4] {dup} map

add pops two items off the stack and pushes one back. swap pops two items off the stack and pushes two back. dup pops one item off the stack and pushes two back.

1 [2 3 4] [dup] map put .

This prints [2 3 4] 1. Try it online!

The two examples above doesn't seem to check the stack effect. However, a simple modification to the first example gives a stack effect error:

USING: mathkernel sequences ;

1 1 1 { 2 3 4 } [ +dup ] map

Here is theIt gives a stack effect error message (Attempt This Online!Attempt This Online!):

The input quotation to “map” doesn't match its expected effect

For more information, evaluate:
    "inference-branches" help

Input   Expected                  Got
[ +dup ] ( ... elt -- ... newelt ) ( x x -- x x )

The first two examples above doesn't seem to check the stack effect. However, a simple modification to the first example gives a stack effect error:

USING: math sequences ;

1 1 1 { 2 3 4 } [ + ] map

Attempt This Online!

I don't understand why adding two 1s to the stack makes a difference. Does it mean that Factor checks the stack effect after evaluation instead of before?

The result is the same as Factor's. It seems that map's type isn't as restrictive as I thought. At least it allows functions that push and pop the same number of items, even if this number is not 1.

1 [2, 3, 4] { dup } map

This is also rejected by compile-time type checking.

This also errors with Stack underflow.

Print Map (Twin) List (2 3 4) 1;

This prints (2, 2, 3, 3, 4, 4). It also shows a warning: Exiting with 1 object(s) on the stack.

The top of the stack is still [2 3 4], while the 1 below it becomes [1 1 1]. This is unexpected. I don't understand it at all.

∵. [2 3 4] 1

duplicate is represented by .. The code above prints(Try it online!):

1
[2 3 4]
[2 3 4]

I tried some stack-based languages to see how the following codes work:

1 [2 3 4] {add} map

1 [2 3 4] {swap} map

add pops two items off the stack and pushes one back. swap pops two items off the stack and pushes two back.

The two examples above doesn't seem to check the stack effect. However, a simple modification to the first example gives a stack effect error:

USING: math sequences ;

1 1 1 { 2 3 4 } [ + ] map

Here is the error message (Attempt This Online!):

The input quotation to “map” doesn't match its expected effect

For more information, evaluate:
    "inference-branches" help

Input Expected                  Got
[ + ] ( ... elt -- ... newelt ) ( x x -- x )

I don't understand why adding two 1s to the stack makes a difference. Does it mean that Factor checks the stack effect after evaluation instead of before?

The result is the same as Factor's. It seems that map's type isn't as restrictive as I thought. At least it allows functions that push and pop the same number of items, even if this number is not 1.

This also errors with Stack underflow.

The top of the stack is still [2 3 4], while the 1 below it becomes [1 1 1]. This is unexpected. I don't understand it at all.

I tried some stack-based or concatenative languages to see how the following codes work:

1 [2 3 4] {add} map

1 [2 3 4] {swap} map

1 [2 3 4] {dup} map

add pops two items off the stack and pushes one back. swap pops two items off the stack and pushes two back. dup pops one item off the stack and pushes two back.

1 [2 3 4] [dup] map put .

This prints [2 3 4] 1. Try it online!

USING: kernel sequences ;

1 { 2 3 4 } [ dup ] map

It gives a stack effect error (Attempt This Online!):

The input quotation to “map” doesn't match its expected effect

For more information, evaluate:
    "inference-branches" help

Input   Expected                  Got
[ dup ] ( ... elt -- ... newelt ) ( x -- x x )

The first two examples above doesn't seem to check the stack effect. However, a simple modification to the first example gives a stack effect error:

USING: math sequences ;

1 1 1 { 2 3 4 } [ + ] map

Attempt This Online!

I don't understand why adding two 1s to the stack makes a difference. Does it mean that Factor checks the stack effect after evaluation instead of before?

The result is the same as Factor's. It seems that map's type isn't as restrictive as I thought. At least it allows functions that push and pop the same number of items, even if this number is not 1.

1 [2, 3, 4] { dup } map

This is also rejected by compile-time type checking.

This also errors with Stack underflow.

Print Map (Twin) List (2 3 4) 1;

This prints (2, 2, 3, 3, 4, 4). It also shows a warning: Exiting with 1 object(s) on the stack.

The top of the stack is still [2 3 4], while the 1 below it becomes [1 1 1]. This is unexpected. I don't understand it at all.

∵. [2 3 4] 1

duplicate is represented by .. The code above prints(Try it online!):

1
[2 3 4]
[2 3 4]
Source Link
alephalpha
  • 690
  • 5
  • 13

I tried some stack-based languages to see how the following codes work:

1 [2 3 4] {add} map

1 [2 3 4] {swap} map

add pops two items off the stack and pushes one back. swap pops two items off the stack and pushes two back.

Joy

As @Michael Homer said, Joy simply treats the input function as a single-return function, and would treat the top element on the stack as the replacement. The rest of the stack is not affected.

1 [2 3 4] [+] map put .

This prints [3 4 5] 1. Try it online!

1 [2 3 4] [swap] map put .

This prints [1 1 1] 1. Try it online!

Factor

I don't know Factor, so I'm not sure if I'm doing it right. But the result is really interesting.

USING: math sequences ;

1 { 2 3 4 } [ + ] map

This errors as expected. The error message is Data stack underflow, followed by some stack trace that I don't understand. Attempt This Online!

USING: kernel sequences ;

1 { 2 3 4 } [ swap ] map

It prints (Attempt This Online!):

--- Data stack:
4
{ 1 2 3 }

The result is unexpected but understandable. It seems that it treats map's function argument as a function that takes one argument, returns one value, and possibly modifies the stack as a side effect. So here, [ swap ] map first swaps 2 and 1, where it returns 1 and leaves 2 on the stack. Then it swaps 3 and 2, and finally 4 and 3. So the result is { 1 2 3 }.

The two examples above doesn't seem to check the stack effect. However, a simple modification to the first example gives a stack effect error:

USING: math sequences ;

1 1 1 { 2 3 4 } [ + ] map

Here is the error message (Attempt This Online!):

The input quotation to “map” doesn't match its expected effect

For more information, evaluate:
    "inference-branches" help

Input Expected                  Got
[ + ] ( ... elt -- ... newelt ) ( x x -- x )

I don't understand why adding two 1s to the stack makes a difference. Does it mean that Factor checks the stack effect after evaluation instead of before?

Kitten

Kitten is static-typed. I can't find an online interpreter for it, so I tried it on my computer.

1 [2, 3, 4] { (+) } map

It is rejected by compile-time type checking as expected. Here is the error message on REPL:

<interactive>:1.16-17: I can't match the type 'R...'
<interactive>:1.16-17: with the type 'R..., A'

<interactive>:1.16-17: the type 'R...'
<interactive>:1.16-17: occurs in the type 'R..., A' (which often indicates an infinite type)

<interactive>:1.16-17: you may have a stack depth mismatch

However, the second example is accepted:

1 [2, 3, 4] { swap } map

The REPL prints:

[1i32, 2i32, 3i32]
4i32

The result is the same as Factor's. It seems that map's type isn't as restrictive as I thought. At least it allows functions that push and pop the same number of items, even if this number is not 1.

I read the source code of Kitten's standard library, and found that map's type signature is map<A, B, +P> (List<A>, (A -> B +P) -> List<B> +P). Kitten has a simple effect system called Permissions. +P might be related to it.

Cognate

It seems that Attempt This Online! isn't working for Cognate, so I tried it on my computer.

Unlike most other stack-based languages, Cognate is prefix instead of postfix.

Print Map (+) List (2 3 4) 1;

This errors with Stack underflow.

Print Map (Swap) List (2 3 4) 1;

This also errors with Stack underflow.

Cognate's documentation isn't very clear, so I don't really know how it works. It might be one example of "error out, because you’ve gone off the end of the isolated stack" in Michael Homer's answer.

Uiua

Uiua is a new language that combines stack-based and array programming. It is also prefix.

map is called each in Uiua, and is represented by the symbol . Usually we don't need it, because most functions are already vectorized.

∵+ [2 3 4] 1

It prints [3 4 5] as expected, and shows a warning that is not needed. Try it online!

∵∶ [2 3 4] 1

swap is called flip and is represented by :. The code above prints(Try it online!):

[1 1 1]
[2 3 4]

The top of the stack is still [2 3 4], while the 1 below it becomes [1 1 1]. This is unexpected. I don't understand it at all.