container first{
container second{
type boolean;
}
}
how can i do something like this.(My error:i can't boolean a container/error: unexpected keyword "type") I don't want to use leaf. Is there an alternative ?
As per RFC 6020. For storing single data we have to use leaf. Using containers to store boolean data, I don't think would be possible.
As per RFC6020 section 7.5.1, Containers are used to organize the hierarchy of data nodes, and those whose presence in the configuration has an explicit meaning.It means we can't use container to store the data.
If you don't want to use boolean then you can try to use "enum" like this:
leaf myenum {
type enumeration {
enum zero {
value 0;
}
enum one {
value 1;
}
}
}
.
Suppose I have two modules, I would like to extend one list with new leafs.
module A {
list deviceList {
key name;
leaf name{
}
leaf hostname{
}
}
}
and I would like to augment it to another leaf
module B {
list generalInfo{
key customerName;
leaf customerName{
type string;
}
augment moduleA:deviceList {
leaf ipAddress{
}
}
}
I have done it using grouping and container and list inside but this completely changes our existing structure, I would like to ommit container and grouping if thats possible.
It seems that you want to reuse a part of the schema definition, put it in another place in the schema tree and add a node to it.
You cannot do it the way you tried because the augment statement can appear only on the root level or in the uses statement.
You can do that only with a grouping but you can omit the container. Refactor A: define a grouping that's a list. Refer to it in B and augment it.
module A {
grouping devices {
list deviceList {
key name;
leaf name{
}
leaf hostname{
}
}
}
uses devices;
}
module B {
list generalInfo{
key customerName;
leaf customerName{
type string;
}
uses moduleA:devices {
augment "deviceList" {
leaf ipAddress{
}
}
}
}
}
Note that if you use the augment statement in the module B then it means that any device implementing module B has to also implement module A and its root-level list deviceList. See RFC 7950 4.2.8:
When a server implements a module containing an "augment" statement,
that implies that the server's implementation of the augmented module
contains the additional nodes.
I am not sure if this is what you want. If not, then move the grouping definition to a module that contains only grouping definitions (without any "data definition statements") and import it from both A and B.
With arrays you can use a subscript to access Array Elements directly. You can read or write to them. With Sets I am not sure of a way to write its Elements.
For example, if I access a set element matching a condition I'm only able to read the element. It is passed by copy and I can't therefore write to the original.
For example:
columns.first(
where: {
$0.header.last == Character(String(i))
}
)?.cells.append(value: addValue)
// ERROR: Cannot use mutating member on immutable value: function call returns immutable value
You can't just change things inside a set, because of how a (hash) set works. Changing them would possibly change their hash value, making the set into an invalid state.
Therefore, you would have to take the thing you want to change out of the set, change it, then put it back.
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
columns.remove(thing)
thing.cells.append(value: addValue)
columns.insert(thing)
}
If the == operator on Column doesn't care about cells (i.e. adding cells to a column doesn't suddenly make two originally equal columns unequal and vice versa), then you could use update instead:
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
thing.cells.append(value: addValue)
columns.update(thing)
}
As you can see, it's quite a lot of work, so maybe sets aren't a suitable data structure to use in this situation. Have you considered using an array instead? :)
private var _columns: [Column]
public var columns : [Column] {
get { _columns }
set { _columns = Array(Set(newValue)) }
// or any other way to remove duplicate as described here: https://stackoverflow.com/questions/25738817/removing-duplicate-elements-from-an-array-in-swift
}
You are getting the error because columns might be a set of struct. So columns.first will give you an immutable value. If you were to use a class, you will get a mutable result from columns.first and your code will work as expected.
Otherwise, you will have to do as explained by #Sweeper in his answer.
I know that when I use for it creates a group of the generated children.
I created a module called grid like so:
module grid(x0,y0,dx,dy,nx,ny) {
for (x=[0:1:nx-1]) {
for(y=[0:1:ny-1]) {
i=x*nx+y;
echo(i);
translate([x0+x*dx,y0+y*dy,0]) children(i);
}
}
}
which when used like this:
grid(-50,-50,25,25,5,5) {
cube([10,10,10],center=true);
cube([10,10,10],center=true);
cube([10,10,10],center=true);
cube([10,10,10],center=true);
//.. continue to create 25 cubes total
}
arranges the cubes in a nice grid.
however my original hope and intention was to use it like this:
grid(-50,-50,25,25,5,5) {
for(i=[0:1:24]) {
cube([10,10,10],center=true);
}
}
Which fails because the for operator returns a group and not a set of children.
Why does the for add a group to begin with? (also leading to the need for intersection_for)
And is there a way for my Grid operator module to handle the children of the group?
I personally hope for the grouping/union for elements within a for() to become optional at some time.
If you don't mind compiling OpenSCAD from source, you could try it already today.
There is an ongoing issue Lazy union (aka. no implicit union)
and a patch here Make for() UNION optional
Just updated my knowledge of OpenSCAD, there is a better solution:
module nice_cube()
{
translate([0,0,$height/2]) cube([9,9,$height], center = true);
}
module nice_cylinder()
{
translate([0,0,$height/2]) cylinder(d=10,h=$height, center = true);
}
module nice_text()
{
linear_extrude(height=$height, center=false) text(str($height), size=5);
}
module nice_grid()
{
for(i=[0:9], j=[0:9])
{
$height=(i+1)*(j+1);
x=10*i;
y=10*j;
translate([x,y,0]) children();
/* let($height=(i+1)*(j+1)) {children();} */
}
}
nice_grid() nice_cube();
translate([0,-110,0]) nice_grid() nice_text();
translate([-110,0,0]) nice_grid() nice_cylinder();
The trick here is to control the shape produced by module by special variables (starting with $) those can be used like in example, commented line using let() requires development version of openscad.
I guess You want this:
for(x=[...], y=[...]) {
translate([x,y,0]) children();
}
Note, that you need only one for statement to loop through both x and y values.
What I have understood from your comment is, that you want your objects in the nodes of the grids to be parametric, and parameter depends on index. This requirement was not mentioned in the original question. In this case, solution depends on your problem context, I guess. The two possibilities I see are:
module grid_of_parametric_modules(other_param)
{
for(i=[0:24])
{
x=_x(i);
y=_y(i);
translate([x,y,0]) parametric_module(i_param(i), other_param);
}
}
However this may not be suitable, especially if You are going to add new shapes to your grid in future. Then you can probably do it like:
function grid_pos(i) = [_x(i), _y(i), 0];
....
for(i=[0:24])
translate(grid_pos(i)) parametric_module(i);
I need to match items in two different arrays (one with imported items and another with local items that share some properties with the imported items) to sync two databases that are quite different. I need to use several criteria to do the matching to increase the robustness of finding the right local item and match it with the imported item. I could check each criterium in the same loop, but that is too expensive, because the criteria are checked by the likelihood of success in descending order. Thus, in my first implementation I used a boolean flag called found to flag that the checking of other criteria should be ignored.
Using pseudo code:
// calling code for the matching
for item in importedItems {
item.match() }
In the imported item class:
match()
{
var found = false
for localItem in localItems
{
if (self.property == localItem.property)
{
// update the local item here
found = true
break
}
}
// match with less likely 2nd property
if (!found)
{
for localItem in localItems
{
if (self.property2 == localItem.property2)
{
// update the local item here
found = true
break
}
}
}
The if !found {...} pattern is repeated two additional times with even less likely criteria.
After reviewing this code, it is clear that this can be optimized by returning instead of breaking when there is a match.
So, my question is "are there any known side-effects of leaving a loop early by using return instead of break in Swift?" I could not find any definitive answer here in SO or in the Swift documentation or in blogs that discuss Swift flow control.
No, there are no side effects, quite the opposite it's more efficient.
It's like Short-circuit evaluation in a boolean expression.
But your code is a bad example because found cannot be used outside the function.
This is a more practical example returning a boolean value
func match() -> Bool
{
for localItem in localItems
{
if (self.property == localItem.property)
{
// update the local item here
return true
}
}
....
return false
}
If you know for sure that you can return because nothing else have to be done after the loop then there are no side effects of using return