"Ignoring unknown variable" issue...

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

"Ignoring unknown variable" issue...

Amedee
All,

I am running into an weird issue in a small project with include files, where I want to override variables defined in the includes...

I eventually made a very simple testcase to illustrate what is happening, it turns out it is linked to the sequence variables are first defined.

Here is my test case:

Testcase 1:
     a = 1;
     b = 2;

     b = a;  // Works, b gets 1
     echo(a,b);

This works as well and prints
ECHO: 1, 1

Testcase 2:
     a = 1;
     b = 2;

     a = b;  // Problem: WARNING: Ignoring unknown variable 'b'.
               // a gets undef
     echo(a,b)

This will generate a warning and print:
WARNING: Ignoring unknown variable 'b'.
ECHO: undef, 2

I understand that a variable in OpenSCAD is a compile time thing and does not change at runtime, but I would have expected that the parser would know the 'last' value/state of all variables before resolving the dependencies...

Any comment / explanation on the above behavior?
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

nophead
The explanation is OpenScad uses the last value assigned all the way through the script because a variable only ever has one value. So a=1 gets replaced by a= b but b isn't defined at that point.

On 15 July 2015 at 10:07, Amedee <[hidden email]> wrote:
All,

I am running into an weird issue in a small project with include files,
where I want to override variables defined in the includes...

I eventually made a very simple testcase to illustrate what is happening, it
turns out it is linked to the sequence variables are first defined.

Here is my test case:

Testcase 1:
     a = 1;
     b = 2;

     b = a;  // Works, b gets 1
     echo(a,b);

This works as well and prints
ECHO: 1, 1

Testcase 2:
     a = 1;
     b = 2;

     a = b;  // Problem: WARNING: Ignoring unknown variable 'b'.
               // a gets undef
     echo(a,b)

This will generate a warning and print:
WARNING: Ignoring unknown variable 'b'.
ECHO: undef, 2

I understand that a variable in OpenSCAD is a compile time thing and does
not change at runtime, but I would have expected that the parser would know
the 'last' value/state of all variables before resolving the dependencies...

Any comment / explanation on the above behavior?



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Amedee
nophead wrote
The explanation is OpenScad uses the last value assigned all the way
through the script because a variable only ever has one value.
Yes, I understand that

nophead wrote
So a=1 gets replaced by a= b but b isn't defined at that point.
I see as well what is happening here, but it is a bit in opposition with the first part where we say  "OpenScad uses the last value assigned all the way through"

I appreciate compiler and dependencies are complex things, but at the time we resolve a=b  we should already know b is defined (and has no dependencies)...
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

nophead
Perhaps it is more correct to say the "variables" (actually named constants) only have one value throughout their lexical scope and that is the value assigned last. Yes the compiler could work out the value of b but the point is it isn't in scope at the first point a is defined, so using it breaks the scope rules.

It isn't my design, I am just describing what it does.



On 15 July 2015 at 11:32, Amedee <[hidden email]> wrote:
nophead wrote
> The explanation is OpenScad uses the last value assigned all the way
> through the script because a variable only ever has one value.

Yes, I understand that


nophead wrote
> So a=1 gets replaced by a= b but b isn't defined at that point.

I see as well what is happening here, but it is a bit in opposition with the
first part where we say  "OpenScad uses the last value assigned all the way
through"

I appreciate compiler and dependencies are complex things, but at the time
we resolve a=b  we should already know b is defined (and has no
dependencies)...



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13159.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

jon_bondy
That is QUITE a different description than the one that is usually offered.  And much more  helpful.  Thank you very much!

On 7/15/2015 7:13 AM, nop head wrote:
Perhaps it is more correct to say the "variables" (actually named constants) only have one value throughout their lexical scope and that is the value assigned last. Yes the compiler could work out the value of b but the point is it isn't in scope at the first point a is defined, so using it breaks the scope rules.

It isn't my design, I am just describing what it does.



On 15 July 2015 at 11:32, Amedee <[hidden email]> wrote:
nophead wrote
> The explanation is OpenScad uses the last value assigned all the way
> through the script because a variable only ever has one value.

