Skip to main content

News

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

0 Members and 3 Guests are viewing this topic.
Re: Link.js v0.2.7
Reply #90
Try passing everything as arrays?

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Link.js v0.2.7
Reply #91
Can anyone ... 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).


You might want to read up on Function.apply again for this one ;)

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Link.js v0.2.7
Reply #92
No, I know what he means.  Passing multiple arguments isn't the issue, the issue is keeping track of all the array indices across recursive calls.  I could probably figure it out, but I'm not on my laptop at the moment...
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: Link.js v0.2.7
Reply #93
Passing the indicies in arrays would keep them as reference, rather than value.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Link.js v0.2.7
Reply #94
Feature request: Ability to query against multiple arrays.  Thus the following:
Code: (javascript) [Select]
Link(arr1, arr2, arr3).each(function(item) {
    // ...
});

...would be equivalent to this:
Code: (javascript) [Select]
Link( [ arr1, arr2, arr3 ] ).unroll().each(function(item) {
    // ...
});
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Link.js v0.2.7
Reply #95
Ok, since arguments are slow to use to help speed it up I did a bit of trickery:

Code: (javascript) [Select]

var _splice = [].splice;

function Link(arr, test) {
if (!test)
return new Chain(arr);
else {
var a = _splice.call(arguments, 0, arguments.length);
return (new Chain(a)).unroll();
}
}


It should work naturally. I use splice on arguments since I've always known it as an array-like object, however, Link really only uses .length and the [] getter, that's it. But it could be an issue later on, so I've fixed it here. In JS 1.6 I could use an array generic to cast the list, but those methods aren't guaranteed to be implemented in any JS environment, well, besides Mozilla's, and I doubt Sphere will get to see them.

I put up v0.2.8b online, I'll mark it as officially 0.2.8 once I can figure out (or someone helps with) gathering the multiple array indices in the create method.
  • Last Edit: February 02, 2014, 12:06:10 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

Re: Link.js v0.2.8b
Reply #96
Radnen, would you mind if I used your proposed name Dash.js for my library (formerly known as For.js)? The fact that it compiles for loops behind the scenes is just an implementation detail now, and I don't feel like For.js fits it too well any more. I rather like the sound of Dash (it implies speed); if you don't mind, I think I'd rename it to that.

(Link.js is still, somehow, faster than it, BTW.)

Re: Link.js v0.2.8b
Reply #97
Huh, I thought it was called For.js because, when I read it, it reads as 'forges'.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Link.js v0.2.8b
Reply #98
alpha123: There already exists a library called lo-dash (a pun on Underscore), naming it Dash might imply a nonexistent connection and confuse people.  I'm thinking that might be why Radnen chose not to use it.

Oh and Radnen: I think I might have a way to keep track of the array indices, but I have to test it out first, which I won't be able to do until later. Stay tuned! :)
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Link.js v0.2.8b
Reply #99

Radnen, would you mind if I used your proposed name Dash.js for my library (formerly known as For.js)? The fact that it compiles for loops behind the scenes is just an implementation detail now, and I don't feel like For.js fits it too well any more. I rather like the sound of Dash (it implies speed); if you don't mind, I think I'd rename it to that.

(Link.js is still, somehow, faster than it, BTW.)


Sure. Link is only very fast in Chrome, it is fast (faster than Lazy) in other browsers, but I don't think it's a universal solution. In Sphere it's not all that great (esp. on small arrays), so I've been using a different code called 'List.js' for arrays where I do one thing to it, and Link if I need to do more than one thing.

Of course, if those other browsers get faster, then Link will get faster. It also depends on how the code was written. In Firefox link was the fastest at one point, but then I changed the way I added methods, from:
Code: (javascript) [Select]

function foo() {
    this.bar = function() { };
}


To:
Code: (javascript) [Select]

function foo() { }
foo.prototype.bar = function() { };


And noticed a considerable speed up, with the bonus of not 'slowing down' on subsequent runs due to some weird compiler optimization thing in Chrome that Firefox never had. (Chrome was flagging the former functions as too much to optimize).


alpha123: There already exists a library called lo-dash (a pun on Underscore), naming it Dash might imply a nonexistent connection and confuse people.  I'm thinking that might be why Radnen chose not to use it.

I thought it was because you didn't really like it, and I've learned to trust your judgement on a few things. :P Plus, Link is not so bad, it is a lot like Linq.


