discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Special variable scoping rules

A
adrian
Fri, Feb 3, 2017 7:02 PM

I hit upon an interesting use case.  If I have two files A and B, and B
includes A (keyword /include/) which contains a function/module that
references a special variable, setting the variable in B will be seen in A.
However, if B uses A (keyword /use/), then the function/module will not see
the special variable set in the global scope of B (though, it can be passed
as a parameter).

This doesn't seem consistent.  What do you think?

--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I hit upon an interesting use case. If I have two files A and B, and B includes A (keyword /include/) which contains a function/module that references a special variable, setting the variable in B will be seen in A. However, if B uses A (keyword /use/), then the function/module will not see the special variable set in the global scope of B (though, it can be passed as a parameter). This doesn't seem consistent. What do you think? -- View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Fri, Feb 3, 2017 8:01 PM

On Feb 3, 2017, at 14:02, adrian adrianh.bsc@gmail.com wrote:

This doesn't seem consistent.  What do you think?

To avoid any misunderstandings, could your provide testable code for this, including expected and actual results?

-Marius

> On Feb 3, 2017, at 14:02, adrian <adrianh.bsc@gmail.com> wrote: > > This doesn't seem consistent. What do you think? > To avoid any misunderstandings, could your provide testable code for this, including expected and actual results? -Marius
A
adrian
Fri, Feb 3, 2017 10:06 PM

Sure:
// File A$special="No, I'm just weird.";function special() = $special;module
special(){    echo($special);}// File
Binclude<A.scad>//use<A.scad>echo (special());$special = "I'm
special!";special();
If include is used, then /"I'm special!"/ comes up twice, this is what I
expected for both include and use.  When use is used, then /"No, I'm
just weird."/ comes up.

--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20310.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Sure: // File A$special="No, I'm just weird.";function special() = $special;module special(){ echo($special);}// File Binclude&lt;A.scad>//use&lt;A.scad>echo (special());$special = "I'm special!";special(); If *include* is used, then /"I'm special!"/ comes up twice, this is what I expected for both *include* and *use*. When *use* is used, then /"No, I'm just weird."/ comes up. -- View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20310.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Sat, Feb 4, 2017 12:57 PM

When file A.scad is included there is only one top level scope so it works
as expected. I.e. just the same as if you pasted A.scad into B.scad.

When you use a file things get very weird. The used file has its own
separate top level scope. But one would expect dynamic scope variables to
override that when functions and modules are called.

This is the work around that I use and I don't have an explanation why it
works.

// File A

special= $special == undef ? "No, I'm just weird." : $special;
function special() = special;
module special()
{
echo(special, $special);
}

If $special is not set in B.scad then it prints:
ECHO: "No, I'm just weird."

ECHO: "No, I'm just weird.", undef

If $special is set then it prints:

ECHO: "I'm special!"

ECHO: "I'm special!", "I'm special!"

On 3 February 2017 at 22:06, adrian adrianh.bsc@gmail.com wrote:

Sure:

// File A

$special="No, I'm just weird.";
function special() = $special;
module special()
{
echo($special);
}

// File B

include<A.scad>
//use<A.scad>
echo (special());
$special = "I'm special!";
special();

If include is used, then "I'm special!" comes up twice, this is what
I expected for both include and use. When use is used, then "No,
I'm just weird."
comes up.

View this message in context: Re: Special variable scoping rules
http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20310.html

Sent from the OpenSCAD mailing list archive http://forum.openscad.org/
at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

When file A.scad is included there is only one top level scope so it works as expected. I.e. just the same as if you pasted A.scad into B.scad. When you use a file things get very weird. The used file has its own separate top level scope. But one would expect dynamic scope variables to override that when functions and modules are called. This is the work around that I use and I don't have an explanation why it works. // File A special= $special == undef ? "No, I'm just weird." : $special; function special() = special; module special() { echo(special, $special); } If $special is not set in B.scad then it prints: ECHO: "No, I'm just weird." ECHO: "No, I'm just weird.", undef If $special is set then it prints: ECHO: "I'm special!" ECHO: "I'm special!", "I'm special!" On 3 February 2017 at 22:06, adrian <adrianh.bsc@gmail.com> wrote: > Sure: > > // File A > > $special="No, I'm just weird."; > function special() = $special; > module special() > { > echo($special); > } > > // File B > > include<A.scad> > //use<A.scad> > echo (special()); > $special = "I'm special!"; > special(); > > If *include* is used, then *"I'm special!"* comes up twice, this is what > I expected for both *include* and *use*. When *use* is used, then *"No, > I'm just weird."* comes up. > ------------------------------ > View this message in context: Re: Special variable scoping rules > <http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20310.html> > > Sent from the OpenSCAD mailing list archive <http://forum.openscad.org/> > at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
R
Ronaldo
Mon, Feb 6, 2017 3:34 PM

nophead wrote

This is the work around that I use and I don't have an explanation why it
works.

It seems that when you use an OpenSCAD file, the assignments in the used
file override the assignments in the main file.

--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20345.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

nophead wrote > This is the work around that I use and I don't have an explanation why it > works. It seems that when you use an OpenSCAD file, the assignments in the used file override the assignments in the main file. -- View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20345.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Tue, Feb 7, 2017 7:28 PM

So to me, this sounds like it is a bug.  It's definitely not what I would
have expected.  What does eveyone else think?

--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20361.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

So to me, this sounds like it is a bug. It's definitely not what I would have expected. What does eveyone else think? -- View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20361.html Sent from the OpenSCAD mailing list archive at Nabble.com.
N
nophead
Tue, Feb 7, 2017 7:57 PM

It's hard to say because OpenSCAD's scope rules are unique, so you can't
compare them with an existing language to say what is expected in this
situation. You can't normally inject symbols into another module you are
using.

It seems you can inject special variables but whether they should override
special variables in the used module I am not sure. It is probably more
useful if they do but you can work around it.

--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20362.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

It's hard to say because OpenSCAD's scope rules are unique, so you can't compare them with an existing language to say what is expected in this situation. You can't normally inject symbols into another module you are using. It seems you can inject special variables but whether they should override special variables in the used module I am not sure. It is probably more useful if they do but you can work around it. -- View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20362.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Wed, Feb 8, 2017 5:10 AM

Thanks Adrian,

Special variables is probably one of the worst design mistakes in OpenSCAD. I would strongly recommend not using your own special variables. The main purpose of introducing these was to allow dynamic binding of tessellation density ($fn/$fs/$fa) variables, but the mechanism was (somehow) extended to catch all variables starting with ‘$’.

I’ll look into this specific case as soon as I find enough space cycles..

-Marius

Thanks Adrian, Special variables is probably one of the worst design mistakes in OpenSCAD. I would strongly recommend not using your own special variables. The main purpose of introducing these was to allow dynamic binding of tessellation density ($fn/$fs/$fa) variables, but the mechanism was (somehow) extended to catch all variables starting with ‘$’. I’ll look into this specific case as soon as I find enough space cycles.. -Marius
NH
nop head
Wed, Feb 8, 2017 8:47 AM

They are essential for passing parameters to children. For example:

function layout_offset(widths, i, gap = 2) = i == 0 ? widths[0] / 2

: layout_offset(widths, i - 1, gap) + widths[i - 1] / 2 + gap + widths[i] /
2;

module layout(widths, gap = 2) {
for($i = [0 : len(widths) - 1])
translate([layout_offset(widths, $i, gap), 0, 0])
children();
}

layout([for(p = pillars) pillar_od(p)])
pillar(pillars[$i]);

On 8 February 2017 at 05:10, Marius Kintel marius@kintel.net wrote:

Thanks Adrian,

Special variables is probably one of the worst design mistakes in
OpenSCAD. I would strongly recommend not using your own special variables.
The main purpose of introducing these was to allow dynamic binding of
tessellation density ($fn/$fs/$fa) variables, but the mechanism was
(somehow) extended to catch all variables starting with ‘$’.

I’ll look into this specific case as soon as I find enough space cycles..

-Marius


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

They are essential for passing parameters to children. For example: function layout_offset(widths, i, gap = 2) = i == 0 ? widths[0] / 2 : layout_offset(widths, i - 1, gap) + widths[i - 1] / 2 + gap + widths[i] / 2; module layout(widths, gap = 2) { for($i = [0 : len(widths) - 1]) translate([layout_offset(widths, $i, gap), 0, 0]) children(); } layout([for(p = pillars) pillar_od(p)]) pillar(pillars[$i]); On 8 February 2017 at 05:10, Marius Kintel <marius@kintel.net> wrote: > Thanks Adrian, > > Special variables is probably one of the worst design mistakes in > OpenSCAD. I would strongly recommend not using your own special variables. > The main purpose of introducing these was to allow dynamic binding of > tessellation density ($fn/$fs/$fa) variables, but the mechanism was > (somehow) extended to catch all variables starting with ‘$’. > > I’ll look into this specific case as soon as I find enough space cycles.. > > -Marius > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
MK
Marius Kintel
Wed, Feb 8, 2017 3:09 PM

On Feb 8, 2017, at 03:47, nop head nop.head@gmail.com wrote:

They are essential for passing parameters to children. For example:

Yes, there are naturally good uses of such constructs (for the above-average power users :))
A good discussion would be the best way of achieving this in the context of a future language revamp.

-Marius

On Feb 8, 2017, at 03:47, nop head <nop.head@gmail.com> wrote: > > They are essential for passing parameters to children. For example: > Yes, there are naturally good uses of such constructs (for the above-average power users :)) A good discussion would be the best way of achieving this in the context of a future language revamp. -Marius