Yes, I understand that


nophead wrote
> So a=1 gets replaced by a= b but b isn't defined at that point.

I see as well what is happening here, but it is a bit in opposition with the
first part where we say  "OpenScad uses the last value assigned all the way
through"

I appreciate compiler and dependencies are complex things, but at the time
we resolve a=b  we should already know b is defined (and has no
dependencies)...



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13159.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


No virus found in this message.
Checked by AVG - www.avg.com
Version: 2015.0.6081 / Virus Database: 4392/10231 - Release Date: 07/14/15



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Neon22
In reply to this post by nophead
FWIW I get around this problem by making a new variable and assigning the right value to it in the scope where I need it.
I.e. don't reuse variables as assignments don't work like programming languages.
For me the mental trick is to realise you are writing something that - when evaluated - describes a scene. It just happens to look like a program.
Its like "for" loops. Each one creates an object (probably), if you try to assign an object to a variable in a loop - its not going to do that.


On 7/15/2015 11:13 PM, nop head wrote:
Perhaps it is more correct to say the "variables" (actually named constants) only have one value throughout their lexical scope and that is the value assigned last. Yes the compiler could work out the value of b but the point is it isn't in scope at the first point a is defined, so using it breaks the scope rules.

It isn't my design, I am just describing what it does.



On 15 July 2015 at 11:32, Amedee <[hidden email]> wrote:
nophead wrote
> The explanation is OpenScad uses the last value assigned all the way
> through the script because a variable only ever has one value.

Yes, I understand that


nophead wrote
> So a=1 gets replaced by a= b but b isn't defined at that point.

I see as well what is happening here, but it is a bit in opposition with the
first part where we say  "OpenScad uses the last value assigned all the way
through"

I appreciate compiler and dependencies are complex things, but at the time
we resolve a=b  we should already know b is defined (and has no
dependencies)...



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13159.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


No virus found in this message.
Checked by AVG - www.avg.com
Version: 2015.0.6081 / Virus Database: 4392/10233 - Release Date: 07/15/15



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Amedee
nophead wrote
It isn't my design, I am just describing what it does.
Yes, thank you for clarifying the process

Neon22 wrote
FWIW I get around this problem by making a new variable and
    assigning the right value to it in the scope where I need it.
    I.e. don't reuse variables as assignments don't work like
    programming languages.
Functional languages require a mental switch ;)

Just as background info, this is what brought me to this issue: I have separated parts of my little project into several include files, so that I could work on these parts separately with smaller files.
In each file I typically never have raw numbers in the modules, I only use 'variables' defined at the top of these files, so it is fully parametric.

For a full assembly, I have a 'main' file which includes all the 'part' files and call the different modules.
When I want to 'customize' the model, I assign new values to the variables in the 'main' file; that way I don't touch the parts, and it works well due to the way variables are working in OpenSCAD (Last value overrides).

What putted me in trouble was that I wanted to have a variable from file A derived from a variable from file B. Sometimes it worked, and sometimes not, depending on the include order -- which is the issue I described here.

Now I appreciate that a better solution would be to use module parameters with default values, but I didn't wanted to end up with modules having a huge list of parameters (maybe I should...)
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

nophead
The way to avoid long parameter lists is to represent properties of an object with a named list and just pass that. For example I have M3_cap_screw, etc, and pass that along with its length to module screw(), which draws it and functions like screw_clearance_radius().

On 15 July 2015 at 13:50, Amedee <[hidden email]> wrote:
nophead wrote
> It isn't my design, I am just describing what it does.

Yes, thank you for clarifying the process


Neon22 wrote
> FWIW I get around this problem by making a new variable and
>     assigning the right value to it in the scope where I need it.
>     I.e. don't reuse variables as assignments don't work like
>     programming languages.

Functional languages require a mental switch ;)

Just as background info, this is what brought me to this issue: I have
separated parts of my little project into several include files, so that I
could work on these parts separately with smaller files.
In each file I typically never have raw numbers in the modules, I only use
'variables' defined at the top of these files, so it is fully parametric.

