Old 04-06-2012, 08:40 AM   #1
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default JSFX function support discussion thread

Hello everybody,




Function support has the following features/restrictions:
  • Functions can only be declared at the top level of JS code (i.e. not within a () block etc).
  • Functions defined in @init can be used in any other section, but functions defined elsewhere can only be used in that section.
  • Functions can have 0 or more parameters, and any number of local variables.
  • Functions can not call recursively (a function can only call functions defined prior to that function)
  • Functions have very low overhead, and are automatically inlined if they are below a certain size.
  • The last statement to be executed in a function is effectively the return value (matching the logic used elsewhere in JS).

The most basic declarations and use of functions might be:
Code:
@sample

function getSomeValue()  (
  2;
);

spl1 = spl1 * getSomeValue();
or:
Code:
@sample

function applyGain(spl)  (
  spl * 2;
);

spl1 = applyGain(spl1); // same as spl1 = spl1 * 2;
or


Code:
@sample

function applyGain(spl,scale)  (
  spl * scale;
);

spl1 = applyGain(spl1,2); // same as spl1 = spl1 * 2;
If you wish to define local variables for the function, you can do it by adding one or more local() definitions to the declaration:

Code:
@sample

function applyWave(spl)  
  local(somecounter, scale)
(
  scale < 1.0 ? scale += 1.0/srate;
  somecounter += 1.0/srate;
  spl * sin(somecounter) * scale;
);

spl1 = applyWave(spl1);
Local variable can be used for temporary storage within the function, but they also persist across calls. If you define a function in @init and use it within two other sections (say, @gfx and @sample), your local variables will (now as of April 14) be in separate spaces -- so if you need them shared, you would want to use instance variables.

OK, post any questions or feedback you have here (especially if you see any regressions on existing FX or other code).

Last edited by Justin; 01-17-2014 at 09:15 AM.
Justin is offline   Reply With Quote
Old 04-06-2012, 10:30 AM   #2
Banned
Human being with feelings
 
Banned's Avatar
 
Join Date: Mar 2008
Location: Unwired (probably in the proximity of Amsterdam)
Posts: 4,868
Default

Wow... That is awesome.
__________________
˙lɐd 'ʎɐʍ ƃuoɹʍ ǝɥʇ ǝɔıʌǝp ʇɐɥʇ ƃuıploɥ ǝɹ,noʎ
Banned is offline   Reply With Quote
Old 04-06-2012, 01:18 PM   #3
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

OK, this is pretty awesome. Thanks!
dub3000 is offline   Reply With Quote
Old 04-06-2012, 01:33 PM   #4
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Cool!!1!
Tale is offline   Reply With Quote
Old 04-06-2012, 02:31 PM   #5
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

w00t!
IXix is offline   Reply With Quote
Old 04-06-2012, 02:56 PM   #6
captain_caveman
Human being with feelings
 
captain_caveman's Avatar
 
Join Date: Dec 2011
Posts: 999
Default

Great stuff!

It doesn't appear to be possible to use gfx_ draw stuff within functions....
Code:
@gfx  400 400

function drawSquare(tlx, tly, size)
(
    x = tlx; y = tly;
    gfx_x = tlx;
    gfx_y = tly;
    gfx_lineto(tlx+size, tly, 1);
    gfx_lineto(tlx+size, tly+size, 1);
    gfx_lineto(tlx, tly+size, 1);
    gfx_lineto(tlx, tly, 1);
    //gfx_rectto(200,200);
    1;
);

function setColours(r,g b) 
(
    gfx_r = r;
    gfx_g = g;
    gfx_g = b;
    a = 5;
    1;
);

setColours(100,255,255);

gfx_a = 255; 
//gfx_r = 255; gfx_g = 255; gfx_b = 255;

setColours(100,255,255);
drawSquare(10,50,100);
gfx_lineto(100,100,1);
SetColours works and x and y are set in drawSquare, but nothing is drawn, although gfx_x and gfx_y change. gfx_lineto draws a line.

