Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request to support Spread Syntax or Spread Operator #3524

Open
EricRohlfs opened this issue Dec 9, 2020 · 8 comments
Open

Request to support Spread Syntax or Spread Operator #3524

EricRohlfs opened this issue Dec 9, 2020 · 8 comments

Comments

@EricRohlfs
Copy link

EricRohlfs commented Dec 9, 2020

Adding spread syntax would be a big help when building parametric models.

cup_size = [10,10,10];
cylinder(...cup_size, false); // spread syntax
cylinder(cup_size[0], cup_size[1], cup_size[2], false); // non-spread syntax

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

// just variables/functions for parametric development, nothing interesting here
function subtract(my_number, by) = my_number - by; 
cup_size = [10,10,10];
cup_thickness = 1;
nudge = 0.001;

//use case - without spread syntax
difference(){
    cylinder(cup_size[0], cup_size[1], cup_size[2], false);
    inner = [for(x= cup_size) subtract(x, cup_thickness)];
    translate([0,0,cup_thickness + nudge]){
        cylinder(inner[0], inner[1], inner[2], false);
    }
}
// use case - with spread syntax
difference(){
    cylinder(...cup_size, false);
    inner = [for(x= cup_size) subtract(x, cup_thickness)];
    translate([0,0,cup_thickness + nudge]){
        cylinder(...inner), false);
    }
}

With spread syntax it is easier to read and to write. Less of a bug magnet too.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@nophead
Copy link
Member

nophead commented Dec 9, 2020

I don't see how subtract would work. Doesn't it get four arguments when it expects 2?

@EricRohlfs
Copy link
Author

I don't see how subtract would work. Doesn't it get four arguments when it expects 2?

Your are correct, My example was not right. I've updated it to use a loop to calculate the new inner dimensions.
Less impressive, but would still be a nice feature.

@thehans
Copy link
Member

thehans commented Jan 11, 2021

In list comprehensions we have the each keyword which acts a bit like this, so it might make sense to just expand that to apply within function/module argument lists.

@jordanbrown0
Copy link
Contributor

Complimentary to this would be a way to get the current module/function's argument list as an array, so (with a hypothetical function args() that returns the arguments as an array) that you could say

    module mycube(size, center) {
        cube(...args());
    }

Named args throw a wrench into this picture. You want a way to have a module like that, that works even if invoked as mycube(center=true, size=10). One could imagine a spread syntax variant that would accept an array of [name, value] pairs, and maybe args() generates that structure.

Anyhow, just some things to think about.

@jordanbrown0
Copy link
Contributor

Named arguments might map well to objects, ref PR#4478.

@paul-lalonde
Copy link

My current model of parameter passing is that all parameter passing is named, with some sugar to allow omission of names for the leading parameters of a function/module call.

That implies that any args() mechanism returns a dictionary. That dictionary itself should be limited to variables actually set, so that undef can be differentiated from unset. Implementation of a dictionary in the language is orthogonal; the array of [name, value] pairs is minimally invasive and coud be sugared if needed.

My use case from #4478 is satisfied by your proposed ...args() above.

I don't think I'm saying anything new or original. I'm looking for a place to start in the code base that won't waste people's time with ill-thought-out contribution efforts ;-)

@jordanbrown0
Copy link
Contributor

When you say "dictionary", I hear what #4478 calls "object"; I've been programming in JavaScript rather than Python. Terminology is one of the open issues there. (But let's discuss that terminology over there.)

Yes, I think that a name-value mechanism, whether you call it dictionaries, objects, associative arrays, or whatever, is probably the right answer to varargs for named arguments. Combining that with an array-based scheme for positional arguments covers most of the bases.

In theory you can mix them arbitrarily. I don't know how much order matters. But maybe that's weird enough that we should discourage it.

And yes, I tend to use mostly named arguments with a few special cases where the first argument or two are "primary" and positional. The simplest example is that I would say cube(10, center=true). I would never put a name on the first argument, and I would never not put a name on the center argument.

@jordanbrown0
Copy link
Contributor

Hmm. Since every argument does have a name, the arguments-as-object mechanism could represent all argument lists.

But: one of the things you'd like to be able to do is to handle arbitrary argument lists, without names - e.g., have a function add(a,b,c,d,e,f,...) that could add up all of its arguments. (Stupid example, but I hope the idea makes sense.)

But but: you can always wrap them in brackets and pass an array.

And builtins have more control; you can say echo(x=1, x=2) and it works. I don't know if we want to try to extend that ability to OpenSCAD-language functions/modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants