A
adrian
Wed, Feb 8, 2017 4:39 PM
Nophead,
That example doesn't look "essential". Seems that could be achieved just by
using variable i, and passing i as a parameter.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20368.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Nophead,
That example doesn't look "essential". Seems that could be achieved just by
using variable i, and passing i as a parameter.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20368.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Wed, Feb 8, 2017 4:41 PM
Oh wait, I misunderstood. That's clever.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20369.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Oh wait, I misunderstood. That's clever.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20369.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Wed, Feb 8, 2017 8:37 PM
Marius: "Special variables is probably one of the worst design mistakes in
OpenSCAD."
Nop Head: "They are essential for passing parameters to children." <code
example>
Adrian: "That's clever." [My response: but not so easy to understand.]
Marius: "A good discussion would be the best way of achieving this in the
context of a future language revamp."
I'm continuing to work on my new geometry language ("a superset of a subset
of OpenSCAD2").
I haven't implemented special variables, because they are complicated and
tricky, the correct semantics are not clear to me, and I haven't needed
them so far. I was originally planning to implement them, but now I don't
see the need. What I do have (that's missing from OpenSCAD) are records
{n=1, s="abc"}, similar to Javascript object literals, and function
literals (x,y)->x+y.
This language is not OpenSCAD, the programming style is different.
Instead of implicitly passing special variables, I can explicitly pass a
record value containing name/value pairs. The same programming style is
used in Javascript. The explicit style makes it easier to see what is going
on, and is more expressive.
OpenSCAD modules pass children "by name", evaluating the children argument
expression each time children() is referenced. In my language, shapes are
passed by value, all function arguments are evaluated before the function
is entered. To get the effect that Nop Head demonstrated, I pass a function
value, but that is made very convenient using function literals.
OpenSCAD:
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]);
My language:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
Marius: "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 ‘$’."
OpenSCAD tessellates curved surfaces as early as possible. My language uses
functional representation and tessellates curved surfaces as late as
possible. Spheres, cylinders, B-splines (possible future extension), and
their unions and intersections, are all represented exactly, and are not
tessellated until you export to STL. As a result, the motivation to use
dynamic binding for tessellation density variables (you want to avoid
passing these variables explicitly through multiple layers of function
calls) doesn't exist in my language.
I don't use circle($fn=6) to construct a hexagon, I use regular_polygon(6).
Similarly, instead of cylinder($fn=6) I use prism(6).
On 8 February 2017 at 00: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
Marius: "Special variables is probably one of the worst design mistakes in
OpenSCAD."
Nop Head: "They are essential for passing parameters to children." <code
example>
Adrian: "That's clever." [My response: but not so easy to understand.]
Marius: "A good discussion would be the best way of achieving this in the
context of a future language revamp."
I'm continuing to work on my new geometry language ("a superset of a subset
of OpenSCAD2").
I haven't implemented special variables, because they are complicated and
tricky, the correct semantics are not clear to me, and I haven't needed
them so far. I was originally planning to implement them, but now I don't
see the need. What I do have (that's missing from OpenSCAD) are records
{n=1, s="abc"}, similar to Javascript object literals, and function
literals (x,y)->x+y.
This language is *not* OpenSCAD, the programming style is different.
Instead of implicitly passing special variables, I can explicitly pass a
record value containing name/value pairs. The same programming style is
used in Javascript. The explicit style makes it easier to see what is going
on, and is more expressive.
OpenSCAD modules pass children "by name", evaluating the children argument
expression each time children() is referenced. In my language, shapes are
passed by value, all function arguments are evaluated before the function
is entered. To get the effect that Nop Head demonstrated, I pass a function
value, but that is made very convenient using function literals.
OpenSCAD:
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]);
My language:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
Marius: "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 ‘$’."
OpenSCAD tessellates curved surfaces as early as possible. My language uses
functional representation and tessellates curved surfaces as *late* as
possible. Spheres, cylinders, B-splines (possible future extension), and
their unions and intersections, are all represented exactly, and are not
tessellated until you export to STL. As a result, the motivation to use
dynamic binding for tessellation density variables (you want to avoid
passing these variables explicitly through multiple layers of function
calls) doesn't exist in my language.
I don't use circle($fn=6) to construct a hexagon, I use regular_polygon(6).
Similarly, instead of cylinder($fn=6) I use prism(6).
On 8 February 2017 at 00: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
>
NH
nop head
Wed, Feb 8, 2017 9:01 PM
Very nice, no doubt, but the beauty of OpenSCAD was I could immediately
read and understand it because of its familiar syntax. It took me virtually
no learning time at all to be able to code Mendel90.
I can't understand you example code because it looks like no language I
have used. Why square brackets in union()?
Why i->pillar(pillars[i]); Looks like a pointer dereference but i is an
index. Perhaps lambda synstax but I don't see why i is even in scope there.
I doubt I will take the time to learn a more complex language and
unfamiliar language when OpenSCAD does everything I need and is very simple
to read and write.
On 8 February 2017 at 20:37, doug moen doug@moens.org wrote:
Marius: "Special variables is probably one of the worst design mistakes
in OpenSCAD."
Nop Head: "They are essential for passing parameters to children." <code
example>
Adrian: "That's clever." [My response: but not so easy to understand.]
Marius: "A good discussion would be the best way of achieving this in the
context of a future language revamp."
I'm continuing to work on my new geometry language ("a superset of a
subset of OpenSCAD2").
I haven't implemented special variables, because they are complicated and
tricky, the correct semantics are not clear to me, and I haven't needed
them so far. I was originally planning to implement them, but now I don't
see the need. What I do have (that's missing from OpenSCAD) are records
{n=1, s="abc"}, similar to Javascript object literals, and function
literals (x,y)->x+y.
This language is not OpenSCAD, the programming style is different.
Instead of implicitly passing special variables, I can explicitly pass a
record value containing name/value pairs. The same programming style is
used in Javascript. The explicit style makes it easier to see what is going
on, and is more expressive.
OpenSCAD modules pass children "by name", evaluating the children argument
expression each time children() is referenced. In my language, shapes are
passed by value, all function arguments are evaluated before the function
is entered. To get the effect that Nop Head demonstrated, I pass a function
value, but that is made very convenient using function literals.
OpenSCAD:
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]);
My language:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
Marius: "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 ‘$’."
OpenSCAD tessellates curved surfaces as early as possible. My language
uses functional representation and tessellates curved surfaces as late as
possible. Spheres, cylinders, B-splines (possible future extension), and
their unions and intersections, are all represented exactly, and are not
tessellated until you export to STL. As a result, the motivation to use
dynamic binding for tessellation density variables (you want to avoid
passing these variables explicitly through multiple layers of function
calls) doesn't exist in my language.
I don't use circle($fn=6) to construct a hexagon, I use
regular_polygon(6). Similarly, instead of cylinder($fn=6) I use prism(6).
On 8 February 2017 at 00: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
Very nice, no doubt, but the beauty of OpenSCAD was I could immediately
read and understand it because of its familiar syntax. It took me virtually
no learning time at all to be able to code Mendel90.
I can't understand you example code because it looks like no language I
have used. Why square brackets in union()?
Why i->pillar(pillars[i]); Looks like a pointer dereference but i is an
index. Perhaps lambda synstax but I don't see why i is even in scope there.
I doubt I will take the time to learn a more complex language and
unfamiliar language when OpenSCAD does everything I need and is very simple
to read and write.
On 8 February 2017 at 20:37, doug moen <doug@moens.org> wrote:
> Marius: "Special variables is probably one of the worst design mistakes
> in OpenSCAD."
> Nop Head: "They are essential for passing parameters to children." <code
> example>
> Adrian: "That's clever." [My response: but not so easy to understand.]
> Marius: "A good discussion would be the best way of achieving this in the
> context of a future language revamp."
>
> I'm continuing to work on my new geometry language ("a superset of a
> subset of OpenSCAD2").
>
> I haven't implemented special variables, because they are complicated and
> tricky, the correct semantics are not clear to me, and I haven't needed
> them so far. I was originally planning to implement them, but now I don't
> see the need. What I do have (that's missing from OpenSCAD) are records
> {n=1, s="abc"}, similar to Javascript object literals, and function
> literals (x,y)->x+y.
>
> This language is *not* OpenSCAD, the programming style is different.
>
> Instead of implicitly passing special variables, I can explicitly pass a
> record value containing name/value pairs. The same programming style is
> used in Javascript. The explicit style makes it easier to see what is going
> on, and is more expressive.
>
> OpenSCAD modules pass children "by name", evaluating the children argument
> expression each time children() is referenced. In my language, shapes are
> passed by value, all function arguments are evaluated before the function
> is entered. To get the effect that Nop Head demonstrated, I pass a function
> value, but that is made very convenient using function literals.
>
> OpenSCAD:
> 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]);
>
> My language:
> layout(widths, gap=2) f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
> layout([for(p = pillars) pillar_od(p)])
> i->pillar(pillars[i]);
>
> Marius: "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 ‘$’."
>
> OpenSCAD tessellates curved surfaces as early as possible. My language
> uses functional representation and tessellates curved surfaces as *late* as
> possible. Spheres, cylinders, B-splines (possible future extension), and
> their unions and intersections, are all represented exactly, and are not
> tessellated until you export to STL. As a result, the motivation to use
> dynamic binding for tessellation density variables (you want to avoid
> passing these variables explicitly through multiple layers of function
> calls) doesn't exist in my language.
>
> I don't use circle($fn=6) to construct a hexagon, I use
> regular_polygon(6). Similarly, instead of cylinder($fn=6) I use prism(6).
>
> On 8 February 2017 at 00: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
>>
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
DM
doug moen
Wed, Feb 8, 2017 9:39 PM
Hi Nop Head. The language I'm working on is for me, not for you. I can
build geometric objects in it that I can't construct in OpenSCAD, but your
uses are a lot different than mine, so I wouldn't expect it to be useful to
you. And yes, it isn't a C-like language.
My implementation of union is a function that takes a list of shapes as an
argument. That was the simplest code I could write that worked. I have to
invoke union explicitly here because I haven't implemented "implicit union"
yet, except at the top level.
i->pillar(pillars[i]) is a function literal with a single parameter 'i'. In
Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses -> in
its syntax for lambda expressions, and so do many other languages.
The reason I responded is because Marius surprised me by inviting a
discussion about how to get rid of special variables in a future revamp of
OpenSCAD. Since I'm creating a related geometry language that already works
that way, my experiences would be relevant to that discussion.
On 8 February 2017 at 16:01, nop head nop.head@gmail.com wrote:
Very nice, no doubt, but the beauty of OpenSCAD was I could immediately
read and understand it because of its familiar syntax. It took me virtually
no learning time at all to be able to code Mendel90.
I can't understand you example code because it looks like no language I
have used. Why square brackets in union()?
Why i->pillar(pillars[i]); Looks like a pointer dereference but i is an
index. Perhaps lambda synstax but I don't see why i is even in scope there.
I doubt I will take the time to learn a more complex language and
unfamiliar language when OpenSCAD does everything I need and is very simple
to read and write.
On 8 February 2017 at 20:37, doug moen doug@moens.org wrote:
Marius: "Special variables is probably one of the worst design mistakes
in OpenSCAD."
Nop Head: "They are essential for passing parameters to children." <code
example>
Adrian: "That's clever." [My response: but not so easy to understand.]
Marius: "A good discussion would be the best way of achieving this in
the context of a future language revamp."
I'm continuing to work on my new geometry language ("a superset of a
subset of OpenSCAD2").
I haven't implemented special variables, because they are complicated and
tricky, the correct semantics are not clear to me, and I haven't needed
them so far. I was originally planning to implement them, but now I don't
see the need. What I do have (that's missing from OpenSCAD) are records
{n=1, s="abc"}, similar to Javascript object literals, and function
literals (x,y)->x+y.
This language is not OpenSCAD, the programming style is different.
Instead of implicitly passing special variables, I can explicitly pass a
record value containing name/value pairs. The same programming style is
used in Javascript. The explicit style makes it easier to see what is going
on, and is more expressive.
OpenSCAD modules pass children "by name", evaluating the children
argument expression each time children() is referenced. In my language,
shapes are passed by value, all function arguments are evaluated before the
function is entered. To get the effect that Nop Head demonstrated, I pass a
function value, but that is made very convenient using function literals.
OpenSCAD:
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]);
My language:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
Marius: "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 ‘$’."
OpenSCAD tessellates curved surfaces as early as possible. My language
uses functional representation and tessellates curved surfaces as late as
possible. Spheres, cylinders, B-splines (possible future extension), and
their unions and intersections, are all represented exactly, and are not
tessellated until you export to STL. As a result, the motivation to use
dynamic binding for tessellation density variables (you want to avoid
passing these variables explicitly through multiple layers of function
calls) doesn't exist in my language.
I don't use circle($fn=6) to construct a hexagon, I use
regular_polygon(6). Similarly, instead of cylinder($fn=6) I use prism(6).
On 8 February 2017 at 00: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
Hi Nop Head. The language I'm working on is for me, not for you. I can
build geometric objects in it that I can't construct in OpenSCAD, but your
uses are a lot different than mine, so I wouldn't expect it to be useful to
you. And yes, it isn't a C-like language.
My implementation of union is a function that takes a list of shapes as an
argument. That was the simplest code I could write that worked. I have to
invoke union explicitly here because I haven't implemented "implicit union"
yet, except at the top level.
i->pillar(pillars[i]) is a function literal with a single parameter 'i'. In
Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses -> in
its syntax for lambda expressions, and so do many other languages.
The reason I responded is because Marius surprised me by inviting a
discussion about how to get rid of special variables in a future revamp of
OpenSCAD. Since I'm creating a related geometry language that already works
that way, my experiences would be relevant to that discussion.
On 8 February 2017 at 16:01, nop head <nop.head@gmail.com> wrote:
> Very nice, no doubt, but the beauty of OpenSCAD was I could immediately
> read and understand it because of its familiar syntax. It took me virtually
> no learning time at all to be able to code Mendel90.
>
> I can't understand you example code because it looks like no language I
> have used. Why square brackets in union()?
>
> Why i->pillar(pillars[i]); Looks like a pointer dereference but i is an
> index. Perhaps lambda synstax but I don't see why i is even in scope there.
>
> I doubt I will take the time to learn a more complex language and
> unfamiliar language when OpenSCAD does everything I need and is very simple
> to read and write.
>
> On 8 February 2017 at 20:37, doug moen <doug@moens.org> wrote:
>
>> Marius: "Special variables is probably one of the worst design mistakes
>> in OpenSCAD."
>> Nop Head: "They are essential for passing parameters to children." <code
>> example>
>> Adrian: "That's clever." [My response: but not so easy to understand.]
>> Marius: "A good discussion would be the best way of achieving this in
>> the context of a future language revamp."
>>
>> I'm continuing to work on my new geometry language ("a superset of a
>> subset of OpenSCAD2").
>>
>> I haven't implemented special variables, because they are complicated and
>> tricky, the correct semantics are not clear to me, and I haven't needed
>> them so far. I was originally planning to implement them, but now I don't
>> see the need. What I do have (that's missing from OpenSCAD) are records
>> {n=1, s="abc"}, similar to Javascript object literals, and function
>> literals (x,y)->x+y.
>>
>> This language is *not* OpenSCAD, the programming style is different.
>>
>> Instead of implicitly passing special variables, I can explicitly pass a
>> record value containing name/value pairs. The same programming style is
>> used in Javascript. The explicit style makes it easier to see what is going
>> on, and is more expressive.
>>
>> OpenSCAD modules pass children "by name", evaluating the children
>> argument expression each time children() is referenced. In my language,
>> shapes are passed by value, all function arguments are evaluated before the
>> function is entered. To get the effect that Nop Head demonstrated, I pass a
>> function value, but that is made very convenient using function literals.
>>
>> OpenSCAD:
>> 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]);
>>
>> My language:
>> layout(widths, gap=2) f = union([
>> for (i=[0..len(widths) - 1])
>> translate([layout_offset(widths, i, gap), 0, 0])
>> f(i)
>> ]);
>> layout([for(p = pillars) pillar_od(p)])
>> i->pillar(pillars[i]);
>>
>> Marius: "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 ‘$’."
>>
>> OpenSCAD tessellates curved surfaces as early as possible. My language
>> uses functional representation and tessellates curved surfaces as *late* as
>> possible. Spheres, cylinders, B-splines (possible future extension), and
>> their unions and intersections, are all represented exactly, and are not
>> tessellated until you export to STL. As a result, the motivation to use
>> dynamic binding for tessellation density variables (you want to avoid
>> passing these variables explicitly through multiple layers of function
>> calls) doesn't exist in my language.
>>
>> I don't use circle($fn=6) to construct a hexagon, I use
>> regular_polygon(6). Similarly, instead of cylinder($fn=6) I use prism(6).
>>
>> On 8 February 2017 at 00: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
>>>
>>
>>
>> _______________________________________________
>> OpenSCAD mailing list
>> Discuss@lists.openscad.org
>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>>
>>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
A
adrian
Thu, Feb 9, 2017 12:33 AM
i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
InJavascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
inits syntax for lambda expressions, and so do many other languages.
Sorry, I am having difficulty trying to understand you syntax as well.
Given:
layout(widths, gap=2) f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)]);layout([for(p = pillars) pillar_od(p)]) i->pillar(pillars[i]);
I take it that layout(widths, gap=2) is a module definition.
f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0]) f(i)]);
would appear to be the body of that definition.
layout([for(p = pillars) pillar_od(p)]) would appear to be calling the
module with [for(p = pillars) pillar_od(p)] being passed to /widths/, and
i->pillar(pillars[i]); would then appear to be the children you will be
passing?
Within the body of your module, you are referencing /f/, which is being
assigned within the body of the module, but not assigned quite yet.
I'm really having a lot of difficulty as to what you are trying to express
here.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug.moen wrote
> i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
> InJavascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
> inits syntax for lambda expressions, and so do many other languages.
Sorry, I am having difficulty trying to understand you syntax as well.
Given:
layout(widths, gap=2) f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)]);layout([for(p = pillars) pillar_od(p)]) i->pillar(pillars[i]);
I take it that *layout(widths, gap=2)* is a module definition.
f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0]) f(i)]);
would appear to be the body of that definition.
*layout([for(p = pillars) pillar_od(p)])* would appear to be calling the
module with *[for(p = pillars) pillar_od(p)]* being passed to /widths/, and
*i->pillar(pillars[i]);* would then appear to be the children you will be
passing?
Within the body of your module, you are referencing /f/, which is being
assigned within the body of the module, but not assigned quite yet.
I'm really having a lot of difficulty as to what you are trying to express
here.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Thu, Feb 9, 2017 12:43 AM
It would be more normal to have f in the argument list and pass the
function literal inside the parenthesis.
layout(widths, f, gap=2 = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)], i->pillar(pillars[i]));
But if you have function parameters then you can pass the width
function instead of list of widths.
On 9 February 2017 at 00:33, adrian adrianh.bsc@gmail.com wrote:
doug.moen wrote
i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
in its syntax for lambda expressions, and so do many other languages.
Sorry, I am having difficulty trying to understand you syntax as well.
Given:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
I take it that layout(widths, gap=2) is a module definition.
f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
would appear to be the body of that definition.
layout([for(p = pillars) pillar_od(p)]) would appear to be calling the
module with [for(p = pillars) pillar_od(p)] being passed to widths,
and i->pillar(pillars[i]); would then appear to be the children you
will be passing?
Within the body of your module, you are referencing f, which is being
assigned within the body of the module, but not assigned quite yet.
I'm really having a lot of difficulty as to what you are trying to express
here.
View this message in context: Re: Special variable scoping rules
http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.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
It would be more normal to have f in the argument list and pass the
function literal inside the parenthesis.
layout(widths, f, gap=2 = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)], i->pillar(pillars[i]));
But if you have function parameters then you can pass the width
function instead of list of widths.
On 9 February 2017 at 00:33, adrian <adrianh.bsc@gmail.com> wrote:
> doug.moen wrote
> i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
> In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
> in its syntax for lambda expressions, and so do many other languages.
>
> Sorry, I am having difficulty trying to understand you syntax as well.
> Given:
>
> layout(widths, gap=2) f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
> layout([for(p = pillars) pillar_od(p)])
> i->pillar(pillars[i]);
>
> I take it that *layout(widths, gap=2)* is a module definition.
>
> f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
>
> would appear to be the body of that definition.
>
> *layout([for(p = pillars) pillar_od(p)])* would appear to be calling the
> module with *[for(p = pillars) pillar_od(p)]* being passed to *widths*,
> and *i->pillar(pillars[i]);* would then appear to be the children you
> will be passing?
>
> Within the body of your module, you are referencing *f*, which is being
> assigned within the body of the module, but not assigned quite yet.
>
> I'm really having a lot of difficulty as to what you are trying to express
> here.
>
> ------------------------------
> View this message in context: Re: Special variable scoping rules
> <http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.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
>
>
DM
doug moen
Thu, Feb 9, 2017 1:19 AM
In OpenSCAD, you can write
translate([10,10]) square(5)
I wanted to support that syntax in my language. I don't have OpenSCAD-style
modules, only functions. So translate and square are functions that return
shapes.
Obviously it would be possible to use
translate([10,10], square(5))
but I like the OpenSCAD syntax better.
So I defined translate(vector) as a function that returns a 2nd function
that takes a shape as an argument, and returns the translated shape as a
result. So you can write
translate([10,10])(square(5))
Then I added another grammar rule that lets you omit the parentheses around
an argument list if there is a single argument, that is a function call
beginning with an identifier. It's an abbreviation. So you can abbreviate
the above expression as:
translate([10,10]) square(5)
I guess it is an open question whether the OpenSCAD "module call" syntax is
better than the standard function call syntax. But this is my experimental
toy language, so I decided to implement this syntax to see if it is usable.
I'm not 100% sure, but it seems okay so far.
The actual definition of the translate function, in the standard library,
has this form:
translate(vector) shape = ... ;
Here, 'vector' and 'shape' are both formal parameters. I don't have
modules, so I don't have 'children()'. The 'shape' parameter is used in
place of 'children()'. You can also write the same function definition like
this:
translate(vector)(shape) = ... ;
but the same grammar production that lets me leave off the final set of
parentheses in the call to translate also lets me omit the parentheses
around 'shape' in the definition, so I got used to writing function
definitions this way.
PS you can also write
v = [10,10];
s = square(5);
translate(v) s;
So the definition of translate consists of a prototypical call to the
function, followed by '=', followed by the body.
Doug.
On 8 February 2017 at 19:33, adrian adrianh.bsc@gmail.com wrote:
doug.moen wrote
i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
in its syntax for lambda expressions, and so do many other languages.
Sorry, I am having difficulty trying to understand you syntax as well.
Given:
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
I take it that layout(widths, gap=2) is a module definition.
f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
would appear to be the body of that definition.
layout([for(p = pillars) pillar_od(p)]) would appear to be calling the
module with [for(p = pillars) pillar_od(p)] being passed to widths,
and i->pillar(pillars[i]); would then appear to be the children you
will be passing?
Within the body of your module, you are referencing f, which is being
assigned within the body of the module, but not assigned quite yet.
I'm really having a lot of difficulty as to what you are trying to express
here.
View this message in context: Re: Special variable scoping rules
http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.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
In OpenSCAD, you can write
translate([10,10]) square(5)
I wanted to support that syntax in my language. I don't have OpenSCAD-style
modules, only functions. So translate and square are functions that return
shapes.
Obviously it would be possible to use
translate([10,10], square(5))
but I like the OpenSCAD syntax better.
So I defined translate(vector) as a function that returns a 2nd function
that takes a shape as an argument, and returns the translated shape as a
result. So you can write
translate([10,10])(square(5))
Then I added another grammar rule that lets you omit the parentheses around
an argument list if there is a single argument, that is a function call
beginning with an identifier. It's an abbreviation. So you can abbreviate
the above expression as:
translate([10,10]) square(5)
I guess it is an open question whether the OpenSCAD "module call" syntax is
better than the standard function call syntax. But this is my experimental
toy language, so I decided to implement this syntax to see if it is usable.
I'm not 100% sure, but it seems okay so far.
The actual definition of the `translate` function, in the standard library,
has this form:
translate(vector) shape = ... ;
Here, 'vector' and 'shape' are both formal parameters. I don't have
modules, so I don't have 'children()'. The 'shape' parameter is used in
place of 'children()'. You can also write the same function definition like
this:
translate(vector)(shape) = ... ;
but the same grammar production that lets me leave off the final set of
parentheses in the call to translate also lets me omit the parentheses
around 'shape' in the definition, so I got used to writing function
definitions this way.
PS you can also write
v = [10,10];
s = square(5);
translate(v) s;
So the definition of translate consists of a prototypical call to the
function, followed by '=', followed by the body.
Doug.
On 8 February 2017 at 19:33, adrian <adrianh.bsc@gmail.com> wrote:
> doug.moen wrote
> i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
> In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
> in its syntax for lambda expressions, and so do many other languages.
>
> Sorry, I am having difficulty trying to understand you syntax as well.
> Given:
>
> layout(widths, gap=2) f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
> layout([for(p = pillars) pillar_od(p)])
> i->pillar(pillars[i]);
>
> I take it that *layout(widths, gap=2)* is a module definition.
>
> f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
>
> would appear to be the body of that definition.
>
> *layout([for(p = pillars) pillar_od(p)])* would appear to be calling the
> module with *[for(p = pillars) pillar_od(p)]* being passed to *widths*,
> and *i->pillar(pillars[i]);* would then appear to be the children you
> will be passing?
>
> Within the body of your module, you are referencing *f*, which is being
> assigned within the body of the module, but not assigned quite yet.
>
> I'm really having a lot of difficulty as to what you are trying to express
> here.
>
> ------------------------------
> View this message in context: Re: Special variable scoping rules
> <http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20373.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
>
>
A
adrian
Thu, Feb 9, 2017 1:58 AM
i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses
-> in its syntax for lambda expressions, and so do many other languages.
Oh, and C++11 doesn't use -> for its lambda expressions exactly, it is an
artifact of how regular functions signatures can now be written as:
auto fn() -> ret_type
Allowing for return type inference. Lambda only uses -> because it allows
for the return type to be explicitly specified instead of inferred.
I'm understanding your code a bit more, but I'm still trying to wrap my head
around it. In
layout(widths, gap=2) f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)]);layout([for(p = pillars) pillar_od(p)]) i->pillar(pillars[i]);
What is the /i/ to the left of the -> in /i->pillar(pillars[i]);/ supposed
to be? Is it getting the /i/ from the /f(i)/? In which case, it would
appear that you are doing something similar to what nophead is doing. If
not, then I'm just lost.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20376.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug.moen wrote
> i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
> In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses
> -> in its syntax for lambda expressions, and so do many other languages.
Oh, and C++11 doesn't use -> for its lambda expressions exactly, it is an
artifact of how regular functions signatures can now be written as:
auto fn() -> ret_type
Allowing for return type inference. Lambda only uses -> because it allows
for the return type to be explicitly specified instead of inferred.
I'm understanding your code a bit more, but I'm still trying to wrap my head
around it. In
layout(widths, gap=2) f = union([ for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)]);layout([for(p = pillars) pillar_od(p)]) i->pillar(pillars[i]);
What is the /i/ to the left of the *->* in /i->pillar(pillars[i]);/ supposed
to be? Is it getting the /i/ from the /f(i)/? In which case, it would
appear that you are doing something similar to what nophead is doing. If
not, then I'm just lost.
--
View this message in context: http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20376.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Thu, Feb 9, 2017 3:01 AM
i->pillar(pillars[i])
This is a function literal. The formal parameter is 'i', the body of the
function is 'pillar(pillars[i])'.
Just as if you had defined
F(i) = pillar(pillars[i]);
and then used the value of 'F'.
The layout function has a formal parameter 'f', and when layout is called,
the function "i->pillar(pillars[i])" is bound to the parameter 'f'.
It might have been clearer if I had used a different name than 'i' for the
formal parameter, to make it clear that this is a different 'i' than the
'i' used in the for loop. I will also get rid of the "curried" function
call syntax, which is causing confusion.
layout(widths, gap, f) = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout(
[for(p = pillars) pillar_od(p)],
2,
x->pillar(pillars[x]));
In the functional programming style that I am using, it is common to pass
functions as arguments and return functions as results. It helps to have a
very terse syntax for anonymous function literals.
The technique that Nop Head is using is an advanced technique that isn't
documented in the OpenSCAD manual, and probably most people don't know the
feature exists. To do the same thing in my language, you must instead pass
functions as arguments, which is arguably also an advanced technique.
Another way to write the layout function in my language is to pass a list
of shapes as the third argument. This is less "magical" than passing a
function argument, I think.
layout(widths, gap, shapes) = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
shapes[i]
]);
layout(
[for (p = pillars) pillar_od(p)],
2,
[for (p = pillars) pillar(p)]);
On 8 February 2017 at 20:58, adrian adrianh.bsc@gmail.com wrote:
doug.moen wrote
i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
in its syntax for lambda expressions, and so do many other languages.
Oh, and C++11 doesn't use -> for its lambda expressions exactly, it is an
artifact of how regular functions signatures can now be written as:
auto fn() -> ret_type
Allowing for return type inference. Lambda only uses -> because it allows
for the return type to be explicitly specified instead of inferred.
I'm understanding your code a bit more, but I'm still trying to wrap my
head around it. In
layout(widths, gap=2) f = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout([for(p = pillars) pillar_od(p)])
i->pillar(pillars[i]);
What is the i to the left of the -> in i->pillar(pillars[i]);
supposed to be? Is it getting the i from the f(i)? In which case, it
would appear that you are doing something similar to what nophead is doing.
If not, then I'm just lost.
View this message in context: Re: Special variable scoping rules
http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20376.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
i->pillar(pillars[i])
This is a function literal. The formal parameter is 'i', the body of the
function is 'pillar(pillars[i])'.
Just as if you had defined
F(i) = pillar(pillars[i]);
and then used the value of 'F'.
The layout function has a formal parameter 'f', and when layout is called,
the function "i->pillar(pillars[i])" is bound to the parameter 'f'.
It might have been clearer if I had used a different name than 'i' for the
formal parameter, to make it clear that this is a different 'i' than the
'i' used in the for loop. I will also get rid of the "curried" function
call syntax, which is causing confusion.
layout(widths, gap, f) = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
f(i)
]);
layout(
[for(p = pillars) pillar_od(p)],
2,
x->pillar(pillars[x]));
In the functional programming style that I am using, it is common to pass
functions as arguments and return functions as results. It helps to have a
very terse syntax for anonymous function literals.
The technique that Nop Head is using is an advanced technique that isn't
documented in the OpenSCAD manual, and probably most people don't know the
feature exists. To do the same thing in my language, you must instead pass
functions as arguments, which is arguably also an advanced technique.
Another way to write the layout function in my language is to pass a list
of shapes as the third argument. This is less "magical" than passing a
function argument, I think.
layout(widths, gap, shapes) = union([
for (i=[0..len(widths) - 1])
translate([layout_offset(widths, i, gap), 0, 0])
shapes[i]
]);
layout(
[for (p = pillars) pillar_od(p)],
2,
[for (p = pillars) pillar(p)]);
On 8 February 2017 at 20:58, adrian <adrianh.bsc@gmail.com> wrote:
> doug.moen wrote
> i->pillar(pillars[i]) is a function literal with a single parameter 'i'.
> In Javascript, you would instead write i=>pillar(pillars[i]). C++11 uses ->
> in its syntax for lambda expressions, and so do many other languages.
>
> Oh, and C++11 doesn't use -> for its lambda expressions exactly, it is an
> artifact of how regular functions signatures can now be written as:
>
> auto fn() -> ret_type
>
> Allowing for return type inference. Lambda only uses -> because it allows
> for the return type to be explicitly specified instead of inferred.
>
> I'm understanding your code a bit more, but I'm still trying to wrap my
> head around it. In
>
> layout(widths, gap=2) f = union([
> for (i=[0..len(widths) - 1])
> translate([layout_offset(widths, i, gap), 0, 0])
> f(i)
> ]);
> layout([for(p = pillars) pillar_od(p)])
> i->pillar(pillars[i]);
>
> What is the *i* to the left of the *->* in *i->pillar(pillars[i]);*
> supposed to be? Is it getting the *i* from the *f(i)*? In which case, it
> would appear that you are doing something similar to what nophead is doing.
> If not, then I'm just lost.
>
> ------------------------------
> View this message in context: Re: Special variable scoping rules
> <http://forum.openscad.org/Special-variable-scoping-rules-tp20305p20376.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
>
>