Jump to content

WeiDU: arrays and functions


Recommended Posts

Not directly. You can pass the array name to the function and use EVAL to access the array.

Example:

DEFINE_ACTION_FUNCTION MyFunc
STR_VAR
  array = ~~
BEGIN
  ACTION_PHP_EACH EVAL ~%array%~ AS key => value BEGIN
    PRINT ~%key% => %value%~
  END
END

ACTION_DEFINE_ASSOCIATIVE_ARRAY MyArray BEGIN
  ~first~ => ~1~
  ~second~ => ~2~
  ~third~ => ~3~
END

LAF MyFunc STR_VAR array = ~MyArray~ END

 

Link to comment

Year has passed and I'm already quite proficient with passing arrays to functions. Now I would you like to ask you about returning arrays from functions. But not simple arrays, those are easy to return with `RET_ARRAY` keyword. I'm wondering if there is good way to return array of arrays. Here is simple example:

DEFINE_ACTION_FUNCTION test_function 
    RET_ARRAY test_arrays
BEGIN 
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
        abc => 123
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
        abc => 234
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
        1 => test_1
        2 => test_2
    END
END

LAF test_function RET_ARRAY test_arrays END

ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

This only prints:

1: test_1

2: test_2

However desired output would be:

1: test_1

abc: 123

2: test_2

abc: 234

That is because test_1 and test_2 get cleared after function ends.

In this exact example I could simply return also test_1 and test_2, but I'm looking for solution that would work when exact number of nested arrays is dynamic and not known upfront. Is there any way to accomplish that?

Link to comment
46 minutes ago, marchitek said:
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
        abc => 123
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
        abc => 234
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
        1 => test_1
        2 => test_2
    END

I'm not sure this is sufficient to make the function realize you are putting array names into this second arrays. It just seems like "test_1" and "test_2" are plain strings.

Which is fine I guess, since the name of any array or string variable is ultimately just a string. But you have to let Weidu distinguish between a string-as-string and a string-as-variable-name. So:

50 minutes ago, marchitek said:
ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

Perhaps add an EVAL in the second/interior ACTION_PHP_EACH command?

Also I would use different variables in each, just to keep things clear. So something like:

ACTION_PHP_EACH test_arrays AS key_outer => value_outer BEGIN 
    PRINT ~%key_outer%: %value_outer%~

    ACTION_PHP_EACH EVAL ~%value%~ AS key_inner => value_inner BEGIN 
        PRINT ~%key_inner%: %value_inner%~
    END
END

...Maybe?

Link to comment

Unfortunately, array definitions and loops are correct here. Both this:

ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
    abc => 123
END
ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
    abc => 234
END
ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
    1 => test_1
    2 => test_2
END

ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

and this:

DEFINE_ACTION_MACRO test_macro BEGIN 
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
        abc => 123
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
        abc => 234
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
        1 => test_1
        2 => test_2
    END
END

LAM test_macro

ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

prints desired output:

1: test_1

abc: 123

2: test_2

abc: 234

 

The problem is that function scoping, which is super cool 99% of the time, here works against me. :( 

Link to comment

Arrays in weidu only store strings/integers.  The following is only storing the strings "test_1" and "test_2", not their arrays.

ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
    1 => test_1
    2 => test_2
END

Any given string can reference both a variable and an array at the same time.  Neither of the following interfere with each other:

OUTER_SET test = 5
ACTION_DEFINE_ARRAY test BEGIN a b c d e f END

As such, Weidu references an array only&always when it expects to do so (immediately after ACTION_DEFINE_ASSOCIATIVE_ARRAY, PHP_EACH, $, RET_ARRAY, etc..., excluding necessary EVALs.)

If you want to return multiple arrays from a function, you must declare each of them as a RET_ARRAY in the function definition and the function call.

DEFINE_ACTION_FUNCTION	array_test
	STR_VAR a = ~~ b = ~~ c = ~~ d = ~~
	RET_ARRAY	EVAL ~%a%~ EVAL ~%b%~ EVAL ~%c%~ EVAL ~%d%~	BEGIN
	ACTION_DEFINE_ARRAY ~%a%~	BEGIN 0 1 2 3 etc END
	OUTER_SPRINT $~%b%~(0) value0	OUTER_SPRINT $~%b%~(1) value1	OUTER_SPRINT $~%b%~(etc) valueetc
	ACTION_DEFINE_ASSOCIATIVE_ARRAY ~%c%~ BEGIN 0 => 0	1 => 1	2 => 2	etc => etc	END
END
LAF	array_test STR_VAR a = test_1 b = test_2	RET_ARRAY test_1 test_2 END
ACTION_DEFINE_ARRAY	test_arrays	BEGIN test_1 test_2	END
ACTION_PHP_EACH test_arrays	AS k => v	BEGIN
	PRINT ~%k%:%v%~
	ACTION_PHP_EACH ~%v%~	AS _ => op	BEGIN
		PRINT ~%_%:%op%~
	END
END
Link to comment
2 hours ago, subtledoctor said:

Any reason not to just use a macro, instead? 

Usual reasons to prefer functions over macros. ;) Ofc this is not type of problem that blocks me from finishing my mod. It's just technical nuisance. Still, I'm curious if someone has some trick for that.

