Skip to main content

News

Topic: Link.js v0.4.2 (Read 78231 times) previous topic - next topic

0 Members and 1 Guest are viewing this topic.
  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.5b
Reply #75
AFAIK recreating an array is really quite fast. I mean, the GC hit is still 10x faster than calling splice each time. ;)

I'll add an alias to expand. I even added the alias expandInto when looking at arrays in objects. So, yeah I'll add unroll to it too.

Edit: and it is done.
  • Last Edit: January 28, 2014, 12:57:59 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.5b
Reply #76
I guess that's true, since splice essentially rebuilds the array each time anyway.  There is one advantage to splice, however: it doesn't change the identity of the array.  Which I don't think matters in this particular case (I don't do any reference equality checks for these arrays), but important to keep in mind.
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.5b
Reply #77
Suggestion for new endpoint: none(), which does the opposite of every().  Right now you can get the same functionality by using every() with a negative predicate, but it would be great to be able to reuse the same predicate I use for where().  For example:

Code: [Select]
if (Link(this.playerUnits).none(isUnitAlive)) {
  // game over handling
}


isUnitAlive was a function I created to be used in earlier queries, so it'd be awesome to be able to re-use it for this test.  Currently I have to create a separate isUnitDead predicate and use every() with that.

Note that none() should probably return true if the array is empty.
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.5b
Reply #78
Ok, it is done. I added none to the repository. No really the method, .none() :P

Since filter() had an opposite called reject(), I guess every() could have one too.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.5b
Reply #79
In my opinion, a library like this is all about improving readability and maintainability, preferably with minimal impact on performance.  Some amount of aliasing is expected.  reject(), for example, often makes the intent of a query more clear than a negative where().  Same for every() versus none().
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.5b
Reply #80
Also I got an idea for keeping the identity of an array:

Code: (javascript) [Select]

var array = []; // filled with stuff, let's say.
var alive = Link(array).filter(theDead).toArray();
array.length = 0; // yes, this is a thing.
array.concat(alive);


I think it's faster to never use splice, clear out the original array, and push back in the entities that remain after an operation.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.5b
Reply #81
I would debate that point.  Your method essentially rebuilds the entire array twice. Given that, on average in the Specs engine, only one battler acts per cycle (in rare cases more than one, if multiple units happen to have an equal CV) and likewise only one unit generally dies in a single cycle, the splice operation amounts to rebuilding only half of the array on average (anything before the insertion point need not be touched), versus your two full rewrites above.  I fail to see how that is faster, unless some crazy optimization is happening behind the scenes I don't know about.

Granted all this is moot seeing as my battler arrays amount to 3 items each, max--beyond trivial to rebuild--but for huge arrays, if you're only deleting one or two items, splice is still going to be faster I would think.
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.5b
Reply #82
No, yeah you are right. I completely forgot Link rebuilds the array with toArray and I wrote it! XD I've been using it so long I tend to forget things like that.

Now, what I could add is a remove point to it:
Code: (javascript) [Select]

Link(array).remove(theDead);


But I'm not sure if I like that or not. It certainly is an issue - keeping the same array identity, but changing it's contents.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.5b
Reply #83
Just a quick question, can queries be built ahead of time and reused multiple times later, as in actual LINQ?  For example:

Code: (javascript) [Select]
var evens = Link(numbers).where(even);
assert(evens.none(odd));
if (!evens.contains(2)) alert("That's weird, there's no 2 here...");
if (!evens.contains(8)) alert("Did the number 8 get... ate?");
evens.each(function(num) {
  print(num);
});


That was... well, horrifically contrived, but you get the idea.

Edit: Now that I think about it, even better would be the ability to build a bare query ahead of time and then pass in an array only when you actually want to run the query on it.  That is to say, have the endpoints accept an array as argument, rather than the Link context.  This way you could run the same query on multiple sets of data.
  • Last Edit: January 29, 2014, 12:40:38 am by Lord English
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.5b
Reply #84
Yes, you can do exactly the above. Endpoints remove themselves as they return their data, so you can keep the same chain and use different endpoints on it.

Furthermore, you can change the target of a Link context by changing the .target member. It was initially designed to take an array as the first thing since other libraries are similar to that and I didn't want to break that heritage.

Code: (javascript) [Select]

var my_query = Link(array1).where(even);
my_query.each(noop);
my_query.toArray();

my_query.target = array2;
my_query.reduce(addUp);


I could add an array parameter to it but then that means rewriting a lot of code. I think setting the target is the best way.