Oh and Radnen: I think I might have a way to keep track of the array indices, but I have to test it out first, which I won't be able to do until later. Stay tuned! :)


That's cool! I just hope the solution is not too slow. If you have to manage a data structure that's anything more than linear to keep track of the  indices it may not be too worth it (for speed reasons it may just be better to use n for loops in that case). I'd like it to ideally create the arrays as fast as possible. ;)

So far I think my fastest solution just assumes at a finite 3D array and fills in indices only to those 3 slots. It might alienate larger arrays, but then the data becomes almost too specialized.
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
  • Sphere Developer
Re: Link.js v0.2.8b
Reply #100
Well yeah, that was true (and still is), I don't really like the name Dash.  It's basically just a pun on all the other similarly named libraries with no real meaning of its own other than "this is fast"--which is useful info, but not really the #1 priority with a library like this.  Otherwise you'd just roll your own for loops! :-). But yeah, I like the name Link.  It sounds like LINQ and is also meaningful: You're using it to "link" together related data that you'd otherwise have to sift through manually.

As for my solution, it's pretty simple, merely involving a 1D array (size equal to number of dimensions) and an integer variable.  And I don't think overhead is as big an issue here anyway since it's not like users will be calling Link.create() every frame or anything.  It's basically just to initialize a default data structure or lookup table, which for the most part should be a one-time thing.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: Link.js v0.2.8b
Reply #101

Huh, I thought it was called For.js because, when I read it, it reads as 'forges'.

That's kind of clever, I hadn't thought of that. :P It was named because it was intended to allowed you to write for loops with a higher-level syntax, but really it just became a faster clone of Lazy.js with a completely different implementation and some cool features.


alpha123: There already exists a library called lo-dash (a pun on Underscore), naming it Dash might imply a nonexistent connection and confuse people.  I'm thinking that might be why Radnen chose not to use it.

I'm definitely aware of Lo-Dash, and the name Dash is actually slightly intended to imply that (mostly) nonexistent connection. ;P (They're pretty close API-wise, and the implementations are actually oddly similar in that they involve code generation and eval().) I thought Radnen didn't use it because Link implied that it's like LINQ, and you didn't like the sound of Dash.js. :P


Sure. Link is only very fast in Chrome, it is fast (faster than Lazy) in other browsers, but I don't think it's a universal solution. In Sphere it's not all that great (esp. on small arrays), so I've been using a different code called 'List.js' for arrays where I do one thing to it, and Link if I need to do more than one thing.

Huh, for me the difference between Link and other libraries is actually bigger in Firefox than in Chrome. I haven't tested my library in Sphere for a while and I'm not really sure how it will perform. On the one hand, since it generates code, it relies mainly on a fast eval() and that the generated code will be well optimized. Sphere doesn't really have either of those, but on the other hand, my library doesn't have a deep call stack, which Lazy and Link tend to create and Sphere generally doesn't handle too well.

Anyway, that is an odd thing that Chrome does with prototypes, and probably has to do with V8's "hidden classes" optimization thing. My library just assigns to prototype directly anyway, but that's good to know.


Well yeah, that was true (and still is), I don't really like the name Dash.  It's basically just a pun on all the other similarly named libraries with no real meaning of its own other than "this is fast"--which is useful info, but not really the #1 priority with a library like this.  Otherwise you'd just roll your own for loops! :-).

If you have any better ideas I'd be happy to hear them. To be honest 90% of the reason I like the name Dash is so that I can use this as the mascot.... ;D

Incidentally, my library does roll its own for loops.... :P Hence the original name For.js, but I decided that it wasn't the greatest idea to name a library after its implementation (which is subject to change; I'm not sure generating for loops at runtime is the best choice in some circumstances).

Expect an alpha release of For/Dash/name-TBD soon. (Name suggestions are appreciated. :P) It's getting pretty close to having a full API; it's not nearly as comprehensive as Link's yet, but one of its main features is that it's fairly easy to extend.

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Link.js v0.2.8b
Reply #102

Expect an alpha release of For/Dash/name-TBD soon. (Name suggestions are appreciated. :P) It's getting pretty close to having a full API; it's not nearly as comprehensive as Link's yet, but one of its main features is that it's fairly easy to extend.