For a full assembly, I have a 'main' file which includes all the 'part'
files and call the different modules.
When I want to 'customize' the model, I assign new values to the variables
in the 'main' file; that way I don't touch the parts, and it works well due
to the way variables are working in OpenSCAD (Last value overrides).

What putted me in trouble was that I wanted to have a variable from file A
derived from a variable from file B. Sometimes it worked, and sometimes not,
depending on the include order -- which is the issue I described here.

Now I appreciate that a better solution would be to use module parameters
with default values, but I didn't wanted to end up with modules having a
huge list of parameters (maybe I should...)



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13163.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Neon22
Can you point to an example of this style please.
I have tried to use named lists but gave up trying to work out how to get the values out again.
So I've tended towards the module with named arguments approach.

On 7/16/2015 12:58 AM, nop head wrote:
The way to avoid long parameter lists is to represent properties of an object with a named list and just pass that. For example I have M3_cap_screw, etc, and pass that along with its length to module screw(), which draws it and functions like screw_clearance_radius().

On 15 July 2015 at 13:50, Amedee <[hidden email]> wrote:
nophead wrote
> It isn't my design, I am just describing what it does.

Yes, thank you for clarifying the process


Neon22 wrote
> FWIW I get around this problem by making a new variable and
>     assigning the right value to it in the scope where I need it.
>     I.e. don't reuse variables as assignments don't work like
>     programming languages.

Functional languages require a mental switch ;)

Just as background info, this is what brought me to this issue: I have
separated parts of my little project into several include files, so that I
could work on these parts separately with smaller files.
In each file I typically never have raw numbers in the modules, I only use
'variables' defined at the top of these files, so it is fully parametric.

For a full assembly, I have a 'main' file which includes all the 'part'
files and call the different modules.
When I want to 'customize' the model, I assign new values to the variables
in the 'main' file; that way I don't touch the parts, and it works well due
to the way variables are working in OpenSCAD (Last value overrides).

What putted me in trouble was that I wanted to have a variable from file A
derived from a variable from file B. Sometimes it worked, and sometimes not,
depending on the include order -- which is the issue I described here.

Now I appreciate that a better solution would be to use module parameters
with default values, but I didn't wanted to end up with modules having a
huge list of parameters (maybe I should...)



--
View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13163.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


No virus found in this message.
Checked by AVG - www.avg.com
Version: 2015.0.6081 / Virus Database: 4392/10233 - Release Date: 07/15/15



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

runsun
In reply to this post by Neon22
Neon22 wrote
FWIW I get around this problem by making a new variable and
    assigning the right value to it in the scope where I need it.
I use the hash parameter model (see my signature) and just
update the value whenever I want, so I hardly encounter this issue.

Another benefit of the hash parameter model is that you will be able
to pack similar or related parameters in one junk so the name space
won't be packed with tons of vars.
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Neon22
wow that's really clever. But maybe in openSCAD2 we should try to make it siompler like have dictionaries - e.g. Python dictionaries, or LISP like association lists.
E.g. stuff = {"name1" : 10, "name2" : 20, "name3" : [12,22]}
and stuff["name1"] returns 10.

The loss of assign has helped to make the code more readable.
and we have mandatory and optional and keyword arguments to modules which is great.
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Amedee
Actually with the latest version of OpenSCAD we have a couple of interesting features which make possible to emulate associative arrays (or dictionaries) easily...

A simple example script:

// Associative arrays...

default_values = [
  ["a", 10],
  ["b", 20],
  ["bb", 100]
  ];

parameters = [
  ["bb", 200]
  ];

// Get value from associative array
function ar_get(ar, key) =
  let(idx = search([key],ar)[0])
    ar[idx][1];
 
// Merge 2 arrays (values from ar2 overrides ar1)
function ar_merge(ar1, ar2) = [ for (elem = ar1)
  let(idx = search([elem[0]],ar2)[0])
    [elem[0], idx != [] ? ar2[idx][1] : elem[1]]
  ];

// Example:
echo ("Default bb is:", ar_get(default_values, "bb"));

merged_values = ar_merge(default_values, parameters);  
echo ("Actual bb is:", ar_get(merged_values, "bb"));
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

