Why is a variable not immutable? - elm

Why is varx not immutable in this code?
y = { g = 'a' }
z = { g = 1 }
varx = foo y
varx = foo z
Anybody knows? Thanks.

I guess that this code is executed in the Elm REPL. Immutable variables behave a little differently there. From the Beginning Elm book:
https://elmprogramming.com/immutability.html
The repl works a little differently. Whenever we reassign a different value to an existing constant, the repl essentially rebinds the constant to a new value. The rebinding process kills the constant and brings it back to life as if the constant was never pointing to any other value before.
When compiling Elm code the ordinary way with Elm make, this code would lead to an error.

Related

Nim sequence assignment value semantics

I was under the impression that sequences and strings always get deeply copied on assignment. Today I got burned when interfacing with a C library to which I pass unsafeAddr of a Nim sequence. The C library writes into the memory area starting at the passed pointer.
Since I don't want the original Nim sequence to be changed by the library I thought I'll simply copy the sequence by assigning it to a new variable named copy and pass the address of the copy to the library.
Lo and behold, the modifications showed up in the original Nim sequence nevertheless. What's even more weird is that this behavior depends on whether the copy is declared via let copy = ... (changes do show up) or via var copy = ... (changes do not show up).
The following code demonstrates this in a very simplified Nim example:
proc changeArgDespiteCopyAssignment(x: seq[int], val: int): seq[int] =
let copy = x
let copyPtr = unsafeAddr(copy[0])
copyPtr[] = val
result = copy
proc dontChangeArgWhenCopyIsDeclaredAsVar(x: seq[int], val: int): seq[int] =
var copy = x
let copyPtr = unsafeAddr(copy[0])
copyPtr[] = val
result = copy
let originalSeq = #[1, 2, 3]
var ret = changeArgDespiteCopyAssignment(originalSeq, 9999)
echo originalSeq
echo ret
ret = dontChangeArgWhenCopyIsDeclaredAsVar(originalSeq, 7777)
echo originalSeq
echo ret
This prints
#[9999, 2, 3]
#[9999, 2, 3]
#[9999, 2, 3]
#[7777, 2, 3]
So the first call changes originalSeq while the second doesn't. Can someone explain what is going on under the hood?
I'm using Nim 1.6.6 and a total Nim newbie.
Turns out there are a lot of issues concerned with this behavior in the nim-lang issue tracker. For example:
let semantics gives 3 different results depends on gc, RT vs VM, backend, type, global vs local scope
Seq assignment does not perform a deep copy
Let behaves differently in proc for default gc
assigning var to local let does not properly copy in default gc
clarify spec/implementation for let: move or copy?
RFC give default gc same semantics as --gc:arc as much as possible
Long story short, whether a copy is made depends on a lot of factors, for sequences especially on the scope (global vs. local ) and the gc (refc, arc, orc) in use.
More generally, the type involved (seq vs. array), the code generation backend (C vs. JS) and whatnot can also be relevant.
This behavior has tricked a lot of beginners and is not well received by some of the contributors. It doesn't happen with the newer GCs --gc:arc or --gc:orc where the latter is expected to become the default GC in an upcoming Nim version.
It has never been fixed in the current default gc because of performance concerns, backward compatibility risks and the expectation that it will disappear anyway once we transition to the newer GCs.
Personally, I would have expected that it at least gets clearly singled out in the Nim language manual. Well, it isn't.
I took a quick look at the generated C code, a highly edited and simplified version is below.
The essential thing that is missing in the let code = ... variant is the call to genericSeqAssign() which makes a copy of the argument and assigns that to copy, instead the argument is assigned to copy directly. So, there is definitely no deep copy on assignment in that case.
I don't know if that is intentional or if it is a bug in the code generation (my first impression was astonishment). Any ideas?
tySequence_A* changeArgDespiteCopyAssignment(tySequence_A* x, NI val) {
tySequence_A* result = NIM_NIL;
tySequence_A* copy;
NI* copyPtr;
copy = x; /* NO genericSeqAssign() call !*/
copyPtr = &copy->data[(NI) 0];
*copyPtr = val;
genericSeqAssign(&result, copy, &NTIseqLintT_B);
return result;
}
tySequence_A* dontChangeArgWhenCopyIsDeclaredAsVar(tySequence_A* x, NI val) {
tySequence_A* result = NIM_NIL;
tySequence_A copy;
NI* copyPtr;
genericSeqAssign(&copy, x, &NTIseqLintT_B);
copyPtr = &copy->data[(NI) 0];
*copyPtr = val;
genericSeqAssign(&result, copy, &NTIseqLintT_B);
return result;
}

