discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

What happened to booleans?

A
adrianv
Sat, Aug 1, 2020 12:51 AM

So you're saying that

foo=sin;

creates a function literal but

sin=12;
foo=sin;

creates a number?  Or maybe I misunderstand.  Do other people think this is
a good idea?  This breaks OpenSCAD's general system of having different
namespaces for variables and functions.  Given that variables and functions
have their own namespace I should be able to introduce a "sin" variable
without changing how my code interacts with the function namespace.

Also, it should be possible to do the same thing with a user defined
function, that is, I should be able to have a library define

function cosh(x) =(exp(x)+exp(-x))/2;

then then I should be able to set

foo = cosh

in the same way that I could set

foo = cos,

converting a defined function (whether builtin or not) into a function
literal.  There shouldn't be a different syntax required for non built-ins
than for built-ins.  A library should be able to define cosh and a user not
have to know that it is not a built-in.

thehans wrote

The difference is that undef is an already established builtin constant
value
, but sin is not.
x = sin;
WARNING: Ignoring unknown variable 'sin', in file , line 1.

If builtin functions were treated as literals, then that would be fine
with
no warning, and x would then hold a FunctionType value.

The user would of course be free to assign a value to their own variable
named "sin", and this would shadow our hypothetical builtin function
literal of the same name.
It would be a weird thing for the user to do, but not ambiguous.

On Fri, Jul 31, 2020 at 6:35 PM adrianv <

avm4@

> wrote:

I hadn't really thought about how function literals might be involved
here.
But I'm a little puzzled.  Suppose builtin functions can be treated as
literals as shown below.  Then

foo = sin

is ambiguous about whether I mean the function "sin" or the variable
"sin".
I would think that if you want to make regular functions (and built-ins)
available as literals---which is a really good idea because otherwise it
creates a confusing situation where some functions need to be redefined
as
function literals for convenience---you should do something like what
MATLAB
does and create a syntax for it.  In MATLAB you create a function literal
(they call them handles) from (any) function using "@".  So in MATLAB

foo = @sin

assigns a function literal into foo.  And the call

foo(@sin,@cos)

passes two function literals into the function foo.  Given how namespaces
work in OpenSCAD there's no way to assign a pre-existing function to a
variable or pass functions as literals without a new syntax that
"converts"
the function into a literal.

But my point is that

foo=undef

is not any more ambiguous than

foo=sin

so it's not a problem that has to do with undef.  So I still don't see
any
issue with using the functional form I proposed.

foo = undef;  // Plain undef without text
foo = undef("reason");  // undef with text
foo = @undef;  // or whatever new syntax....  the undef
function...though
why would you ever want that?

Have I missed something?

thehans wrote

As Doug points out, the situation is more complicated if you account

for

function literals, which already exist as an experimental feature.
It's not necessarily an issue at the moment, but If we ever decided to
make
builtin functions accessible as literals (personally i would like to

see

this), then writing: foo = undef; would be ambiguous whether you want

the

function literal value or the actual undef literal.

On Fri, Jul 31, 2020 at 5:29 PM adrianv <

avm4@

> wrote:

What is confusing about calling undef() like a function?  You say we
don't
want to "mix up" the undef literal with an undef constructor, but

what's

the
difference really between

undef

and

undef("some reason text")

Isn't the first one basically the same as the second one only with the
argument missing, in some sense?  What's the problem or consequence of
"mixing up" these two things?  When there's no string associated with

an