But I must warn you, Link contexts do store some data, unique() is the most noticeable: after running unique() once it'll store what was unique, so subsequent uses of that Link chain will no longer provide you the same information twice. I'll have to look into a way of resetting certain nodes when queries are re-ran. Zip() also as an issue, it'll run only once and that's it, but I think they are the only two.

Edit:
I just now fixed zip and unique, and even skip to use a new internal 'reset' method for when re-running queries. Now query runs are 100% isolated.

What do you feel about a .retarget() method?
Code: (javascript) [Select]

var evenfilter = Link(array1).filter(even);

evenfilter.each(noop);

// later:
evenfilter.retarget(array2).toArray();


Then I have to ask myself should retarget change the original target or the target for only that run?

I would also like to see link-to-link interactions and have some super-lazy methods.
  • Last Edit: January 29, 2014, 02:01:29 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.7
Reply #85
New feature:

Link.create(..., item);

Create n-dimensional arrays:
Code: (javascript) [Select]

var a = Link.create(10, 0);     // 1D array
var a = Link.create(5, 2, 0);   // 2D array
var a = Link.create(8, 8, 5 0); // 3D array
var a = Link.create(4, 3, function() { return new Item(); });


The first n-1 arguments represents the rank of the array, each value the range. The last argument is the 'fill'. If the fill is a primitive it'll be copied throughout. If the fill is a function it'll run the function each time. The function takes one argument: the index of the sub-array it is in.

Code: (javascript) [Select]

// array of: [[0, 1, 2],[0, 1, 2]];
Link.create(2, 3, function(n) { return n; });


This is good for creating a base array of which to do further work off of later. Makes multi-dimensional array creation not such a pain anymore. I think this multi-dimensional array handling is a good thing for Link over other libraries similar to it.
  • Last Edit: February 01, 2014, 01:24:43 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.7
Reply #86
That's a neat feature.  The ability to pass a lambda was a smart move; I could see this being very useful for initializing lookup tables.

As for retargeting, I wouldn't lose sleep over it.  Now that I think about it even real LINQ has you specify a specific collection as part of the query, and for purposes of readability it's better to write queries on different arrays separately, the same way as if you were for-looping through them.

Just out of curiosity, why is this in the Resources forum instead of Libraries?
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Link.js v0.2.7
Reply #87

Just out of curiosity, why is this in the Resources forum instead of Libraries?


Because it used to be a simple code resource. :P

I can move it to libraries, and I think I should... and it's moved.


That's a neat feature.  The ability to pass a lambda was a smart move; I could see this being very useful for initializing lookup tables.


The lambda was essential. Sometimes you want to create a new object for each spot on the array. With a function you can. You can do other things like generate a Fibonacci sequence, too.

BTW, retarget is a completely optional feature. ;)
  • Last Edit: February 01, 2014, 01:30:22 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [code] Link.js v0.2.7
Reply #88

BTW, retarget is a completely optional feature. ;)


No no, I know that.  I just meant not to overthink the API for it, since it's not going to be needed at all 95% of the time.

Any reason why the lambda for Link.create only gets the immediate index as an argument and not a full set of coordinates?  Like I said, it sounds very useful for creating lookup tables on the fly, but you need to know all the indices to do that.
Sphere 5.5.1 - miniSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Link.js v0.2.7
Reply #89

Any reason why the lambda for Link.create only gets the immediate index as an argument and not a full set of coordinates?  Like I said, it sounds very useful for creating lookup tables on the fly, but you need to know all the indices to do that.


A simple error, I'll fix it. Thanks for pointing that out!

Edit: not so simple, I've been scratching my head for a while. Can anyone 10x smarter than me find how to pass n-arguments to the lamda expression, one for each index? I can do only 2D arrays, but never a generalized approach (so far).

Code: (javascript) [Select]

Link.create = function() {
var args = arguments,
stop = args.length - 1,
v    = args[stop],
isFn = (typeof v == "function");

function CreateArray(n, idx) {
if (n == stop) return (isFn) ? v(idx) : v;
var a = [], l = args[n], n = n + 1;
for (var i = 0; i < l; ++i) {
a[i] = CreateArray(n, i);
}
return a;
}

return CreateArray(0, 0);
}


It's recursive code, and I'm having trouble wrapping my head around a generalized method to find the individual indices of each array. I can do this for fixed arrays, like 2D and 3D, but somewhere in that recursive function is a way to get the index as it appears then just pass it along, just like I do for the first index.
  • Last Edit: February 01, 2014, 04:22:44 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here