Immutable class in Eiffel - immutability

I'm trying to make an immutable POINT class in Eiffel. Is the code below defines one? The {NONE} accessibility for the x and y fields is enough for it? Can I write something to the class invariant like x = x', or how else can I achieve immutability?
class POINT
create
make
feature {NONE}
x: DOUBLE
y: DOUBLE
feature
make (x_: DOUBLE; y_: DOUBLE)
do
x := x_
y := y_
ensure
set: x = x_ and y = y_
end
feature --accessors
get_x: DOUBLE
do
Result := x
ensure
Result = x
end
end

Eiffel does not allow to change attributes of a class by its clients. For example, the following code is rejected:
p: POINT
...
p.x := 5.0
As a result, there is no need to provide getters (like in some other languages). You can just use p.x provided that x is sufficiently exported to a client class. So, the code of your example can be simplified to
class POINT
create
make
feature -- Access
x: DOUBLE
y: DOUBLE
feature {NONE} -- Creation
make (x0: DOUBLE; y0: DOUBLE)
-- Initialize object with `x0' and `y0'.
do
x := x0
y := y0
ensure
set: x = x0 and y = y0
end
end
Note that the creation procedure is not exported anymore, otherwise it would be possible to use it as a normal (i.e. non-creation) routine and to change the attributes, that is we would be able to do something as follows
create p.make (1, 1)
p.make (2, 3)
print (p)
and this would print (2, 3), i.e. you would be able to change the value of the original object p, making it mutable.
Though, now the attributes cannot be changed directly, it's still possible to call feature copy on an object of type POINT and to change the whole object. If you want to avoid this situation as well, the feature can be redefined in the class POINT to raise an exception, or even to have a postcondition False causing the run-time to raise an exception for you:
copy (other: like Current)
-- <Precursor>
do
(create {EXCEPTIONS}).raise ("Attempt to change an immutable object.")
ensure then
is_allowed: False
end

Related

Julia JuMP array variable constraint

I am trying to model a non-linear problem involving vector rotation using JuMP in Julia. I need a constraint, which looks something like v[1:3] == rotate(v) If I write it like this, it does not work, since "Nonlinear expressions may contain only scalar expressions". How can I work around this?
I could say something like v[1] == rotate(v)[1] and same for v[2] and v[3], but then I would have to compute rotate(v) three times as often. I could also try to split the rotate function into three functions which compute one element each, but the actual constraint is a bit more complicated than a simple rotation, so this could prove to be tricky.
Are there any other ways to do this? Maybe to have something like an auxiliary variable which can be computed as a vector and then in the constraint only compare the elements of the two vectors (essentialy the first approach, but without computing the function three times)?
See here for a suggested work-around:
https://discourse.julialang.org/t/how-to-set-up-nlconstraints-from-multi-output-user-defined-function/42309/5?u=odow
using JuMP
using Ipopt
function myfun(x)
return sum(xi for xi in x), sum(xi^2 for xi in x)
end
function memoized()
cache = Dict{UInt, Any}()
fi = (i, x) -> begin
h = hash((x, typeof(x)))
if !haskey(cache, h)
cache[h] = myfun(x)
end
return cache[h][i]::Real
end
return (x...) -> fi(1, x), (x...) -> fi(2, x)
end
model = Model(Ipopt.Optimizer)
f1, f2 = memoized()
register(model, :f1, 3, f1; autodiff = true)
register(model, :f2, 3, f2; autodiff = true)
#variable(model, x[1:3] >= 0, start = 0.1)
#NLconstraint(model, f1(x...) <= 2)
#NLconstraint(model, f2(x...) <= 1)
#objective(model, Max, sum(x))
optimize!(model)

Modelica: assign array return value to scalars

The following model tries to assign a vector return value of a function call to a vector of scalars. It checks and works if it is inside an equation section, but it fails inside an algorithm section. Is that a bug in the Modelica tool I am using, or am I doing something wrong? And, how can I write it without introducing the intermediate variable x[2]?
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1,2;3,4];
Real b[2] = {8,7};
algorithm
x = Modelica.Math.Matrices.solve(A,b);
{x1, x2} = Modelica.Math.Matrices.solve(A,b);
end returnVector;
You are doing something wrong :-)
In equations the left-hand-side is any expression; so you could even write Modelica.Math.Matrices.solve(A,b)={x1,x2};.
In algorithms the left-hand-side must be a component-reference (section 11.2 in Modelica 3.4; https://modelica.org/documents/ModelicaSpec34.pdf ) and the right-hand-side is evaluated and then assigned to the left-hand-side variable.
Under the 'algorithm', one must use ' := ' to represent the Assignment in Modelica instead of ' = ' as like in C/C++.
So the code could be rewritten as follows:
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1, 2; 3, 4];
Real b[2] = {8, 7};
algorithm
x := Modelica.Math.Matrices.solve(A, b);
x1 := x[1];
x2 := x[2];
//{x1, x2} = Modelica.Math.Matrices.solve(A, b);
end returnVector;
Simply write the left-hand-side within round parentheses:
({x1, x2}) := Modelica.Math.Matrices.solve(A, b);

