Coder Social home page Coder Social logo

blob2d's Issues

Blob-Lang super and delayed state introduction or private state

As state is associated with a level of scope, and accessing higher levels of scope can be done using the super or strict-super functions. For the most part this makes for a fairly simple workflow.

(begin
    (state! ".a" 1)
    (state! ".c" 3)
    (begin
        (state! ".b" 2)
        (state! ".c" 300)
        (print (.a .b .c)) ; => (1 2 300)
        (print (super (.a .b .c))) ; => (1 .b 3)
    )
    (print (.a .b .c)) ; => (1 .b 3)
)

However one problem that comes up is when using functions that define their own private state (no obvious way of exposing it to the user aside from trial & error). It could be put into the api specs (so it's available in the editor), however I'm not too keen on that approach as for the most part you shouldn't need to concern yourself with it. Where this becomes an even bigger problem is with functions that declare private state but only after they've already evaluated all of their arguments.

An example of this is the render-rect function.

(render-rect (flatten (text-cursor-position .text (super .cursor)) 2 10) .cursor-colour)
(render-rect (flatten (text-cursor-position .text (super (super .cursor))) 2 10) .cursor-colour)

In the examples above we want to access the .cursor state that is a level above the nearest defined one. So in the first example this would correctly access the .cursor we want but only on the first evaluation of render-rect, after it has introduced its state it will instead access the nearest .cursor. Meanwhile the second example will work correctly on every subsequent call, but on the first evaluation it will skip the state we care about and access whatever is above it.

Now this can be solved by using strict-super, as you're then able to get outside of the problem scope and then revert back to super.

(render-rect (flatten (text-cursor-position .text (strict-super (strict-super (strict-super (super .cursor))))) 2 10) .cursor-colour)
;Or event better:
(render-rect (strict-super (flatten (text-cursor-position .text (super .cursor)) 2 10)) .cursor-colour)

But the problem is still there, that being that this is something that may potentially catch someone off-guard. Or a potential issue is if another function is ever modified to have its own state later, this may potentially break scripts and require them to be fixed up like so.

Solutions

The best solution I'm currently considering is to introduce the concept of private state.

typedef struct CCExpressionState {
    CCDictionary values;
    CCExpression super;
    CCExpression result;
    CCCollection remove;
    CCExpression private; //or CCDictionary if want it to work like regular state
} CCExpressionState;

This would be state that can be used internally by functions that wish to retain some private data. Instead of having them use CCExpressionGetStateStrict and CCExpressionCreateState.

Benefits of this approach are that it's simple to implement, and could even have performance improvements as it reduces the amount of state that has to be searched through during regular evaluation of scripts, as well as speeding up the functions themselves when accessing their own private state.

Other ideas were:

To introduce a super function for a specific state, so instead acting like the regular super function which will find the next top level of state defined, it would instead find the next top level of state defined with the given key. e.g. (super-get .cursor) would skip the first .cursor state it finds and get the second (possibly needs argument to specify the number to skip). This may still be a useful function to have even if going with another method.

Or introduce some kind of mark or namespace, so a super could be referenced for a given namespace. e.g. (super .cursor :my-scope) and defining the namespace (namespace! :my-scope). This may still be a useful function to have even if going with another method. This could be easily implemented by making the namespace actually just something like (state! ".some-secret-field" name), and then just implementing a super that finds it.

(begin
    (namespace! :top)
    (state! ".a" 1)
    (begin
        (state! ".a" 2)
        (begin
            (state! ".a" 3)
            (print (super .a :top))
        )
    )
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.