Yeah, my library is a pain to add things on to it. It's very "class heavy" - like how compilers are written. So adding a new feature means adding a lot of little stuff, most of which is boilerplate stuff that I can't seem to get rid of effectively. For example, some things have a .run method which kick-starts the query by staring off with the first modification made whether it is a map or a filter. But in order to do this for each type of operation the 'runner' as I call it needs to be written differently each time. The general runner just blindly goes to the next operation. It is still faster than Lazy, but for single operations is near Lazy's speed.

I guess you can still add stuff to it, but you end up doing a lot of the leg work:
Code: (javascript) [Select]

Link.prototype.add = function() {
    this.pushPoint(new AddPoint());
    return this;
}

function AddPoint(num) { this.num = num; }
AddPoint.prototype.exec = function(item) { this.next.exec(item + this.num); }

var added = Link([1, 2, 3]).add(1).toArray(); // 2, 3, 4


The above is how 80% of the library is implemented; which is why you can see how it is so fast. It runs at nearly the speed of traversing your standard every-day link list. That's the whole secret. I really want to expand to a binary tree, but such a format is not always easy to use when given an already linear array, but my hope would be to add binary searching to it - crazy stuff for a 0.3.0 release someday in the future.
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
  • Sphere Developer
Re: Link.js v0.2.8b
Reply #103
Haha, the name Link was even more clever than I thought, and I already thought it was pretty clever so that's awesome. :)

Also, brony alert! (Bronies are cool, I bear no ill will against them :) )
  • Last Edit: February 10, 2014, 08:08:20 pm by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: Link.js v0.2.8b
Reply #104

Yeah, my library is a pain to add things on to it. It's very "class heavy" - like how compilers are written. So adding a new feature means adding a lot of little stuff, most of which is boilerplate stuff that I can't seem to get rid of effectively.

I know how that goes. My library pretty much is a compiler, actually (and a reasonably advanced one at that, capable of function inlining, loop unrolling, and specializing certain chains of functions). It does make adding new methods pretty tedious. To do your example, it would be

Code: (javascript) [Select]
For.prototype.add = function (num) {
    this.nodes.push(new AddNode(num))
    return this
}

function AddNode(num) { this.num = num }
AddNode.prototype.compile = function () {
    return 'a+=' + this.num + ';'
}

For([1, 2, 3]).add(1).toArray()  // [2, 3, 4]


which is surprisingly not all that different. It is, however, fairly tedious, so I developed an easier (but less performant) way to extend it by taking advantage of the fact that every array operation1 can be done as a map, filter, or reduce.2

Code: (javascript) [Select]
For.addFilter('even', function (element) { return element % 2 == 0 })
For.addMapper('add', function (element, index, amount) { return element + amount })
For.addEvaluator('sum', function (accumulator, element) { return accumulator + element })

For.range(10).even().add(5).sum()  // 45


All these methods do is create a function on For.prototype that does all the boilerplate stuff, and then calls map, filter, or reduce with a function that does more boilerplate and then calls the actual extension function.
There is another extension method, addFilterMap, which is a little more complicated (it generates a sequence of method calls instead of just a single one to map/filter/reduce) but allows both transforming and testing an element at the same time.

Quote

The above is how 80% of the library is implemented; which is why you can see how it is so fast. It runs at nearly the speed of traversing your standard every-day link list. That's the whole secret. I really want to expand to a binary tree, but such a format is not always easy to use when given an already linear array, but my hope would be to add binary searching to it - crazy stuff for a 0.3.0 release someday in the future.

I really like how that's implemented; it is simple, effective, and is very friendly to modern JS engines which will do a lot of optimization for you. It really is very fast too; I was only able to beat Link in Chrome by less than 10 milliseconds when I added loop unrolling. I still haven't beaten Link in Firefox, and this is in a test that is rather contrived to play off of my library's specific optimizations. :P
The binary tree thing would be quite interesting. I was thinking of extending my library to binary heaps and linked lists, but that would A) add a lot of complexity and B) I don't really know enough about data structures or algorithms to do that effectively.


Also, brony alert! (Bronies are cool, I bear no ill will against them :) )

Oh, alright, you found me. :D

1With some exceptions like drop and take. For/Dash/name-TBD's extension system doesn't quite support extending with methods like that yet, but the general groundwork is there.
2Technically I suppose map and filter can be implemented on top of reduce, but that would kill For's performance.
  • Last Edit: February 11, 2014, 11:12:31 am by alpha123