What is wrong with my if statement 'if x + y = z'

I am trying to evaluate if a selected item meats a requirement. I am trying to evaluate the result of nominal + x against required.
I am using the following code:
if #weight.nominal + x = required
weights << #weight.id
end
However, it adds nominal + x together. Why is that, and how do I do what I want?
As #Pavan said in the comment, your conditional might be wrong. It should be == instead of =. = is the assignment.
if #weight.nominal + x == required ... end
Here what happens "behind the scene" with your original code:
required is assigned to x.
Add x to #weight.nominal (#weight.nominal + x)
Evaluate the result from step 2, which is always true.
Execute the code within if block, which is weights << #weight.id
Eventually, your x's value is lost, it will take required value instead and your conditional is useless since it always true.

how does this checks surrounding cells in a 2D array

I am attempting to write a battleship game in ruby. I came across a code snippet that I think I grasp, but was hoping you all could maybe offer some clarification. The [-1,0,1] is what is throwing me. This is to check a 2D array. Thank you for your help as always.
def neighbors
#neighbors ||= [-1, 0, 1].repeated_permutation(2).map do |dx, dy|
#grid[x + dx, y + dy] unless dx.zero? && dy.zero?
end.compact
end
I think I may have figured it out finally. The repeated_permutation(2) takes to of the values in the [-1,0,1] to search around the "cell" in question.
What ||= means is if #neighbors responds to a nil (NilClass) object type or false (FalseClass) object value, it will take the value which you're assigning in the right side, that's to say the result of:
[-1, 0, 1].repeated_permutation(2).map do |dx, dy|
#grid[x + dx, y + dy] unless dx.zero? && dy.zero?
end.compact
To use ||= is like to use x || x = a or maybe x = a unless x, but in the Ruby way to be simple to read, simple to understand, simple to work with.
And what the [-1, 0, 1].repeated_permutation(2).map is trying to do is to map the result of a repeated_permutation over the [-1, 0, 1] array and to take the first and second value within the permutation, and to set your #grid variable probably (because I can't say what's #grid) as a range starting in the sum of dx plus x and then dy plus y unless the value of dx and dy are 0 at the same time (&&). Then compact the "mapped" result.
You might want to see Array#repeated_permutation and Array#permutation
Quick & dirty permutations are like minor changes to a series of numbers ([link to more indepth])1. What you're looking at is the array with being altered by the .repeated_permutations to find all options for each value & the results then being added to the original x & y coords...
The ||= & the unless parts are just checks to ensure the code doesn't run on 0's ...

How to apply HoldForm to a list of variables without the variables in the list being evaluated first?

I am writing a debug function, which prints a variable name, and its value. I call this debug function with a list of variables from anywhere in the program. So the idea is for it to work like this:
debug[var_List] := Module[{values = ReleaseHold[var], i},
For[i = 1, i <= Length[values], i++,
Print[var[[i]], " = ", values[[i]]]
]
];
Now I use the above, like this
x = 3; y = 5;
debug[{HoldForm[x], HoldForm[y]}]
and I see in the console the following
x = 3
y = 5
But I have a large program and long list of variables at different places I want to debug. And I do not want to type HoldForm to each variable to make up the list to call the debug[] function. Much easier to Map it if possible. Less typing each time. But this does not work:
debug[ Map[HoldForm,{x,y}]]
The reason is that {x,y} was evaluated before HoldForm got hold of it. So I end up with a list that has the values in it, like this:
3 = 3
5 = 5
I could not find a way to Map HoldForm without the list being evaluated.
The best I could find is this:
debug[HoldForm[Defer[{x, y}]]]
which gives the following output from the above debug[] function:
{x,y} = {3,5}
Since Defer[{x, y}] has length 1, and it is just one thing, I could not break it up to make a 2 column list like in the above example.
It will be better if I can get an output of the form
x = 3
y = 5
easier to match the variable with its value since I have many variables.
question is: Any one knows of a programming trick to convert HoldForm[{x,y}] to {HoldForm[x],HoldForm[y]}
thanks
Just use Thread:
Thread[HoldForm[{x, y}]]
alternatively,
Map[HoldForm, Unevaluated[{x, y}]]
Here is a longer alternative demonstrating use of Hold, found in Roman Maeder's Programming In Mathematica (3rd ed.), page 137:
e1 = Hold[{x, y}];
e2 = MapAt[Hold, e1, {1, 0}];
e3 = Map[HoldForm, e2, {2}];
e4 = MapAt[ReleaseHold, First[e3], {0}];
debug[e4]
x=3
y=5
I did a PrintIt function using attributes that does what you want. I posted it here https://stackoverflow.com/a/8270643/884752, I repeat the code:
SetAttributes[System`ShowIt, HoldAll];
System`ShowIt[code__] := System`ShowIt[{code}];
System`ShowIt[code_] :=
With[{y = code},
Print[Defer[code = y]];
y
];
SetAttributes[System`PrintIt, {HoldAll,Listable}];
System`PrintIt[expr__]:=System`PrintIt[{expr}];
System`PrintIt[expr_] := System`ShowIt[expr];

Resources