why are objects clipping behind each other?

I'm making a script that sorts the depth for my objects by prioritizing the y variable, but then afterwards checks to see if the objects that are touching each other have a higher depth the further to the right they are, but for some reason the last part isn't working.
Here's the code:
ds_grid_sort(_dg,1,true);
_yy = 0;
repeat _inst_num
{
_inst = _dg[# 0, _yy];
with _inst
{
with other
{
if (x > _inst.x and y = _inst.y)
{
_inst.depth = depth + building_space;
}
}
}
_yy++;
}
I've identified that the problem is that nothing comes out as true when the game checks the y = _inst.y part of the _inst statement, but that doesn't make any sense seeing how they're all at the same y coordinate. Could someone please tell me what I'm doing wrong?
As Steven mentioned, it's good practice to use double equal signs for comparisons (y == _inst.y) and a single equals sign for assignments (_yy = 0;), but GML doesn't care if you use a single equals sign for comparison, so it won't be causing your issue. Though it does matter in pretty much every other language besides GML.
From what I understand, the issue seems to be your use of other. When you use the code with other, it doesn't iterate through all other objects, it only grabs one instance. You can test this by running this code and seeing how many debug messages it shows:
...
with other
{
show_debug_message("X: "+string(x)+"; Y: "+string(y));
...
You could use with all. That will iterate through all objects or with object, where object is either an object or parent object. That will iterate through all instances of that object. However, neither of these functions check whether the objects overlap (it's just going to iterate over all of them), so you'll have to check for collisions. You could do something like this:
...
with all
{
if place_meeting(x, y, other)
{
if (x > _inst.x and y = _inst.y)
{
_inst.depth = depth + building_space;
}
}
...
I don't know what the rest of your code looks like, but there might be an easier way to achieve your goal. Is it possible to initially set the depth based on both the x and y variables? Something such as depth = -x-y;? For people not as familiar with GameMaker, objects with a smaller depth value are drawn above objects with higher depth values; that is why I propose setting the depth to be -x-y. Below is what a view of that grid would look like (first row and column are x and y variables; the other numbers would be the depth of an object at that position):
Having one equation that everything operates on will also make it so that if you have anything moving (such as a player), you can easily and efficiently update their depth to be able to display them correctly relative to all the other objects.
I think it should be y == _inst.y.
But I'm not sure as GML tends to accept such formatting.
It's a better practise to use == to check if they're equal when using conditions.

F# poorly formatted module

Hi what is wrong with my code below, my errors are:
unmatched { which is mostly due to my tabs,
Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq { ... }'
Incomplete structured construct at or before this point in expression
module records =
let debate(irthes:DateTime) =
{
let mutable manch = nexttime(irthes)
let mutable array1: DateTime array = Array.zeroCreate 480
for i in 0 .. 480-1 do
Array.set array1 i (manch)
let next = Array.get array1 i
let! manch=nexttime(next)
return(array1)
}
I suppose you want something like this:
module records =
let debate(irthes:DateTime) =
let mutable manch = nexttime(irthes)
let array1: DateTime array = Array.zeroCreate 480
for i in 0 .. 480-1 do
array1.[i] <- manch
manch <- nexttime manch
array1
Here are things that were wrong with the code:
You are not using computation expressions (like asynchronous workflows), so there is no need to wrap things in curly brackets.
To return a value you do not need return. Just use the value as the last expression of the body
The let! construct does not mean assign. It has a fairly special meaning in computation expressions. To mutate manch, you can write manch <- nexttime(next).
Not an error, but you do not need to mark the array as mutable. You are mutating its contents, not the array1 variable.
You can make the code nicer by using arr.[i] <- v to write to an array and arr.[i] to read from an array. I also do not understand why you were reading a value immediately after writing it.
There's not that much that's even valid about what you're trying to do. First off, it seems you're trying to initialize a record -- to do so, you have to assign the fields to values with =, like so:
type Person = { name: string; address: string }
let joe = { name = "Joe Smith"; address: "1600 Pennsylvania Avenue NW, Washington, 20500" }
Also, F# doesn't have an early exit (return); the result of any function/method is simply the result of the last expression:
let increment n = n + 1
Hence no return n + 1. Also, let! is only used in computation expressions. However, if you want to mutate a variable, foo for example, to 42, use foo <- 42. One last thing that I see: the line with return(array1) is lacking another space of indentation -- it really matters!
It looks like you might be copy-pasting code without knowing what any of it means -- that doesn't often work out too well. If this is the case, try to understand exactly how certain features in F# work by testing them out yourself. It'll go a lot smoother in the long run.

Why can't you use a object property as an index in a for loop? (MATLAB)

Below is an example that doesn't work in Matlab because obj.yo is used as the for loop's index. You can just convert this to the equivalent while loop and it works fine, so why won't Matlab let this code run?
classdef iter_test
properties
yo = 1;
end
methods
function obj = iter_test
end
function run(obj)
for obj.yo = 1:10
disp('yo');
end
end
end
end
Foreword: You shouldn't expect too much from Matlab's oop capabilities. Even though things have gotten better with matlab > 2008a, compared to a real programming language, oop support in Matlab is very poor.
From my experience, Mathworks is trying to protect the user as much as possible from doing mistakes. This sometimes also means that they are restricting the possibilities.
Looking at your example I believe that exactly the same is happening.
Possible Answer: Since Matlab doesn't have any explicit typing (variables / parameters are getting typed on the fly), your code might run into problems. Imagine:
$ a = iter_test()
% a.yo is set to 1
% let's overwrite 'yo'
$ a.yo = struct('somefield', [], 'second_field', []);
% a.yo is now a struct
The following code will therefore fail:
$ for a.yo
disp('hey');
end
I bet that if matlab would support typing of parameters / variables, your code would work just fine. However, since you can assign a completely different data type to a parameter / variable after initialization, the compiler doesn't allow you to do what you want to do because you might run into trouble.
From help
"properties are like fields of a struct object."
Hence, you can use a property to read/write to it. But not use it as variable like you are trying to do. When you write
for obj.yo = 1:10
disp('yo');
end
then obj.yo is being used as a variable, not a field name.
compare to actual struct usage to make it more clear:
EDU>> s = struct('id',10)
for s.id=1:10
disp('hi')
end
s =
id: 10
??? for s.id=1:10
|
Error: Unexpected MATLAB operator.
However, one can 'set' the struct field to new value
EDU>> s.id=4
s =
id: 4
compare the above error to what you got:
??? Error using ==> iter_test
Error: File: iter_test.m Line: 9 Column: 20
Unexpected MATLAB operator.
Therefore, I do not think what you are trying to do is possible.
The error is
??? Error: File: iter_test.m Line: 9 Column: 20
Unexpected MATLAB operator.
Means that the MATLAB parser doesn't understand it. I'll leave it to you to decide whether it's a bug or deliberate. Raise it with TMW Technical Support.
EDIT: This also occurs for all other kinds of subscripting:
The following all fail to parse:
a = [0 1];
for a(1) = 1:10, end
a = {0 1};
for a{1} = 1:10, end
a = struct('a', 0, 'b', 0);
for a.a = 1:10, end
It's an issue with the MATLAB parser. Raise it with Mathworks.

== Operator and operands

I want to check whether a value is equal to 1. Is there any difference in the following lines of code
Evaluated value == 1
1 == evaluated value
in terms of the compiler execution
In most languages it's the same thing.
People often do 1 == evaluated value because 1 is not an lvalue. Meaning that you can't accidentally do an assignment.
Example:
if(x = 6)//bug, but no compiling error
{
}
Instead you could force a compiling error instead of a bug:
if(6 = x)//compiling error
{
}
Now if x is not of int type, and you're using something like C++, then the user could have created an operator==(int) override which takes this question to a new meaning. The 6 == x wouldn't compile in that case but the x == 6 would.
It depends on the programming language.
In Ruby, Smalltalk, Self, Newspeak, Ioke and many other single-dispatch object-oriented programming languages, a == b is actually a message send. In Ruby, for example, it is equivalent to a.==(b). What this means, is that when you write a == b, then the method == in the class of a is executed, but when you write b == a, then the method in the class of b is executed. So, it's obviously not the same thing:
class A; def ==(other) false end; end
class B; def ==(other) true end; end
a, b = A.new, B.new
p a == b # => false
p b == a # => true
No, but the latter syntax will give you a compiler error if you accidentally type
if (1 = evaluatedValue)
Note that today any decent compiler will warn you if you write
if (evaluatedValue = 1)
so it is mostly relevant for historical reasons.
Depends on the language.
In Prolog or Erlang, == is written = and is a unification rather than an assignment (you're asserting that the values are equal, rather then testing that they are equal or forcing them to be equal), so you can use it for an assertion if the left hand side is a constant, as explained here.
So X = 3 would unify the variable X and the value 3, whereas 3 = X would attempt to unify the constant 3 with the current value of X, and be equivalent of assert(x==3) in imperative languages.
It's the same thing
In general, it hardly matters whether you use,
Evaluated value == 1 OR 1 == evaluated value.
Use whichever appears more readable to you. I prefer if(Evaluated value == 1) because it looks more readable to me.
And again, I'd like to quote a well known scenario of string comparison in java.
Consider a String str which you have to compare with say another string "SomeString".
str = getValueFromSomeRoutine();
Now at runtime, you are not sure if str would be NULL. So to avoid exception you'll write
if(str!=NULL)
{
if(str.equals("SomeString")
{
//do stuff
}
}
to avoid the outer null check you could just write
if ("SomeString".equals(str))
{
//do stuff
}
Though this is less readable which again depends on the context, this saves you an extra if.
For this and similar questions can I suggest you find out for yourself by writing a little code, running it through your compiler and viewing the emitted asembler output.
For example, for the GNU compilers, you do this with the -S flag. For the VS compilers, the most convenient route is to run your test program in the debugger and then use the assembeler debugger view.
Sometimes in C++ they do different things, if the evaluated value is a user type and operator== is defined. Badly.
But that's very rarely the reason anyone would choose one way around over the other: if operator== is not commutative/symmetric, including if the type of the value has a conversion from int, then you have A Problem that probably wants fixing rather than working around. Brian R. Bondy's answer, and others, are probably on the mark for why anyone worries about it in practice.
But the fact remains that even if operator== is commutative, the compiler might not do exactly the same thing in each case. It will (by definition) return the same result, but it might do things in a slightly different order, or whatever.
if value == 1
if 1 == value
Is exactly the same, but if you accidentally do
if value = 1
if 1 = value
The first one will work while the 2nd one will produce an error.
They are the same. Some people prefer putting the 1 first, to void accidentally falling into the trap of typing
evaluated value = 1
which could be painful if the value on the left hand side is assignable. This is a common "defensive" pattern in C, for instance.
In C languages it's common to put the constant or magic number first so that if you forget one of the "=" of the equality check (==) then the compiler won't interpret this as an assignment.
In java, you cannot do an assignment within a boolean expression, and so for Java, it is irrelevant which order the equality operands are written in; The compiler should flag an error anyway.