Now I know that technically in theory one could just use blocks to convey values in and out of any body of code. What I'm asking is whether or not a built-in syntax exists for input parameters and return values similar to what pretty much all other programming languages consider to be functions?
3 Answers
A function in Minecraft and a function in programming is completely different.
A function in Minecraft is just a list of commands, which can be executed in game with a single command, running commands in the function from top to bottom. The only other thing you can do with functions right now is leave comments in the code, which start with a #.
So to answer both of your questions; no.
-
2I had a little look at the wiki, and this seems to be correct, it should probably be called a "script" instead of a function.– AequitasJun 8, 2017 at 1:30
While it's true that functions don't take any inputs or return any outputs, there are ways to fake it. A good way to conceptualize it is to look under the hood of how a language like C++ actually does function calls. Take this function declaration:
public list<Player> Foo(int a, int b);
When that function is called, the calling code pushes the values of a
and b
on to the top of the stack. The function will pop those values off, and just before it's finished, it'll push the list of players on at the same place a
was for the calling code to continue to use.
Now we don't have a stack that we can use when making command contraptions, but we do have some things that are almost as good: scoreboards and tags. In C++, the function knows (relative to the stack pointer) where a
and b
are, and where to put the list<Player>
when it's done. In Minecraft, we can use scoreboard values to pass around ints, tags to pass around players and entities, and tagged armor stands to pass around coordinates, and use the name of the function in those scoreboards and tags so the function knows where to look.
So let's see how the above C++ function might look in Minecraft commands. First, we need to pass in our two integers. We'll use a fake scoreboard player for this:
scoreboard objectives add a dummy
scoreboard objectives add b dummy
scoreboard players set #Foo a 1
scoreboard players set #Foo b 5
After this, we can just call the function:
function MyNamespace:Foo
To return the list of players, a command similar to this one inside Foo can be used:
scoreboard players tag @a[<some selector>] add FooResult
In the calling portion we can then use those tagged players in another command:
tell @a[tag=FooResult] Hello!
This is just one relatively simple example, but hopefully it shows that there's a lot of complexity that can be added to commands and functions.
-
Indeed, I am very well aware of the function stack. In fact, a strategy I use in many languages is to write a memory allocator as the language has no structs. I hadnt thought if this, but to be honest I am 1000% a noob at command block scripts. Dec 25, 2017 at 19:42
-
For all my scripts that require inputs & outputs, I manipulate the scoreboard for a player named Invocation and have objectives for param1, param2, and result. As long as a real player named Invocation never logs in, it should be fine. Aug 2, 2018 at 16:02
-
@Thick_propheT as I say in my answer, you don't need to use a player that might be real, you can use a fake player by adding a # in front of the name. Another option would be to use something like a named armor stand, but that can get complicated. Aug 2, 2018 at 16:52
-
Oh, I thought the # might've been a typo. I didn't realize player names could contain special charactors. Also, I figured the function parser would see the # as the beginning of a comment. It's been a while since I've done any work in the command/function system, so my assumptions were obviously a little off. Thanks for the clarification. Aug 2, 2018 at 19:42
So, especially in 1.13 when a function/command is called, you need to give it parameters, that sounds a lot like an input to me. You could key coordinates for instance, or you could use a 'soft' variable, like the nearest non-player entity @e[type=!player].
You can also have other commands manage your inputs to zero in on something extremely specific and conditional. A system to manage in 'input' or 'victim/s' of the command. And you can set it up so that either the player has instant control over triggering, or the game is constantly sensing for the trigger conditions.
Then you have a lot of foo/bar to do with the command once the victim is selected. One thing you can do that is relevant is perform math operations on two stored score values; such as adding them, setting one equal to the other, or doing something if they are equal.
As far as output goes, obviously there are lots of things that can be considered output. You could say hello world, you can build something, you can interact with the world, or the scoreboard, and you can call other functions.
What I think other people are trying to get at is that there is a very limited ability to use scores as inputs. You can - in some limited ways; but you can't directly use a stored score or tag as a single x-coordinate in tp for example. and you can't call a function passing another function (as a native function) to it as an input as you would in functional programming. You are limited to using the other function as a called output that is hard-coded. If you want input from another command you need to store the commands output first, and you are fairly limited to what DATA can be both stored and accessed by downstream commands.
As of 1.13 with the next execute, store, tag, tick and load features, I can't say that there is much distinction between what can be done with datapacks and functional-like programming capabilities, but the game is so state-dependent and the limitations on inputs to commands make it hard to say that commands provide the true functional-equivalent to computer-programming functions(pun). But, they are comparable and getting much more powerful. The new store and other features in execute are incredible and very relevant to this question.
For another example, see this video on creating a sphere using recursion. You call some commands that call other functions in a recursive loop with a tail condition to produce a sphere. That is sort of the hallmark of intro to functional programming:
-
If this store command is getting close to being comparable to arrays in programming you may be interested in looking at one of my other questions regarding just that. I haven't had a chance to read those links yet though. Jul 6, 2018 at 23:12
success
andresult
statistic that you can get from command blocks or entities that call the function or fromexecute store
.result
andsuccess
. They are explained on the page about/stats
, because that's what you would use in 1.12. If it is possible in any way to make your map in 1.13, I would highly recommend it, because/stats
is a giant pain./execute store
is much easier and is sadlyresult
andsuccess
of a function are those of the last command in the function.