runsun
Amedee wrote
Actually with the latest version of OpenSCAD we have a couple of interesting features which make possible to emulate associative arrays (or dictionaries) easily...

A simple example script:

// Associative arrays...

default_values = [
  ["a", 10],
  ["b", 20],
  ["bb", 100]
  ];
Indeed. We had a discussion about this here. it was when the change made.

However, it requires array of [key,val]s,  means to type in lots of [ ], which is I try to avoid. So in my hash parameter model, I use a flat array like [  "a", 10,  "b", 20,  "bb", 100  ].

In fact, it doesn't need latest version of OpenSCAD to come up with several user function for array of [key,val]'s to work like an associate array.

But it's just my personal taste. Your code does solve the problem and would probably run faster than mine.

Btw, if your keys are all numerical, you can simply use lookup:

 function get_cylinder_h(p) = lookup(p, [
  [ -200, 5 ],
  [ -50, 20 ],
  [ -20, 18 ],
  [ +80, 25 ],
  [ +150, 2 ]
  ]);
 
 for (i = [-100:5:+100]) {
  // echo(i, get_cylinder_h(i));
  translate([ i, 0, -30 ]) cylinder(r1 = 6, r2 = 2, h = get_cylinder_h(i)*3);
 }
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Neon22
when using Search I had all kinds of problems in that these two will match:
     "grip", "grip-2" when searching for "grip". I.e same for any
substring that starts the same.

Also lookup does interp if there is no match. I wasn't sure I could
count on it for lookups if my field wasn't in the list - but I didn't
extensively test it.


On 7/16/2015 6:44 AM, runsun wrote:

> Amedee wrote
>> Actually with the latest version of OpenSCAD we have a couple of
>> interesting features which make possible to emulate associative arrays (or
>> dictionaries) easily...
>>
>> A simple example script:
>>
>> // Associative arrays...
>>
>> default_values = [
>>    ["a", 10],
>>    ["b", 20],
>>    ["bb", 100]
>>    ];
> Indeed. We had a discussion about this  here
> <http://forum.openscad.org/Digging-into-search-td12421.html>  . it was when
> the change made.
>
> However, it requires array of [key,val]s,  means to type in lots of [ ],
> which is I try to avoid. So in my hash parameter model, I use a flat array
> like [  "a", 10,  "b", 20,  "bb", 100  ].
>
> In fact, it doesn't need latest version of OpenSCAD to come up with several
> user function for array of [key,val]'s to work like an associate array.
>
> But it's just my personal taste. Your code does solve the problem and would
> probably run faster than mine.
>
> Btw, if your keys are all numerical, you can simply use lookup:
>
>
>>   function get_cylinder_h(p) = lookup(p, [
>>   [ -200, 5 ],
>>   [ -50, 20 ],
>>   [ -20, 18 ],
>>   [ +80, 25 ],
>>   [ +150, 2 ]
>>   ]);
>>  
>>   for (i = [-100:5:+100]) {
>>   // echo(i, get_cylinder_h(i));
>>   translate([ i, 0, -30 ]) cylinder(r1 = 6, r2 = 2, h =
>> get_cylinder_h(i)*3);
>>   }
>
>
>
>
> -----
>
> $  Runsun Pan, PhD
>
> $ -- OpenScad_DocTest ( Thingiverse ), faces , Offliner
>
> $ -- hash parameter model: here , here
>
> $ -- Linux Mint 17.1 Rebecca x64  + OpenSCAD 2015.03.15/2015.04.01.nightly
>
>
>
>
> --
> View this message in context: http://forum.openscad.org/Ignoring-unknown-variable-issue-tp13156p13175.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
> -----
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2015.0.6081 / Virus Database: 4392/10233 - Release Date: 07/15/15
>
>


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Amedee
Neon22 wrote
when using Search I had all kinds of problems in that these two will match:
     "grip", "grip-2" when searching for "grip". I.e same for any
substring that starts the same.
You probably had the 'wrong' syntax...

The documentation wrote
Note: If match_value is a vector of strings, search will look for exact string matches.
So you need to search for ["grip"], not just "grip"
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