It's probably me, although it seems it should work.
captain_caveman is offline   Reply With Quote
Old 04-06-2012, 06:40 PM   #7
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

I've had a poke around with this now, pretty cool.

The only thing that feels a bit tricky are functions that need to set multiple bits of state. Eg. I have a bandpass function that needs to store four variables (for each channel - I'm trying to split out common code that used to be repeated for both l and r). I adapted it to use an array for that and performance dropped a lot. Any ideas on having multiple "out" values for functions?
dub3000 is offline   Reply With Quote
Old 04-07-2012, 02:45 AM   #8
egoadsr
Human being with feelings
 
egoadsr's Avatar
 
Join Date: May 2008
Location: In Space
Posts: 240
Default

Nice
egoadsr is offline   Reply With Quote
Old 04-07-2012, 05:01 AM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by captain_caveman View Post
It's probably me, although it seems it should work.
Yeah, it's you. The gfx_r, gfx_g, gfx_b and gfx_a variables are all in the 0.0..1.0 range, not 0..255. If you change them accordingly (especially gfx_a), then your drawSquare will work just fine.
Tale is offline   Reply With Quote
Old 04-07-2012, 06:18 AM   #10
captain_caveman
Human being with feelings
 
captain_caveman's Avatar
 
Join Date: Dec 2011
Posts: 999
Default

Quote:
Originally Posted by Tale View Post
Yeah, it's you. The gfx_r, gfx_g, gfx_b and gfx_a variables are all in the 0.0..1.0 range, not 0..255. If you change them accordingly (especially gfx_a), then your drawSquare will work just fine.
Ah... *cough*... of course... (mops brow)... it's been a while.

Thanks Tale!
captain_caveman is offline   Reply With Quote
Old 04-07-2012, 09:00 AM   #11
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

Quote:
Originally Posted by dub3000 View Post
Any ideas on having multiple "out" values for functions?
How about something like this?
Code:
function f(arg1, arg2, arg3)
  out(arg2, arg3)
(
   arg2 = 1; // set output var
   arg3 = 2; // ^^

   1; // normal return val
);
Dunno if that's technically possible though. Justin?
IXix is offline   Reply With Quote
Old 04-07-2012, 09:51 AM   #12
vocalid
Human being with feelings
 
vocalid's Avatar
 
Join Date: Sep 2009
Location: Middle of nowhere (where the cheese comes from)
Posts: 483
Default

Quote:
Originally Posted by IXix View Post
How about something like this?
Code:
function f(arg1, arg2, arg3)
  out(arg2, arg3)
(
   arg2 = 1; // set output var
   arg3 = 2; // ^^

   1; // normal return val
);
Dunno if that's technically possible though. Justin?
can't you just define normal vars as answer_1, answer_2 etc. and put the return values there? I know it's not quite as spiffy, but it should work
vocalid is offline   Reply With Quote
Old 04-07-2012, 02:10 PM   #13
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

I think what we'll do is actually add two new functions, push() and pop(), and let you just use a stack for this sort of thing. I think we can implement a stack that is very fast and will be generally quite useful -- you could use it for passing extra parameters in, as well as returning multiple values.

(As a side note, I'd like to optimize array access, but of course you have to be super careful not to change any of the rounding behavior, ugh)
Justin is offline   Reply With Quote
Old 04-07-2012, 02:11 PM   #14
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

Quote:
Originally Posted by IXix View Post
How about something like this?
Code:
function f(arg1, arg2, arg3)
  out(arg2, arg3)
(
   arg2 = 1; // set output var
   arg3 = 2; // ^^

   1; // normal return val
);
Dunno if that's technically possible though. Justin?
This would sort me out, yep (I'd split the bandpass into lopass and hi pass to get under the 3 var limit). Any chance of this or something like it?
dub3000 is offline   Reply With Quote
Old 04-07-2012, 02:13 PM   #15
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

Quote:
Originally Posted by Justin View Post
I think what we'll do is actually add two new functions, push() and pop(), and let you just use a stack for this sort of thing. I think we can implement a stack that is very fast and will be generally quite useful -- you could use it for passing extra parameters in, as well as returning multiple values.

(As a side note, I'd like to optimize array access, but of course you have to be super careful not to change any of the rounding behavior, ugh)
This will also work.

On the performance thing - 16 array accesses per sample uses 0.7% total CPU of an i5....
dub3000 is offline   Reply With Quote
Old 04-07-2012, 02:36 PM   #16
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by dub3000 View Post
This will also work.

On the performance thing - 16 array accesses per sample uses 0.7% total CPU of an i5....
Yeah, the big problem is that we index it with a double, so we have to do some rounding, convert to integer, check the bounds, then make sure that that section of RAM is available, then return it... it all adds up

a stack (push/pop, maybe peekstack and peekstack2 too) would be a lot quicker...
Justin is offline   Reply With Quote
Old 04-07-2012, 11:53 PM   #17
vocalid
Human being with feelings
 
vocalid's Avatar
 
Join Date: Sep 2009
Location: Middle of nowhere (where the cheese comes from)
Posts: 483
Default

Quote:
Originally Posted by Justin View Post
(As a side note, I'd like to optimize array access, but of course you have to be super careful not to change any of the rounding behavior, ugh)
2 different array types maybe?
vocalid is offline   Reply With Quote
Old 04-08-2012, 05:59 PM   #18
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Actually I think I managed to speed up array accesses a bit on x86/x86-64, without changing function at all. I will post a new build soon with that (and stack support, which is mostly done but I need to implement on PPC).

For example, a stereo 16-sample bit-bucket style delay line using an array (buf[16]=buf[15]; buf[15]=buf[14]; ...) went from 1.7% CPU use to 1.2% CPU here, woot.

I also am going to look at adding some basic optimization passes, such as detecting expressions that can be resolved at compile time (such as converting x * 1 / 2 into x * 0.5, etc).
Justin is offline   Reply With Quote
Old 04-08-2012, 06:40 PM   #19
tonecarver
Human being with feelings
 
Join Date: Feb 2009
Posts: 60
Default

Quote:
Originally Posted by Justin View Post
For example, a stereo 16-sample bit-bucket style delay line using an array (buf[16]=buf[15]; buf[15]=buf[14]; ...) went from 1.7% CPU use to 1.2% CPU here, woot.
Nice... off topic, but this made me think some builtins to do array shifting, thinking something like perl shift() and unshift() builtins, maybe even a rotateLeft() and rotateRight(), could be useful in JS.
tonecarver is offline   Reply With Quote
Old 04-08-2012, 07:01 PM   #20
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by tonecarver View Post
Nice... off topic, but this made me think some builtins to do array shifting, thinking something like perl shift() and unshift() builtins, maybe even a rotateLeft() and rotateRight(), could be useful in JS.
Hmm, not sure how this would be meaningful, given that JS "arrays" are really just pointers into a global memory space...
Justin is offline   Reply With Quote
Old 04-08-2012, 09:46 PM   #21
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

Quote:
Originally Posted by Justin View Post
Actually I think I managed to speed up array accesses a bit on x86/x86-64, without changing function at all. I will post a new build soon with that (and stack support, which is mostly done but I need to implement on PPC).

For example, a stereo 16-sample bit-bucket style delay line using an array (buf[16]=buf[15]; buf[15]=buf[14]; ...) went from 1.7% CPU use to 1.2% CPU here, woot.

I also am going to look at adding some basic optimization passes, such as detecting expressions that can be resolved at compile time (such as converting x * 1 / 2 into x * 0.5, etc).
This is all awesome, thanks!! This will make all of my js FX run a lot better, I use arrays a fair bit.
dub3000 is offline   Reply With Quote
Old 04-09-2012, 08:11 AM   #22
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

This is great! While there's all this JS love in the air, how about that two's compliment ~ operator? A rebuild of ReaJS to bring it up to speed would be nice too .
IXix is offline   Reply With Quote
Old 04-09-2012, 09:17 AM   #23
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by IXix View Post
This is great! While there's all this JS love in the air, how about that two's compliment ~ operator? A rebuild of ReaJS to bring it up to speed would be nice too .
To 32 bits, I guess? Or would it make more sense to make it be xor and require you to do (var~$xffffffff)?

Edit: this makes the most sense, I think. Perhaps a syntax for "n bits of 1" would be nice, like $~32.

Edit again: making ~ and ~= xor, and $~32 if you want to do 32 bits of 1s... so for example:
Code:
y = x ~ $~32;
y ~= $~32;
Almost ready for a new build, just need to implement the new stack functions on PPC, bleh..

Last edited by Justin; 04-09-2012 at 09:55 AM.
Justin is offline   Reply With Quote
Old 04-09-2012, 10:01 AM   #24
DarkStar
Human being with feelings
 
DarkStar's Avatar
 
Join Date: May 2006
Location: Surrey, UK
Posts: 19,677
Default

If we're doing JS FX FRs:

gfx_drawstring();
http://forum.cockos.com/project.php?issueid=3268

debugging aid:
http://forum.cockos.com/project.php?issueid=3739

suppress meters for MIDI FX
http://forum.cockos.com/showthread.php?t=77031
__________________
DarkStar ... interesting, if true. . . . Inspired by ...
DarkStar is offline   Reply With Quote
Old 04-09-2012, 11:27 AM   #25
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by DarkStar View Post
You can use Ctrl+T or F4 for matching () or [] (if you want to see which parenthesis matches to which, etc).
Justin is offline   Reply With Quote
Old 04-09-2012, 01:35 PM   #26
DarkStar
Human being with feelings
 
DarkStar's Avatar
 
Join Date: May 2006
Location: Surrey, UK
Posts: 19,677
Default



Well, I never knew that ... any other goodies tucked away?
__________________
DarkStar ... interesting, if true. . . . Inspired by ...
DarkStar is offline   Reply With Quote
Old 04-09-2012, 02:56 PM   #27
Jeffos
Mortal
 
Jeffos's Avatar
 
Join Date: Dec 2008
Location: France
Posts: 1,969
Default

Functions, a stack, array optimizations.. now THAT is some JS love, thank you Justin!
WOW!

@DS: didn't knew that one either!
Jeffos is offline   Reply With Quote
Old 04-09-2012, 02:59 PM   #28
Jeffos
Mortal
 
Jeffos's Avatar
 
Join Date: Dec 2008
Location: France
Posts: 1,969
Default

Slow array..
I agree with remarks above (in @sample, you can even see the CPU use growing each time a line of code with an array access is added)
It's hard to shoot ideas since it really depends on how things are done behind the scene but one thing I always wondered is how the global array is allocated (?)
Because one thing that would be awesome is to delegate things to us: let us do the allocs/re-allocs so we could also manage (or not ;-) tied things like bounds checking. Optionnal? or with a new 3rd array "lmem"?..
EDIT: a stack will be cool, of course! but unless I misunderstand "peekstack2", it would not be as flexible as an array.

Well, in short I mean I'm all for faster arrays
Jeffos is offline   Reply With Quote
Old 04-10-2012, 12:40 AM   #29
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

Any chance of a gfx_poly() function? It could reference the effect memory like gfx_blitex does, ie.

Code:
gfx_poly(numPoints, addressOfPoints, fillColor)
...where addressOfPoints would be the start of a list of x/y pairs. Outline could be drawn using the gfx_r/g/b vars, fill could be a packed rgb value.

I never got around to making a real FR for this but is there any point in doing so for JS requests? They never get many votes.
IXix is offline   Reply With Quote
Old 04-10-2012, 12:43 AM   #30
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

Quote:
Originally Posted by Justin View Post
Edit again: making ~ and ~= xor, and $~32 if you want to do 32 bits of 1s... so for example:
Code:
y = x ~ $~32;
y ~= $~32;
Awesome!
IXix is offline   Reply With Quote
Old 04-12-2012, 01:16 PM   #31
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

OK I've updated the jsfx build linked in the original post of this thread. Some big updates are in this one, updates that will need a lot of testing. Here's the summary:
  • Vastly improved code generation (code is smaller and faster, a lot of excess instructions and housekeeping has been optimized out).
  • High level optimizations -- constant expressions can be precalculated, division by constants can be converted into multiplies, ((2^x)^y) can be simplified into 2^(x*y), etc. Internally we changed the compiler to generate a tree of opcodes which can be quickly analyzed and reduced.
  • Array (memory) addressing is a lot faster. The biggest difference here is actually in the PPC version, at least within Rosetta. If someone can test on a real PPC machine that would be very much appreciated.
  • Added a fast, limited size (4096 slots) stack. stack_push(x) pushes. x=stack_pop(), or stack_pop(x) both pop. stack_peek() gets the value of the top item of the stack (and is very fast), stack_peek(1) gets the second item (and if it is passed a constant such as 0 or 1 or 2 etc it is also very fast), etc. stack_peek(-1) gets the next (unused) stack slot. stack_exch(x) exchanges x with the top of the stack.
  • ~ operator added (bitwise xor), ~= for xor-op (x ~= 1 flips the lowest bit). Also added syntax for generating quick bitmasks, $~16 generates 65535, etc.
  • Variable names can now be 64 characters (they were previously limited to 16 chars), and can have .'s within them (though they can't start with .).
  • There is some initial support for some statically-bound, template-like object-orientedness. In addition to local() for functions, you can also specify a list of variables via instance(), and those variables names will be concatenated with the context of the function. I am not going to do a good job of explaining this right now, but I will give an example:
    Code:
      function someMethod(x) 
          instance(value, somestate) // specific to the prefix of the caller, or if no prefix, then it would be someMethod.somestate etc.
    
      (
         somestate = value*x;
      ); 
    
      obj1.value = 32;
      obj1.someMethod(4);
    
      obj2.value = 16;
      obj2.someMethod(2);
      
      v = obj1.somestate == 128 && obj2.somestate == 32;
      // v should be true
    It is not meant to be full OOP, but it does allow you to easily reuse code for different things, i.e. if you have a filter that you want to use in 4 places with different parameters, you can do that cleanly and efficiently...

Last edited by Justin; 04-14-2012 at 02:36 PM.
Justin is offline   Reply With Quote
Old 04-12-2012, 01:26 PM   #32
sstillwell
Human being with feelings
 
Join Date: Jul 2006
Location: Cowtown
Posts: 1,562
Default

Very cool. Time for testingness.

Scott
__________________
https://www.stillwellaudio.com/
sstillwell is offline   Reply With Quote
Old 04-12-2012, 01:39 PM   #33
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Nice developments for JesuSonic!
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 04-12-2012, 02:06 PM   #34
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

O.M.G.

I'll say it again, with added emphasis...

O! M! G!
IXix is offline   Reply With Quote
Old 04-12-2012, 02:29 PM   #35
mabian
Moderator
 
mabian's Avatar
 
Join Date: Aug 2007
Location: Italy
Posts: 4,326
Default

Since there's some JS love going on, any chance to be able to process data in advance for MIDI plugins without inducing PDC strain?

Plugins like my quantizer would benefit a lot from the above feature: I have a realtime quantize JS plugin that needs data be moved earlier in the arrange in order to be able to process data without needing big PDC (the plugin must be able to move data back and forth in time, so it needs data in advance).

IIRC, the needed amount of prebuffering is around 2 * quantize interval, which, in case of fairly big quantize intervals like 1/2 or 1/4 beats means a lot of unneeded sample prebuffering.

If MIDI only plugins could get data in advance by that kind of figures without inducing that big latency, that would help tremendously to improve the usability of MIDI plugins that deal with timing (ahem flat and groove quantizers ahem)...

Further details about my plugin: http://forum.cockos.com/showthread.php?t=42594

Thank you,
Mario
mabian is offline   Reply With Quote
Old 04-12-2012, 02:48 PM   #36
cyco130
Human being with feelings
 
Join Date: Apr 2012
Posts: 4
Default

Wow! This is incredibly cool. I was trying to use C preprocessor for this kind of semi-object-oriented stuff but 16 chars limit prevented me from using token pasting effectively. Just when I was considering to write my own preprocessor I saw this thread. And it all happened today!

Here's a small but useful js function, just to show that this new addition opens up some very cool possibilities that may not be immediately recognizable:

Code:
@init
    function malloc(size)
        local(result)
    (
        result = heapTop;
        heapTop += ceil(size);
        result;
    );
    
    // Allocate 200 ms delay buffers for each channel
    delayBufferL = malloc(srate * 0.200);
    delayBufferR = malloc(srate * 0.200);
    
    // Report memory usage
    freembuf(heapTop);
Automatic memory management for JS

One can also declare heapTop as an instance variable to avoid polluting the global namespace. I love it!

Now this addition begs for an include file functionality (in case it doesn't exist already), with a dedicated Effects\Include folder so we can immediately start rolling reusable DSP libraries for interpolated delay buffers, biquad filters etc.

Last edited by cyco130; 04-12-2012 at 04:11 PM. Reason: Corrected freemembuf -> freembuf in the code
cyco130 is offline   Reply With Quote
Old 04-12-2012, 03:50 PM   #37
dub3000
Human being with feelings
 
dub3000's Avatar
 
Join Date: Mar 2008
Location: Sydney, Australia
Posts: 3,955
Default

ok, this is awesome.

i'll start playing with this this weekend :-)
dub3000 is offline   Reply With Quote
Old 04-12-2012, 04:42 PM   #38
groundhum
Human being with feelings
 
groundhum's Avatar
 
Join Date: Jan 2011
Location: Finger Lakes, NY
Posts: 54
Default

I didn't do any actual testing, but a cursory tryout on my 1gHz G4 (OS v10.4.11; Reaper v4.21) does appear zippier. Case in point: a 1/f generator I've been tinkering with used to clog up MIDI and choke at high rates, but now spews notes with aplomb. Sweet.
__________________
Michael Rees, composer &c.
extraneous data
groundhum is offline   Reply With Quote
Old 04-12-2012, 06:21 PM   #39
cyco130
Human being with feelings
 
Join Date: Apr 2012
Posts: 4
Default

I've played a little with the new template/object system. How about a this keyword so a function can call another function with the current prefix? i.e.:

Code:
    function helper()
        instance(state)
    (
        // change the state in a way that's useful in more than one place
    );

    function f1()
        instance(state)
    (
        this.helper();
        // Do something
    );

    function f2()
        instance(state)
    (
        this.helper();
        // Do something else
    );

    object.f1(); // helper() will be called with "object." prefix.
This way one can refactor common code that operates on an object.

Currently calling helper() without a prefix from f1() operates on helper.state which is a little confusing. Maybe operating on the current prefix could be the default behavior so we can get rid of the this keyword? One could always call helper.helper() if the current behavior is desired.
cyco130 is offline   Reply With Quote
Old 04-13-2012, 02:51 AM   #40
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by Justin View Post
[*] There is some initial support for some statically-bound, template-like object-orientedness. In addition to locals() for functions, you can also specify a list of variables via instance(), and those variables names will be concatenated with the context of the function.
Very cool! I was just playing around with this a bit, but I got an error when declaring local variables using locals(). However, then I saw that cyco130 used local() instead of locals()... So, which is it, local() or locals()?
Tale is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:07 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.