For Loops and Such, in Frogatto:
A common question from those familiar with imperative programming languages, is “how can I do a for loop, in FFL”?
You can’t, by design, because FFL is a functional programming language. Instead, there are some other tools that can achieve the same results via a different means. For/while/etc loops are used for a variety of different things, and the best way to know the corresponding thing in frogatto is to ask what you’re trying to accomplish.
Firstly, I should explain frogatto’s map operation, since it’s used by several of these. The basic container class in frogatto is a “list”; which is something like a array in javascript. It differs from arrays/vectors in C in that it can store members of different types in the same list - it can store any of frogatto’s basic types (including but not limited to strings, ints, decimals, and lists - you can have a list of lists). Like arrays in C, members can be accessed with list_name[index] syntax. A helpful value is list.size, which returns how many elements are in a list.
The map operation takes a list, and “does something” to each member; that is, it returns a new list, with all members of the old list passed through the expression you provide. For an example, the expression: map([1,2,3,4], value * 2) is equal to [2,4,6,8]. With this in mind, let’s run through some common uses of for loops:
I’d like to apply something to every member of a list:
The map operation I just described, does that. If you intend to self-overwrite a list, you’d use an expression like: set(mylist, map(mylist, do_something(value)))
I’d like to do something N times:
Frogatto has a useful function called range(int); it makes a new list for you, with members in sequential order. For example, range(5) is equal to [1,2,3,4,5]. The members are in sequence, but they’re also exactly the amount you asked for, so if you just need to do the same thing, say, 5 times, then you can ignore the sequence part and just use this as a shortcut for making a list 5 elements long. So for example, if I have some visual-effect object; say, a sparkle that appears around frogatto, and I want 6 of them to appear simultaneously, randomly positioned (say, he just grabbed a coin or something), I could call the following code inside frogatto:
map(range(6), spawn(‘sparkle’, mid_x + 1d40-20, mid_y + 1d40-20, facing))
I’d like to do something N times, but have what I do depend on N:
This sequential nature of range is really convenient, because you can use the value of the current member, inside a map operation, very much like you’d use a for-loop’s “i” iterator. For example, if I wanted to spawn 5 shots, each spaced 10 pixels apart, vertically, I could use an expression like:
map(range(5), spawn(‘shot’,x, y + 10*value, facing))
Etc, but I need to start/end at something other than 1 or the last element of the list
Remember that frogatto has slice operators [a:b], which only take a limited subset of a list - if you want a range, going up to 10, to start at 3, rather than 1, you could do range(10)[3:]. You can use this to accomplish much of what you’d do with an initial/final value for i in a for loop. Remember that the value you pass into a slice operator need not be a literal constant, it can be an expression instead.
Etc, but I need to do only the even ones (or some other criterion):
The filter operation takes a list, and returns a sub-list consisting of only those items which match a given criterion. For example, this would do something only for even values:
map(filter(range(10), ‘foo’, foo%2=0), do_something(value))
You could also achieve the same end with an if-statement, but filtering is probably more efficient:
map(range(10), if(value%2=0, do_something(value))
todo: explain recursion, and tail recursion, the latter of which I don’t yet know how to do in frogatto. Also explain why for-loops are a bad idea in frogatto, which I’m slightly fuzzy on besides it having to do with avoiding overruns, and errant control flow. I’m also tired at the time of writing this, so … ehhh