2 hours ago, kjeron said:

If you want to return multiple arrays from a function, you must declare each of them as a RET_ARRAY in the function definition and the function call.

That's pity. Technically it should be possible to have it resolved dynamically, since WeiDU arrays have dynamic size. But TBH I don't have  good idea how syntax of this could look like to fit into general flavor. Maybe something like `RET_ARRAYS array` when "array" is arrays of array references to return. So WeiDU could iterate over this "array" and perform `RET_ARRAY` on each of them.

***

Just for the record. Simplest solution for my example since arrays are statically defined in code would be:

DEFINE_ACTION_FUNCTION test_function 
    RET_ARRAY test_arrays test_1 test_2 // <- return all arrays here
BEGIN 
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
        abc => 123
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
        abc => 234
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
        1 => test_1
        2 => test_2
    END
END

LAF test_function RET_ARRAY test_arrays test_1 test_2 END // <- get all arrays there

ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

However, I was wondering for solution that would allow this for situation when we don't know all arrays upfront (e.g. when number of nested arrays is depending on state of overwrite directory etc).

***

I think I came up with some workaround. It uses fact that RET_ARRAY works for arrays with composite keys. This way we can have macro to "box" array of arrays into one array with composite key and "unbox" macro to get our original array back.

Here are macros:

DEFINE_ACTION_MACRO BOX_ARRAY BEGIN 
    ACTION_CLEAR_ARRAY ~%BOX_ARRAY%_box~
    ACTION_PHP_EACH ~%BOX_ARRAY%~ AS key_0 => value_0 BEGIN 
        ACTION_PHP_EACH ~%value_0%~ AS key_1 => value_1 BEGIN 
            ACTION_DEFINE_ASSOCIATIVE_ARRAY ~%BOX_ARRAY%_box~ BEGIN 
                ~%key_0%~, ~%value_0%~, ~%key_1%~ => ~%value_1%~
            END
        END
    END
END

DEFINE_ACTION_MACRO UNBOX_ARRAY BEGIN 
    ACTION_CLEAR_ARRAY ~%UNBOX_ARRAY%~
    ACTION_PHP_EACH ~%UNBOX_ARRAY%_box~ AS key => _ BEGIN 
        ACTION_CLEAR_ARRAY ~%key_1%~
        ACTION_DEFINE_ASSOCIATIVE_ARRAY ~%UNBOX_ARRAY%~ BEGIN 
            ~%key_0%~ => ~%key_1%~
        END
    END
    ACTION_PHP_EACH ~%UNBOX_ARRAY%_box~ AS key => value BEGIN 
        OUTER_SPRINT $~%key_1%~(~%key_2%~) ~%value%~
    END
END

Here is example of usage:

DEFINE_ACTION_FUNCTION test_function 
    RET_ARRAY test_arrays_box
BEGIN 
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_1 BEGIN 
        abc => 123
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_2 BEGIN 
        abc => 234
    END
    ACTION_DEFINE_ASSOCIATIVE_ARRAY test_arrays BEGIN 
        1 => test_1
        2 => test_2
    END

    OUTER_SPRINT BOX_ARRAY test_arrays
    LAM BOX_ARRAY
END

LAF test_function RET_ARRAY test_arrays_box END

OUTER_SPRINT UNBOX_ARRAY test_arrays
LAM UNBOX_ARRAY

ACTION_PHP_EACH test_arrays AS key => value BEGIN 
    PRINT ~%key%: %value%~

    ACTION_PHP_EACH ~%value%~ AS key => value BEGIN 
        PRINT ~%key%: %value%~
    END
END

It produces desired output:

1: test_1

abc: 123

2: test_2

abc: 234

Still hoping for some "native" method. :D 

***

On a side note. I'm thinking about performance consequences of how WeiDU handles arrays. Passing array to function is done by reference, so it is super fast. In other words, when we pass array to function we pass only string that refers to it, without coping actual array content. However when function returns array, it is returned by value, so whole array is copied. 

Here is some nice practical consequence of it:

However, I guess it can cause some performance problem when we pass and return big array back and forth. Something to keep in mind, but I haven't tested that closely. I just noticed recently that disk operation is not that big % of whole installation time and I started to pay attention to such things. Ofc this can only make difference for mods that do mass editing of game files.

 

Edited by marchitek
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...