scope and loadRelative

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

scope and loadRelative

mwinter
Hello,

So, I think I have always had a bit of trouble about scoping in sclang,
and I figured I should actually try to understand better.

I read about environments and am still scratching my head a bit.

In the past few pieces of mine I have been loading a bunch of files and
managing everything in the automatically defined environments, but I
realize that that is a bit dangerous and not best practice since
multiple launches of the same program will share vars if they are
defined at the top environment (say using ~XXXvar).

On another note, using loadRelative only allows the defined functions to
work within that loaded context.

Lets say I have a launch process such as is pasted below... Each file
defines functions and vars used by other files... What is the best
practice to define all those function such that they are available only
within that application but to all other loaded code.

I imagine that there is a way to create a unique environment specific to
the program such that any other program launch (even of the same
program) would not share any func or variable definitions. So...
basically, in each of the loaded files below (again, each which has
several func defs), is there is a way make all defs  available at the
top level (that is the top level of this particular program, not the top
level SC environment that is shared by anything running at the moment).

Thanks,

Michael

(
// MAIN LAUNCH

launch = {
     //some code here....
};

"a_lot_of_tiles_trivial_scan_tiler.scd".loadRelative(true, {
"a_lot_of_tiles_trivial_scan_visualizer.scd".loadRelative(true, {
"a_lot_of_tiles_trivial_scan_sonifier.scd".loadRelative(true, {
"a_lot_of_tiles_trivial_scan_gui.scd".loadRelative(true, {
                 launch.value();
             });
         });
     });
});
)




_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

