Skip to main content
Source Link
ais523
  • 11
  • 19
  • 35

Underload, 11 bytes

((^)~^~a~*) 

Try it online!

Function submission (because Underload full programs can't take input).

The TIO link shows a curried function a(*a(*)*)* that concatenates its three arguments in reverse order (calling it three times by using the (argument)~^ function call syntax that calls a function with one literal argument). Then it uses the program above, calling it with arguments 3 ((::**)) and the same curried function, producing the output (a(*a(*)*)*)^^^. The final line runs this input on the same three literal arguments ((arg3)~(arg2)~(arg1)~^), demonstrating that it produces the same result.

Explanation

((^)~^~a~*) ( ) define function literal: ~^ call {argument 1} with argument (^) lambda f, x: f(x) {replacing argument 1 with the return value} ~ ~ replace argument 2 with a uneval(argument 2) * compose argument 1 and argument 2 {and return the function newly created} 

The basic idea here is to exploit the fact that Underload is generally very polymorphic with respect to how many arguments a function takes. In particular, we can take a function which takes two arguments and produces one return value, and call it in a loop in order to create a function that takes more than two arguments; each iteration will steal an additional argument from the argument stack.

Numbers in Underload are basically curried loops with a specific number of iterations; you can think of the number 3 as having an effect similar to lambda f: lambda x: f(f(f(x))) (except with the number of arguments being more flexible than this). So by executing the first argument on lambda f, x: f(x), we effectively end up creating a loop that uncurries a function via simply just calling it repeatedly, consuming an extra argument each time.

This could have been just 8 bytes if not for an off-by-one error: if a function takes 1 argument, it's the same curried and uncurried; if it takes 2 arguments, we have to call it one more time; if it takes 3 arguments, we have to call it twice more, etc.. Arithmetic (other than multiplication and exponentiation) is very verbose in Underload, so instead of fixing the off-by-one error with subtraction, we uneval the function we're uncurrying. The uneval'ed function will consume no arguments and output the original function, so this neatly cancels out one level of uncurrying and thus fixes the off-by-one error.

Post Made Community Wiki by ais523