undef then what is there?  Empty string?  Another undef?  It's a bit
unclear what the advantage is of not having a string.  Shouldn't there
always be one?  (undef: "list index out of bounds", undef: "variable

not

set", undef: "mismatched argument types for +".)  It seems like you'd
want
to encourage users to supply the string any time they make an

assignment.

I guess there's the question of what it means if you just write
"foo=undef",
as in that case there's no string.  The string could be "direct
assignment"
or something like that.

To me it seems like doing

foo = undef

but

foo = undefined("some reason")

is more confusing because now I have to remember when to use undef and
when
to use undefined.  It looks like undef is already illegal as a

function

name, so it wouldn't break any code, whereas undefined() is currently

a

valid function, so using that could break code.

thehans wrote

No I haven't added any mechanism to query or set undefined strings
programmatically from scripts, since I felt like that needed some

more

thought and planning around the interface, and wanted to limit this

PR

to

only the least contentious changes.

Adding either of those should be fairly quick and simple to

implement

though.

For displaying the string, i considered that echo() and str() could
possibly automatically show the undef strings if any.  But this

might

end

up with more verbose messages than people would like for general

cases.

Also as far as I know, echo() and str() generally work in such a way

where

you could copy/paste output back into a script and it should be

parsed

into
the same literal values.  So doing something like that should
probably require that we first lock in how the string would be set
programmatically (see below).
Having assert() handle undef as a special case might be one good way

to

inspect for reason strings though.

Another possibility is that the reason string could be a "member

lookup"

on
undef types, so e.g. ( some_undef_value.reason ) could return a

string.

But then should an undef without any string return undef for that as
well?(its undefs all the way down!)
And would ".reason" on a non-undef type also be undef, or throw an

actual

error?

For setting the string, I don't think calling undef() like a

function

is
a

good idea, since we don't want to mix up the default literal "undef"
identifier with a new builtin function(constructor basically)

identifier

of
the same name.  But perhaps a function named undefined() would be

fine,

for
example.

On Fri, Jul 31, 2020 at 5:36 AM adrianv <

avm4@

> wrote:

Another question:  is there a way to create an undef and associate

a

reason,
so for example

undef("line_intersection: lines did not intersect")

JordanBrown wrote

On 7/30/2020 9:24 PM, Hans L wrote:

I've now implemented the capability for undef types to carry a

reason

string.

Cool.

So if your program has an undef in its hands, is there a

straightforward

way to say "what is the reason for this undef"?

I don't know whether it's necessary to have a way to retrieve

the

reason, or just a way to say "hey, I don't want an undef, this is

an

error, report the error with the reason for the undef".

One really simple mechanism might be to have assert(undef) report

the

reason for the undef.

That would be an exception to the general rule that undef is OK

in
a

boolean context, but then again undef is false in a boolean

context

and

assert(false) is an error, so it's not stretching the rule very

much.


OpenSCAD mailing list

Discuss@.openscad

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad


OpenSCAD mailing list

Discuss@.openscad

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

So you're saying that foo=sin; creates a function literal but sin=12; foo=sin; creates a number? Or maybe I misunderstand. Do other people think this is a good idea? This breaks OpenSCAD's general system of having different namespaces for variables and functions. Given that variables and functions have their own namespace I should be able to introduce a "sin" variable without changing how my code interacts with the function namespace. Also, it should be possible to do the same thing with a user defined function, that is, I should be able to have a library define function cosh(x) =(exp(x)+exp(-x))/2; then then I should be able to set foo = cosh in the same way that I could set foo = cos, converting a defined function (whether builtin or not) into a function literal. There shouldn't be a different syntax required for non built-ins than for built-ins. A library should be able to define cosh and a user not have to know that it is not a built-in. thehans wrote > The difference is that undef is an already established builtin *constant > value*, but sin is not. > x = sin; > WARNING: Ignoring unknown variable 'sin', in file , line 1. > > If builtin functions were treated as literals, then that would be fine > with > no warning, and x would then hold a FunctionType value. > > The user would of course be free to assign a value to their own variable > named "sin", and this would shadow our hypothetical builtin function > literal of the same name. > It would be a weird thing for the user to do, but not ambiguous. > > > On Fri, Jul 31, 2020 at 6:35 PM adrianv &lt; > avm4@ > &gt; wrote: > >> I hadn't really thought about how function literals might be involved >> here. >> But I'm a little puzzled. Suppose builtin functions can be treated as >> literals as shown below. Then >> >> foo = sin >> >> is ambiguous about whether I mean the function "sin" or the variable >> "sin". >> I would think that if you want to make regular functions (and built-ins) >> available as literals---which is a really good idea because otherwise it >> creates a confusing situation where some functions need to be redefined >> as >> function literals for convenience---you should do something like what >> MATLAB >> does and create a syntax for it. In MATLAB you create a function literal >> (they call them handles) from (any) function using "@". So in MATLAB >> >> foo = @sin >> >> assigns a function literal into foo. And the call >> >> foo(@sin,@cos) >> >> passes two function literals into the function foo. Given how namespaces >> work in OpenSCAD there's no way to assign a pre-existing function to a >> variable or pass functions as literals without a new syntax that >> "converts" >> the function into a literal. >> >> But my point is that >> >> foo=undef >> >> is not any more ambiguous than >> >> foo=sin >> >> so it's not a problem that has to do with undef. So I still don't see >> any >> issue with using the functional form I proposed. >> >> foo = undef; // Plain undef without text >> foo = undef("reason"); // undef with text >> foo = @undef; // or whatever new syntax.... the undef >> function...though >> why would you ever want that? >> >> Have I missed something? >> >> >> thehans wrote >> > As Doug points out, the situation is more complicated if you account >> for >> > function literals, which already exist as an experimental feature. >> > It's not necessarily an issue at the moment, but If we ever decided to >> > make >> > builtin functions accessible as literals (personally i would like to >> see >> > this), then writing: foo = undef; would be ambiguous whether you want >> the >> > function literal value or the actual undef literal. >> > >> > On Fri, Jul 31, 2020 at 5:29 PM adrianv &lt; >> >> > avm4@ >> >> > &gt; wrote: >> > >> >> What is confusing about calling undef() like a function? You say we >> >> don't >> >> want to "mix up" the undef literal with an undef constructor, but >> what's >> >> the >> >> difference really between >> >> >> >> undef >> >> >> >> and >> >> >> >> undef("some reason text") >> >> >> >> Isn't the first one basically the same as the second one only with the >> >> argument missing, in some sense? What's the problem or consequence of >> >> "mixing up" these two things? When there's no string associated with >> an >> >> undef then what is there? Empty string? Another undef? It's a bit >> >> unclear what the advantage is of not having a string. Shouldn't there >> >> always be one? (undef: "list index out of bounds", undef: "variable >> not >> >> set", undef: "mismatched argument types for +".) It seems like you'd >> >> want >> >> to encourage users to supply the string any time they make an >> assignment. >> >> >> >> I guess there's the question of what it means if you just write >> >> "foo=undef", >> >> as in that case there's no string. The string could be "direct >> >> assignment" >> >> or something like that. >> >> >> >> To me it seems like doing >> >> >> >> foo = undef >> >> >> >> but >> >> >> >> foo = undefined("some reason") >> >> >> >> is more confusing because now I have to remember when to use undef and >> >> when >> >> to use undefined. It looks like undef is already illegal as a >> function >> >> name, so it wouldn't break any code, whereas undefined() is currently >> a >> >> valid function, so using that could break code. >> >> >> >> >> >> >> >> thehans wrote >> >> > No I haven't added any mechanism to query or set undefined strings >> >> > programmatically from scripts, since I felt like that needed some >> more >> >> > thought and planning around the interface, and wanted to limit this >> PR >> >> to >> >> > only the least contentious changes. >> >> > >> >> > Adding either of those should be fairly quick and simple to >> implement >> >> > though. >> >> > >> >> > For displaying the string, i considered that echo() and str() could >> >> > possibly automatically show the undef strings if any. But this >> might >> >> end >> >> > up with more verbose messages than people would like for general >> cases. >> >> > Also as far as I know, echo() and str() generally work in such a way >> >> where >> >> > you could copy/paste output back into a script and it should be >> parsed >> >> > into >> >> > the same literal values. So doing something like that should >> >> > probably require that we first lock in how the string would be set >> >> > programmatically (see below). >> >> > Having assert() handle undef as a special case might be one good way >> to >> >> > inspect for reason strings though. >> >> > >> >> > Another possibility is that the reason string could be a "member >> >> lookup" >> >> > on >> >> > undef types, so e.g. ( some_undef_value.reason ) could return a >> string. >> >> > But then should an undef without any string return undef for that as >> >> > well?(its undefs all the way down!) >> >> > And would ".reason" on a non-undef type also be undef, or throw an >> >> actual >> >> > error? >> >> > >> >> > For setting the string, I don't think calling undef() like a >> function >> >> is >> >> a >> >> > good idea, since we don't want to mix up the default literal "undef" >> >> > identifier with a new builtin function(constructor basically) >> >> identifier >> >> > of >> >> > the same name. But perhaps a function named undefined() would be >> fine, >> >> > for >> >> > example. >> >> > >> >> > >> >> > >> >> > >> >> > On Fri, Jul 31, 2020 at 5:36 AM adrianv &lt; >> >> >> >> > avm4@ >> >> >> >> > &gt; wrote: >> >> > >> >> >> Another question: is there a way to create an undef and associate >> a >> >> >> reason, >> >> >> so for example >> >> >> >> >> >> undef("line_intersection: lines did not intersect") >> >> >> >> >> >> >> >> >> >> >> >> JordanBrown wrote >> >> >> > On 7/30/2020 9:24 PM, Hans L wrote: >> >> >> >> I've now implemented the capability for undef types to carry a >> >> reason >> >> >> >> string. >> >> >> > >> >> >> > Cool. >> >> >> > >> >> >> > So if your program has an undef in its hands, is there a >> >> >> straightforward >> >> >> > way to say "what is the reason for this undef"? >> >> >> > >> >> >> > I don't know whether it's necessary to have a way to _retrieve_ >> the >> >> >> > reason, or just a way to say "hey, I don't want an undef, this is >> an >> >> >> > error, report the error with the reason for the undef". >> >> >> > >> >> >> > One really simple mechanism might be to have assert(undef) report >> >> the >> >> >> > reason for the undef. >> >> >> > >> >> >> > That would be an exception to the general rule that undef is OK >> in >> a >> >> >> > boolean context, but then again undef is false in a boolean >> context >> >> and >> >> >> > assert(false) is an error, so it's not stretching the rule very >> >> much. >> >> >> > >> >> >> > >> >> >> > _______________________________________________ >> >> >> > OpenSCAD mailing list >> >> >> >> >> >> > Discuss@.openscad >> >> >> >> >> >> > >> >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> -- >> >> >> Sent from: http://forum.openscad.org/ >> >> >> >> >> >> _______________________________________________ >> >> >> OpenSCAD mailing list >> >> >> >> >> >> >> > Discuss@.openscad >> >> >> >> >> >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> >> >> > >> >> > _______________________________________________ >> >> > OpenSCAD mailing list >> >> >> >> > Discuss@.openscad >> >> >> >> > >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> >> >> >> >> >> >> >> >> >> -- >> >> Sent from: http://forum.openscad.org/ >> >> >> >> _______________________________________________ >> >> OpenSCAD mailing list >> >> >> >> > Discuss@.openscad >> >> >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> > >> > _______________________________________________ >> > OpenSCAD mailing list >> >> > Discuss@.openscad >> >> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> >> >> >> -- >> Sent from: http://forum.openscad.org/ >> >> _______________________________________________ >> OpenSCAD mailing list >> > Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
DM
Doug Moen
Sat, Aug 1, 2020 3:41 AM

On Fri, Jul 31, 2020, at 8:51 PM, adrianv wrote:

So you're saying that

foo=sin;

creates a function literal but

sin=12;
foo=sin;

creates a number?  Or maybe I misunderstand.  Do other people think this is
a good idea?

If you are coming to OpenSCAD after having first learned another programming language,
like Javascript or Python, then the above is exactly what you would expect.

The 'sin' function is a system wide global, from the outermost scope.
A variable definition like
sin=12;
creates a more local variable at the file or module scope.
And now after
foo=sin;
you would naturally expect that the new variable 'foo' contains the value
of the local variable 'sin'.

Try both of these in Python, and that's the behaviour you get.

As for how it could be implemented, I wrote a proposal for this a few years ago:
https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md

With the addition of function literals, named functions can be in either the
variable namespace or the function namespace. In the above proposal, built in
functions like 'sin' are defined in both the function and the variable namespace.
So there is a builtin variable called 'sin'.

So the statement
foo = sin;
defines 'foo' in terms of the sin variable.

This breaks OpenSCAD's general system of having different
namespaces for variables and functions.  Given that variables and functions
have their own namespace I should be able to introduce a "sin" variable
without changing how my code interacts with the function namespace.

Well, you can also say that the introduction of function literals "breaks"
OpenSCAD's system of segregating functions and variables into different namespaces,
because now you are free to adopt a coding style where all user defined functions
are in the variable namespace. The proposal I wrote was intended to make this new
coding style more comfortable, without breaking backward compatibility with
existing scripts. This "new" coding style is the way people expect to code if they
have prior exposure to another programming language.

Also, it should be possible to do the same thing with a user defined
function, that is, I should be able to have a library define

function cosh(x) =(exp(x)+exp(-x))/2;

then then I should be able to set

foo = cosh

in the same way that I could set

foo = cos,

converting a defined function (whether builtin or not) into a function
literal.  There shouldn't be a different syntax required for non built-ins
than for built-ins.  A library should be able to define cosh and a user not
have to know that it is not a built-in.

In the original proposal, if the library uses the new function definition syntax:
cosh(x) = (exp(x) + exp(-x)) / 2;
(omitting the 'function' keyword), then the function 'cosh' is defined
in both the function and variable namespace, and everything works the
way you said.

However, if the library uses the old function definition syntax,
then the function will only be defined in the function namespace,
as seems required for backward compatibility.

More generally, even without the details of my proposal, it's the case that
once function literals are in the language, it is no longer guaranteed that
libraries will define functions only in the function namespace.

On Fri, Jul 31, 2020, at 8:51 PM, adrianv wrote: > So you're saying that > > foo=sin; > > creates a function literal but > > sin=12; > foo=sin; > > creates a number? Or maybe I misunderstand. Do other people think this is > a good idea? If you are coming to OpenSCAD after having first learned another programming language, like Javascript or Python, then the above is exactly what you would expect. The 'sin' function is a system wide global, from the outermost scope. A variable definition like sin=12; creates a more local variable at the file or module scope. And now after foo=sin; you would naturally expect that the new variable 'foo' contains the value of the local variable 'sin'. Try both of these in Python, and that's the behaviour you get. As for how it could be implemented, I wrote a proposal for this a few years ago: https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md With the addition of function literals, named functions can be in either the variable namespace or the function namespace. In the above proposal, built in functions like 'sin' are defined in both the function and the variable namespace. So there is a builtin *variable* called 'sin'. So the statement foo = sin; defines 'foo' in terms of the sin *variable*. > This breaks OpenSCAD's general system of having different > namespaces for variables and functions. Given that variables and functions > have their own namespace I should be able to introduce a "sin" variable > without changing how my code interacts with the function namespace. Well, you can also say that the introduction of function literals "breaks" OpenSCAD's system of segregating functions and variables into different namespaces, because now you are free to adopt a coding style where all user defined functions are in the variable namespace. The proposal I wrote was intended to make this new coding style more comfortable, without breaking backward compatibility with existing scripts. This "new" coding style is the way people expect to code if they have prior exposure to another programming language. > Also, it should be possible to do the same thing with a user defined > function, that is, I should be able to have a library define > > function cosh(x) =(exp(x)+exp(-x))/2; > > then then I should be able to set > > foo = cosh > > in the same way that I could set > > foo = cos, > > converting a defined function (whether builtin or not) into a function > literal. There shouldn't be a different syntax required for non built-ins > than for built-ins. A library should be able to define cosh and a user not > have to know that it is not a built-in. In the original proposal, if the library uses the new function definition syntax: cosh(x) = (exp(x) + exp(-x)) / 2; (omitting the 'function' keyword), then the function 'cosh' is defined in both the function and variable namespace, and everything works the way you said. However, if the library uses the old function definition syntax, then the function will only be defined in the function namespace, as seems required for backward compatibility. More generally, even without the details of my proposal, it's the case that once function literals are in the language, it is no longer guaranteed that libraries will define functions only in the function namespace.
A
adrianv
Sat, Aug 1, 2020 4:25 AM

doug.moen wrote

On Fri, Jul 31, 2020, at 8:51 PM, adrianv wrote:

So you're saying that

foo=sin;

creates a function literal but

sin=12;
foo=sin;

creates a number?  Or maybe I misunderstand.  Do other people think this
is
a good idea?

If you are coming to OpenSCAD after having first learned another
programming language,
like Javascript or Python, then the above is exactly what you would
expect.

The 'sin' function is a system wide global, from the outermost scope.
A variable definition like
sin=12;
creates a more local variable at the file or module scope.
And now after
foo=sin;
you would naturally expect that the new variable 'foo' contains the value
of the local variable 'sin'.

Try both of these in Python, and that's the behaviour you get.

It's also the behavior in OpenSCAD, is it not?  The only thing that's weird
about OpenSCAD in this regard is that variables and functions have separate
namespaces.

With the addition of function literals, named functions can be in either
the
variable namespace or the function namespace. In the above proposal, built
in
functions like 'sin' are defined in both the function and the variable
namespace.
So there is a builtin variable called 'sin'.

So the statement
foo = sin;
defines 'foo' in terms of the sin variable.

Given the obsession with backwards compatibility  I assumed a backwards
compatible approach that matched up with how things generally work in
OpenSCAD.  But I can see that I hadn't thought this through carefully.

When I first read the proposal my immediate reaction was that it would more
or less require me to define all my functions in the new style because
otherwise there's a lack of flexibility.  That seemed odd.  And of course it
might break code if I have variables that share a name with a function.
But it sounds like you're saying that was actually the intent, that people
might switch to the new style, and work with a single name space for
functions and variables.

This breaks OpenSCAD's general system of having different
namespaces for variables and functions.  Given that variables and
functions
have their own namespace I should be able to introduce a "sin" variable
without changing how my code interacts with the function namespace.

Well, you can also say that the introduction of function literals "breaks"
OpenSCAD's system of segregating functions and variables into different
namespaces,
because now you are free to adopt a coding style where all user defined
functions
are in the variable namespace. The proposal I wrote was intended to make
this new
coding style more comfortable, without breaking backward compatibility
with
existing scripts. This "new" coding style is the way people expect to code
if they
have prior exposure to another programming language.

However, if the library uses the old function definition syntax,
then the function will only be defined in the function namespace,
as seems required for backward compatibility.

More generally, even without the details of my proposal, it's the case
that
once function literals are in the language, it is no longer guaranteed
that
libraries will define functions only in the function namespace.

For libraries to define things in the variable namespace they have to be
included instead of used.  Also libraries that are used can't define any
variables because this leads to performance issues.  So it's a little
unclear what might happen with libraries written to use function literals.

I hadn't thought about it being "no longer guaranteed that libraries will
define functions only in the function namespace" but it's certainly true.
So the introduction of function literals represents a more fundamental
change than I realized.

Are there plans to provide a way to check the arguments that a function
requires?  That is, if I write a function that takes as an argument a
function of two variables, can I somehow check that the function I've been
given accepts two variables?

Are there plans to merge the module and variable namespace as well?  Because
the library I work on has tons of function/modules where the function form
returns something and the module form makes the corresponding geometry.

Anyways, with your clarification the problem with my undef functional form
proposal is clear.  But it seems better to have a language structure than a
magic function with an inconsistent name that constructs the undef with its
descriptive string.  I'm not sure what that might look like, though.  Or
the concerns about introducing new syntax.

--
Sent from: http://forum.openscad.org/

doug.moen wrote > On Fri, Jul 31, 2020, at 8:51 PM, adrianv wrote: >> So you're saying that >> >> foo=sin; >> >> creates a function literal but >> >> sin=12; >> foo=sin; >> >> creates a number? Or maybe I misunderstand. Do other people think this >> is >> a good idea? > > If you are coming to OpenSCAD after having first learned another > programming language, > like Javascript or Python, then the above is exactly what you would > expect. > > The 'sin' function is a system wide global, from the outermost scope. > A variable definition like > sin=12; > creates a more local variable at the file or module scope. > And now after > foo=sin; > you would naturally expect that the new variable 'foo' contains the value > of the local variable 'sin'. > > Try both of these in Python, and that's the behaviour you get. It's also the behavior in OpenSCAD, is it not? The only thing that's weird about OpenSCAD in this regard is that variables and functions have separate namespaces. > With the addition of function literals, named functions can be in either > the > variable namespace or the function namespace. In the above proposal, built > in > functions like 'sin' are defined in both the function and the variable > namespace. > So there is a builtin *variable* called 'sin'. > > So the statement > foo = sin; > defines 'foo' in terms of the sin *variable*. Given the obsession with backwards compatibility I assumed a backwards compatible approach that matched up with how things generally work in OpenSCAD. But I can see that I hadn't thought this through carefully. When I first read the proposal my immediate reaction was that it would more or less require me to define all my functions in the new style because otherwise there's a lack of flexibility. That seemed odd. And of course it might break code if I have variables that share a name with a function. But it sounds like you're saying that was actually the intent, that people might switch to the new style, and work with a single name space for functions and variables. >> This breaks OpenSCAD's general system of having different >> namespaces for variables and functions. Given that variables and >> functions >> have their own namespace I should be able to introduce a "sin" variable >> without changing how my code interacts with the function namespace. > > Well, you can also say that the introduction of function literals "breaks" > OpenSCAD's system of segregating functions and variables into different > namespaces, > because now you are free to adopt a coding style where all user defined > functions > are in the variable namespace. The proposal I wrote was intended to make > this new > coding style more comfortable, without breaking backward compatibility > with > existing scripts. This "new" coding style is the way people expect to code > if they > have prior exposure to another programming language. > > However, if the library uses the old function definition syntax, > then the function will only be defined in the function namespace, > as seems required for backward compatibility. > > More generally, even without the details of my proposal, it's the case > that > once function literals are in the language, it is no longer guaranteed > that > libraries will define functions only in the function namespace. For libraries to define things in the variable namespace they have to be included instead of used. Also libraries that are used can't define any variables because this leads to performance issues. So it's a little unclear what might happen with libraries written to use function literals. I hadn't thought about it being "no longer guaranteed that libraries will define functions only in the function namespace" but it's certainly true. So the introduction of function literals represents a more fundamental change than I realized. Are there plans to provide a way to check the arguments that a function requires? That is, if I write a function that takes as an argument a function of two variables, can I somehow check that the function I've been given accepts two variables? Are there plans to merge the module and variable namespace as well? Because the library I work on has tons of function/modules where the function form returns something and the module form makes the corresponding geometry. Anyways, with your clarification the problem with my undef functional form proposal is clear. But it seems better to have a language structure than a magic function with an inconsistent name that constructs the undef with its descriptive string. I'm not sure what that might look like, though. Or the concerns about introducing new syntax. -- Sent from: http://forum.openscad.org/