mwinter
hmmm. after reading a bit more
(http://doc.sccode.org/Classes/Environment.html), I see I can use
Environment.make and Environment.use.

But if I push the Environment then it becomes the current Environment
and any code executed from that point on use the environment. Which
means that for me to really keep everything contained. I would have to
wrap everything on in Environment.use, which seems like I am missing
something because that would be overkill.

or maybe I just push then pop once the code is executed (have not tried
to see if anything created in the push and popped environment run

e = Environment.make { };

e.push

// launch the app and execute a bunch of code and

e.pop



On 02/08/2018 04:38 PM, Michael Winter wrote:

> Hello,
>
> So, I think I have always had a bit of trouble about scoping in
> sclang, and I figured I should actually try to understand better.
>
> I read about environments and am still scratching my head a bit.
>
> In the past few pieces of mine I have been loading a bunch of files
> and managing everything in the automatically defined environments, but
> I realize that that is a bit dangerous and not best practice since
> multiple launches of the same program will share vars if they are
> defined at the top environment (say using ~XXXvar).
>
> On another note, using loadRelative only allows the defined functions
> to work within that loaded context.
>
> Lets say I have a launch process such as is pasted below... Each file
> defines functions and vars used by other files... What is the best
> practice to define all those function such that they are available
> only within that application but to all other loaded code.
>
> I imagine that there is a way to create a unique environment specific
> to the program such that any other program launch (even of the same
> program) would not share any func or variable definitions. So...
> basically, in each of the loaded files below (again, each which has
> several func defs), is there is a way make all defs  available at the
> top level (that is the top level of this particular program, not the
> top level SC environment that is shared by anything running at the
> moment).
>
> Thanks,
>
> Michael
>
> (
> // MAIN LAUNCH
>
> launch = {
>     //some code here....
> };
>
> "a_lot_of_tiles_trivial_scan_tiler.scd".loadRelative(true, {
> "a_lot_of_tiles_trivial_scan_visualizer.scd".loadRelative(true, {
> "a_lot_of_tiles_trivial_scan_sonifier.scd".loadRelative(true, {
> "a_lot_of_tiles_trivial_scan_gui.scd".loadRelative(true, {
>                 launch.value();
>             });
>         });
>     });
> });
> )
>
>



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

mwinter
ok. sorry for talking out loud here, but pushing, popping, and using
(not sure) dont work.

Because if you launch a gui and then pop the environment that gui cannot
access the vars any more. I was hoping that would not be the case.

so now I will await to see if someone has a best practice advice here.

thanks,

Michael


On 02/08/2018 05:15 PM, [hidden email] wrote:

> hmmm. after reading a bit more
> (http://doc.sccode.org/Classes/Environment.html), I see I can use
> Environment.make and Environment.use.
>
> But if I push the Environment then it becomes the current Environment
> and any code executed from that point on use the environment. Which
> means that for me to really keep everything contained. I would have to
> wrap everything on in Environment.use, which seems like I am missing
> something because that would be overkill.
>
> or maybe I just push then pop once the code is executed (have not
> tried to see if anything created in the push and popped environment run
>
> e = Environment.make { };
>
> e.push
>
> // launch the app and execute a bunch of code and
>
> e.pop
>
>
>
> On 02/08/2018 04:38 PM, Michael Winter wrote:
>> Hello,
>>
>> So, I think I have always had a bit of trouble about scoping in
>> sclang, and I figured I should actually try to understand better.
>>
>> I read about environments and am still scratching my head a bit.
>>
>> In the past few pieces of mine I have been loading a bunch of files
>> and managing everything in the automatically defined environments,
>> but I realize that that is a bit dangerous and not best practice
>> since multiple launches of the same program will share vars if they
>> are defined at the top environment (say using ~XXXvar).
>>
>> On another note, using loadRelative only allows the defined functions
>> to work within that loaded context.
>>
>> Lets say I have a launch process such as is pasted below... Each file
>> defines functions and vars used by other files... What is the best
>> practice to define all those function such that they are available
>> only within that application but to all other loaded code.
>>
>> I imagine that there is a way to create a unique environment specific
>> to the program such that any other program launch (even of the same
>> program) would not share any func or variable definitions. So...
>> basically, in each of the loaded files below (again, each which has
>> several func defs), is there is a way make all defs  available at the
>> top level (that is the top level of this particular program, not the
>> top level SC environment that is shared by anything running at the
>> moment).
>>
>> Thanks,
>>
>> Michael
>>
>> (
>> // MAIN LAUNCH
>>
>> launch = {
>>     //some code here....
>> };
>>
>> "a_lot_of_tiles_trivial_scan_tiler.scd".loadRelative(true, {
>> "a_lot_of_tiles_trivial_scan_visualizer.scd".loadRelative(true, {
>> "a_lot_of_tiles_trivial_scan_sonifier.scd".loadRelative(true, {
>> "a_lot_of_tiles_trivial_scan_gui.scd".loadRelative(true, {
>>                 launch.value();
>>             });
>>         });
>>     });
>> });
>> )
>>
>>
>
>
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.):
> http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

ddw_music
mwinter wrote
> ok. sorry for talking out loud here, but pushing, popping, and using
> (not sure) dont work.
>
> Because if you launch a gui and then pop the environment that gui cannot
> access the vars any more.

Right, there's no inherent link between a function and the environment in
force when it was created. (There is such a link for Routines, which is
necessary because you don't have control over the evaluation of a routine,
if it's scheduled on a clock.)

You can establish a link using the inEnvir method:

slider = Slider(...)
.action_(inEnvir { ... });

hjh



--
Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

mwinter
Thanks James,

I have yet to try, so forgive me in advance for speaking prematurely.
But it looks like this would need to be wrapped around every function
call. But the lazy side of me just wants to wrap the whole program in
something like inEnvir and then pop the environment, so that any
subsequent code is not shared. Maybe that works, maybe not. If not, I do
not have too many gui calls to wrap. But like I said... I am really lazy.

Best,

Michael


On 02/08/2018 08:45 PM, [hidden email] wrote:

> mwinter wrote
>> ok. sorry for talking out loud here, but pushing, popping, and using
>> (not sure) dont work.
>>
>> Because if you launch a gui and then pop the environment that gui cannot
>> access the vars any more.
> Right, there's no inherent link between a function and the environment in
> force when it was created. (There is such a link for Routines, which is
> necessary because you don't have control over the evaluation of a routine,
> if it's scheduled on a clock.)
>
> You can establish a link using the inEnvir method:
>
> slider = Slider(...)
> .action_(inEnvir { ... });
>
> hjh
>
>
>
> --
> Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

ddw_music
mwinter wrote
> I have yet to try, so forgive me in advance for speaking prematurely.
> But it looks like this would need to be wrapped around every function
> call.

Not every function *call* -- 'value' is the function call. You mean every
function definition. Functions are defined once, but called repeatedly
(especially in GUIs).


> But the lazy side of me just wants to wrap the whole program in
> something like inEnvir and then pop the environment, so that any
> subsequent code is not shared.

Sorry, it doesn't work that way.

You have a choice between:

- Declared variables = lexical scope = functions have access to variables
declared in any higher level scope, but not external scopes.

- Or environments = dynamic scope = the environment in force at any moment
is completely independent of functions declared at some moment in the past
when the environment had been previously current.

There is no type of variable that is sometimes dynamically scoped but other
times, magically, with no additional syntax, lexically bound to functions.
Magic usually doesn't work out too well in programming language
specifications.

Think of "inEnvir" as a modifier that is part of the function definition.
That isn't formally correct, but conceptually it makes sense: it "marks" the
function as being bound to an environment.

I think the ddwProto quark defines "e" as a synonym:

e { ... your code ... }

I'd hope one extra letter is not too onerous.

hjh



--
Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

mwinter
Thanks James,

Yes I meant to write function def. Sorry for not being clear. And the
extra letter or the wrapping is not too onerous at all (though, I did
admit I was lazy : )...

Still... would it be possibly to make a series of files using
loadRelative load within the same scope.

That way, you can have functions spread across several files but
maintain lexical scope when they are loaded.

Best,

Michael

On 02/09/2018 02:35 AM, [hidden email] wrote:

> mwinter wrote
>> I have yet to try, so forgive me in advance for speaking prematurely.
>> But it looks like this would need to be wrapped around every function
>> call.
> Not every function *call* -- 'value' is the function call. You mean every
> function definition. Functions are defined once, but called repeatedly
> (especially in GUIs).
>
>
>> But the lazy side of me just wants to wrap the whole program in
>> something like inEnvir and then pop the environment, so that any
>> subsequent code is not shared.
> Sorry, it doesn't work that way.
>
> You have a choice between:
>
> - Declared variables = lexical scope = functions have access to variables
> declared in any higher level scope, but not external scopes.
>
> - Or environments = dynamic scope = the environment in force at any moment
> is completely independent of functions declared at some moment in the past
> when the environment had been previously current.
>
> There is no type of variable that is sometimes dynamically scoped but other
> times, magically, with no additional syntax, lexically bound to functions.
> Magic usually doesn't work out too well in programming language
> specifications.
>
> Think of "inEnvir" as a modifier that is part of the function definition.
> That isn't formally correct, but conceptually it makes sense: it "marks" the
> function as being bound to an environment.
>
> I think the ddwProto quark defines "e" as a synonym:
>
> e { ... your code ... }
>
> I'd hope one extra letter is not too onerous.
>
> hjh
>
>
>
> --
> Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

ddw_music
mwinter wrote
> Still... would it be possibly to make a series of files using
> loadRelative load within the same scope.
>
> That way, you can have functions spread across several files but
> maintain lexical scope when they are loaded.

Nope.

That's one of those things that sounds convenient, but turns out to be a
trap.

What you're proposing is essentially to use global variables as a general
mechanism for moving data around the system. That's how it used to work, for
instance, when I was just starting to learn programming using Apple BASIC:
everything is global, no such thing as variable scope. It doesn't take too
long to run into the problem: one part of the code uses X for one value, but
another part accidentally uses X for something else, so, magically, the
second part broke the behavior of the first part. And it's very easy to do
that accidentally.

As software has become more complicated, programming languages have become
*more* restrictive about data flow, not less. Fortran/Pascal/C discourage
global variables in favor of passing data into functions (as arguments) and
returning values. Object-oriented languages have a concept of private member
variables, totally inaccessible from outside a given object except by public
interfaces. Pure functional languages (Haskell) are even more strict about
boundaries.

Long-term, the better approach is to design your functions so that you pass
information into them, and get data out by way of the return values.

FWIW, in my own work, I use separate environments for just about everything
(ddwProto quark), but I use each environment as a self-contained object.
It's technically possible to hack through environment boundaries, but I
avoid it pretty carefully. The stability gained from handling data flow more
carefully more than offsets the inconvenience of not being able to access
everything everywhere.

hjh



--
Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|

Re: scope and loadRelative

mwinter
Again. Thank you James for taking the time for such a thorough response.

With respect to this:

Long-term, the better approach is to design your functions so that you pass
information into them, and get data out by way of the return values.

I am pretty strict about doing this. Where I am running into problems is
the function definition themselves. That is, different functions spread
across different files but accessible (public). So I have used ~ for
those that need to be accessed and kept as many other functions as
possible private.

Now I wrapped the  gui action func defs in inEnvir as you suggested and
pop the environment I made after all the code is loaded. So now
everything works fine and is invisible to the current environment. Which
is safe practice.


On 02/09/2018 04:49 PM, [hidden email] wrote:

> mwinter wrote
>> Still... would it be possibly to make a series of files using
>> loadRelative load within the same scope.
>>
>> That way, you can have functions spread across several files but
>> maintain lexical scope when they are loaded.
> Nope.
>
> That's one of those things that sounds convenient, but turns out to be a
> trap.
>
> What you're proposing is essentially to use global variables as a general
> mechanism for moving data around the system. That's how it used to work, for
> instance, when I was just starting to learn programming using Apple BASIC:
> everything is global, no such thing as variable scope. It doesn't take too
> long to run into the problem: one part of the code uses X for one value, but
> another part accidentally uses X for something else, so, magically, the
> second part broke the behavior of the first part. And it's very easy to do
> that accidentally.
>
> As software has become more complicated, programming languages have become
> *more* restrictive about data flow, not less. Fortran/Pascal/C discourage
> global variables in favor of passing data into functions (as arguments) and
> returning values. Object-oriented languages have a concept of private member
> variables, totally inaccessible from outside a given object except by public
> interfaces. Pure functional languages (Haskell) are even more strict about
> boundaries.
>
> Long-term, the better approach is to design your functions so that you pass
> information into them, and get data out by way of the return values.
>
> FWIW, in my own work, I use separate environments for just about everything
> (ddwProto quark), but I use each environment as a self-contained object.
> It's technically possible to hack through environment boundaries, but I
> avoid it pretty carefully. The stability gained from handling data flow more
> carefully more than offsets the inconvenience of not being able to access
> everything everywhere.
>
> hjh
>
>
>
> --
> Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/