QuackingPlums
In reply to this post by Neon22
Hmm. If I'm reading that hash table approach correctly then isn't it open to 'undefs' in my code if I mistype the hash key? This seems to apply to both the hash table definition and anywhere I want to lookup hash values in my code.

The method I use explicitly defines the properties of my 'object', which means I get the benefits of the compiler telling me if I've tried to access a non-existent property:

--- code ---
stuff1 = [10, 2, "red"];
stuff2 = [20, 5, "blue"];

function stuff_length(stuff) = stuff[0];
function stuff_width(stuff) = stuff[1];
function stuff_colour(stuff) = stuff[2];

example(stuff1);
module example(myStuff)
{
    echo( stuff_length(myStuff) );
    echo( stuff_width(myStuff) );
    echo( stuff_color(myStuff) );    <--- fails with a warning in the compiler window as "stuff_color()" is undefined
}
--- /code ---

The drawback is having to maintain the ordered list but I don't see that being any more onerous than maintaining the keys for every list with the hash table approach - the order of the parameters in the list doesn't actually matter (unless you suffer from tidy code OCD like I do!) as we are abstracting via "property accessors".

Another benefit to using this approach is that you can have derived properties that are based on calculations of the explicit ones:

function stuff_area(stuff) = stuff_length(stuff) * stuff_width(stuff);




Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Amedee
I think both methods have also different use cases...

The 'property array' is nice when you have a whole set of objects with different attributes (like all screw types, bearings, ...)

The hashes are more convenient when you have a base object with (a lot of) default properties and you want to instantiate it with just a couple of changes: you don't have to define the complete array, just the amended key/value.
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

QuackingPlums
In that scenario I'd use a 'constructor' for my object with default parameters

function new_stuff(length = 10, width = 2, colour = "yellow")
    = [length, width, colour];

myNewPartialObject = new_stuff(width = 15);

I can see how this can start becoming difficult to maintain though if those definitions change regularly. I do remember reading the hashtable approach and thinking that it would be useful for certain cases - I just haven't hit a scenario yet where I have felt the need to refactor.
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

Neon22
This is all great info. Thanks for it.
I'd like to ask an open question though (because OpenSCAD2 is being designed).

What do you think woudl be the 'best' way to make this work in OpenSCAD2 ?
Should we add a new accessing method, or type or way of doing this so we don't need to create special code to do it ?

What aspects of the work arounds are the valuable ones ?
Reply | Threaded
Open this post in threaded view
|

Re: "Ignoring unknown variable" issue...

runsun
In reply to this post by QuackingPlums
QuackingPlums wrote
The method I use explicitly defines the properties of my 'object', which means I get the benefits of the compiler telling me if I've tried to access a non-existent property:
My current version of the hash looks like this:

    function hash( h,k, default )= 
    (
        let( ret = [ for(i=[0:2:len(h)-2])
                        if( h[i]==k ) h[i+1] ][0]
           )
        ret==undef? default: ret
    );

It covers the cases of undef:

    h = ["a",2,"b",3];
    hash( h, "c" ) ==> undef
    hash( h, "c", 4) ==> 4

which can be made to give up a warning:

    function hash( h,k, default= "<b style='color:red'>WARNING: key not found !</b>"   )= 
      ...

I have a code to do the string substitution:

    _s( "Warning: key {_} not found !!", "c") ==> "Warning: key c not found !!"

So it is possible to make it behave exactly like the compiler warning you talk about (even more, actually).

The hash would become (note: untested):

    warn = "<b style='color:red'>Warning: key {_} not found in {_} !!</b>";

    function hash( h,k, default,  warn=warn)= 
    (
       let( ret = [ for(i=[0:2:len(h)-2])
                      if( h[i]==k ) [h[i], h[i+1]] ][0]
         , k = ret[0]
         , v = red[1]
        )
      v==undef? 
          (default? default : _s(warn, [k,h] ) )
         : v
    );

    h = ["a",2,"b",3];
    hash( h, "c" ) ==> Warning: key c not found in ["a",2,"b",3] !!
    hash( h, "c", 4) ==> 4


$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
12