ID:2239248
 
Applies to:Dream Maker
Status: Open

Issue hasn't been assigned a status value.

As discussed in this thread, I think a list.ForEach([proc]) function would be super neat and useful. Not a priority, but it would certainly be nifty.

var/list/MonsterList = newlist(/mob/monster1, /mob/monster2)

MonsterList.ForEach( Kill() )


Ex. ForEach() would be a proc for lists that would go through everything in the list and call the proc supplied in the [proc] argument. This would effectively "kill" all the monsters in MonsterList
Currently, this could be implemented as a global proc like so:
// Edited to include index and list in the proc args
proc/list_ForEach(list, proc)
var index = 0
for(var/item in list)
call(proc)(item, ++index, list)

// Example
var list/monsters = newlist(/mob/monster1, /mob/monster2)
list_ForEach(monsters, /proc/kill)

// global proc
proc/kill(mob/monster)
monster.Die()

A built-in proc like this pretty much calls for anonymous functions and a bunch of other features from functional languages.
newlist(/mob/monster1, /mob/monster2).ForEach(proc(monster) monster.Die())

// expanded form
var
list/monsters = newlist(/mob/monster1, /mob/monster2)
kill = proc(monster) monster.Die()
monsters.ForEach(kill)
++
#define foreach(a,b) for(var/i in (##a)){i:##b}

var list/mobs
var list/objs
var list/turfs

world
New()
// Variables
mobs = new
objs = new
turfs = new
var tick = world.tick_lag
// Engine
for()
foreach(mobs, update())
foreach(objs, update())
foreach(turfs, update())
sleep(tick)

mob/proc/update() {world << "[name](MOB) was updated."}
obj/proc/update() {world << "[name](OBJ) was updated."}
turf/proc/update() {world << "[name](TURF) was updated."}

mob/Login(){global.mobs |= src}
In response to Kozuma3
Ignoring that even for a demonstration of an idea this is really poorly-designed code, this is a painfully restricted case for an actual foreach-like situation. There's no reason to assume that the elements of your list will even have methods, let alone the one you actually want to use.
Please stay on-topic, It is a demonstration yes.
Optimize it how you see fit :)
The point of ForEach is to run a proc that takes information about each element. Simply calling a proc on each element is a specific case of that, which you can achieve from my example:
// Proc to run for each element
proc/call_update(updater/updater)
updater.Update()

// Interface type
updater
proc
Update()

// Inside your update loop
list_ForEach(mobs + objs + turfs, /proc/call_update)

// If it was built-in
(mobs + objs + turfs).ForEach(/proc/call_update)
Mine is done in the pre-processor, it "plugs" in said code with no overhead unlike your design.

In response to Kozuma3
And yet Kaio's code is far more robust. Yours is unable to handle a simple task like taking a list of numbers and rounding them without a kludgy workaround, like a wrapper class. In most real would cases, the overhead from Kaio's code is going to be minimal bordering on essentially non-existent.

You need to start trying to see the bigger picture.
In another language yes, BYOND however has okay performance as it stands, and overhead is added for each function called when using dm.

Get back to programming.
In response to Kozuma3
It's incredible how plain and unambiguous my statement can be, and how I address directly what you're saying before you've even said it, and yet you still manage to understand nothing that was said. I would say that you were trying desperately to be mediocre, but given your track record at actually succeeding at something if you went that route you'd probably manage to get better.
I made a library: http://www.byond.com/developer/Kaiochao/FunctionalList
// List of numbers from 1 to 10.
var list/numbers = lf(new(10)).Map(/proc/index).List()

// List of only the odd numbers.
lf(numbers).Keep(/proc/is_odd).List()

// List of doubled numbers.
lf(numbers).Map(/proc/double).List()

// List of doubled odd numbers.
lf(numbers).Keep(/proc/is_odd).Map(/proc/double).List()

// Output the doubled odd numbers to world.log.
lf(numbers).Keep(/proc/is_odd).Map(/proc/double).ForEach(/proc/world_log)

// with global procs:
proc
index(v, index) return index
is_odd(number) return number & 1
double(number) return number * 2
world_log(value) world.log << value

Also includes an "OnEach" function to call a proc on each element of a list:
// Call the "Update" proc on everything in these lists.
lf(mobs + objs + turfs).OnEach("Update")

Every function also has an optional tick usage limit, so you can have kind of "async" functions that happen over time if they use too much tick usage.
I don't negotiate with terrorists.