Why does assignment return the old value instead of the new one? - ponylang

Why does assignment return the previous value instead of the new value, re example: assigns 0 to y instead of 2? This is dangerously unusual as it violates the principle of least surprise.
var x: I32 = 0
let y = (x = 2)

I am pretty sure this was done to get consistent results for iso variables. Assignment to an iso variable would not be able to return the new value because that created an alias. But it's true that a less surprising design would involve an assignment operator returning None and some other operation (swap?) for the recovery of the original value that is being overwritten.

Related

Issue with Double datatype in Scala

New to Scala and am trying to come up with a library in Scala to check if the double value being passed is of a certain precision and scale. What I noticed was that if the value being passed is 1.00001 then I get the value as that in my called function, but if the value being passed is 0.00001 then I get the value as 1.0E-5, Is there any way to preserve the number in Scala?
def checkPrecisionAndScaleFormat(precision: Int, scale: Int)(valueToCheck: Double): Boolean = {
val value = BigDecimal(valueToCheck)
value.precision <= precision && value.scale <= scale
}
What I noticed was that if the value being passed is 1.00001 then I get the value as that in my called function, but if the value being passed is 0.00001 then I get the value as 1.0E-5
From your phrasing, it seems like you see 1.00001 and 1.0E-5 when debugging (either by printing or in the debugger). It's important to understand that
this doesn't correspond to any internal difference, it's just how Double.toString is defined in Java.
when you do something like val x = 1.00001, the value isn't exactly 1.00001 but the closest number representable as a Double: 1.000010000000000065512040237081237137317657470703125. The easiest way to see the exact value is actually looking at BigDecimal.exact(valueToCheck).
The only way to preserve the number is not to work with Double to begin with. If it's passed as a string, create the BigDecimal from the string. If it's the result of some calculations as a double, consider doing them on BigDecimals instead. But string representation of a Double simply doesn't carry the information you want.

Ambiguous use of "subscript"

I'm having an issue trying to access the nth element of a Range using subscripts. The code is super simple:
var range = 0..<9
var itemInRange = range[n] // n is some Int where 0 <= n < 9
The second line complains with the error Ambiguous use of "subscript", which I took to mean that Xcode wasn't clear what the type of the variable range is, and so it's unable to know which implementation of subscript to use. I tried to fix this by explicitly defining the type of range with
var range: Range<Int> = 0..<9
and
var firstInRange = (range as Range<Int>)[0]
but neither of these solved the problem. Is there a way to get Xcode to disambiguate the call to subscript?
You can create an array with the range and then pick an element from the array.
var range = [Int](0..<9)
var itemInRange = range[1]
From apple docs
A collection of consecutive discrete index values.
Like other collections, a range containing one element has an endIndex
that is the successor of its startIndex; and an empty range has
startIndex == endIndex.
Axiom: for any Range r, r[i] == i.
Therefore, if Element has a maximal value, it can serve as an
endIndex, but can never be contained in a Range.
It also follows from the axiom above that (-99..<100)[0] == 0. To
prevent confusion (because some expect the result to be -99), in a
context where Element is known to be an integer type, subscripting
with Element is a compile-time error:
// error: could not find an overload for 'subscript'...
print(Range(start: -99, end: 100)[0])
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Reference/Swift_Range_Structure/index.html

Find value in vector "p" that corresponds to maximum value in vector "r = f(p)"

As simple as in title. I have nx1 sized vector p. I'm interested in the maximum value of r = p/foo - floor(p/foo), with foo being a scalar, so I just call:
max_value = max(p/foo-floor(p/foo))
How can I get which value of p gave out max_value?
I thought about calling:
[max_value, max_index] = max(p/foo-floor(p/foo))
but soon I realised that max_index is pretty useless. I'm sorry asking this, real beginner here.
Having dropped the issue to pieces, I realized there's no unique corrispondence between values p and values in my related vector p/foo-floor(p/foo), so there's a logical issue rather than a language one.
However, given my input data, I know that the solution is unique. How can I fix this?
I ended up doing:
result = p(p/foo-floor(p/foo) == max(p/foo-floor(p/foo)))
Looks terrible, so if you know any other way...
Once you have the index, use it:
result = p(max_index)
You can create a new vector with your lets say "transformed" values:
p2 = (p/foo-floor(p/foo))
and then just use find to find the max values on p2:
max_index = find(p2 == max(p2))
that will return the index or indices of p2 with the max value of that operation, and finally just lookup the original value in p
p(max_index)
in 1 line, this is:
p(find((p/foo-floor(p/foo) == max((p/foo-floor(p/foo))))))
which is basically the same thing you did in the end :)

Number Operations and Return Types

I am confused by what is returned when performing number operations in Swift between various types. Consider the following:
var castedFoo = Float(7.0/5.0) // returns 1.39999997...
var specifiedTypeFoo:Float = 7/5.0 //returns 1.39999997...
var foo = (7/5.0) //returns 1.4
What separates the first two from the last one? They are all returning floats, so why is the value from the last one rounded? I understand that the first is casted and the second explicitly specified to be a Float, but the last one also returns a Float value. So what makes the difference here?
According to Swift documentation,
Unless otherwise specified, the default type of a floating-point literal is the Swift standard library type Double, which represents a 64-bit floating-point number.
In other words, the literal 5.0 is of type Double.
Your first two examples set the result type to Float; your last example keeps the type of the result a Double, because the result of the division of an Int and a Double is a Double. Because of that difference, the last result has higher precision.

How exactly does the "let" keyword work in Swift?

I've read this simple explanation in the guide:
The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.
But I want a little more detail than this. If the constant references an object, can I still modify its properties? If it references a collection, can I add or remove elements from it? I come from a C# background; is it similar to how readonly works (apart from being able to use it in method bodies), and if it's not, how is it different?
let is a little bit like a const pointer in C. If you reference an object with a let, you can change the object's properties or call methods on it, but you cannot assign a different object to that identifier.
let also has implications for collections and non-object types. If you reference a struct with a let, you cannot change its properties or call any of its mutating func methods.
Using let/var with collections works much like mutable/immutable Foundation collections: If you assign an array to a let, you can't change its contents. If you reference a dictionary with let, you can't add/remove key/value pairs or assign a new value for a key — it's truly immutable. If you want to assign to subscripts in, append to, or otherwise mutate an array or dictionary, you must declare it with var.
(Prior to Xcode 6 beta 3, Swift arrays had a weird mix of value and reference semantics, and were partially mutable when assigned to a let -- that's gone now.)
It's best to think of let in terms of Static Single Assignment (SSA) -- every SSA variable is assigned to exactly once. In functional languages like lisp you don't (normally) use an assignment operator -- names are bound to a value exactly once. For example, the names y and z below are bound to a value exactly once (per invocation):
func pow(x: Float, n : Int) -> Float {
if n == 0 {return 1}
if n == 1 {return x}
let y = pow(x, n/2)
let z = y*y
if n & 1 == 0 {
return z
}
return z*x
}
This lends itself to more correct code since it enforces invariance and is side-effect free.
Here is how an imperative-style programmer might compute the first 6 powers of 5:
var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
var n2 = n*n
powersOfFive += n2*n2*n
}
Obviously n2 is is a loop invariant so we could use let instead:
var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
let n2 = n*n
powersOfFive += n2*n2*n
}
But a truly functional programmer would avoid all the side-effects and mutations:
let powersOfFive = [1, 2, 3, 4, 5, 6].map(
{(num: Int) -> Int in
let num2 = num*num
return num2*num2*num})
Let
Swift uses two basic techniques to store values for a programmer to access by using a name: let and var. Use let if you're never going to change the value associated with that name. Use var if you expect for that name to refer to a changing set of values.
let a = 5 // This is now a constant. "a" can never be changed.
var b = 2 // This is now a variable. Change "b" when you like.
The value that a constant refers to can never be changed, however the thing that a constant refers to can change if it is an instance of a class.
let a = 5
let b = someClass()
a = 6 // Nope.
b = someOtherClass() // Nope.
b.setCookies( newNumberOfCookies: 5 ) // Ok, sure.
Let and Collections
When you assign an array to a constant, elements can no longer be added or removed from that array. However, the value of any of that array's elements may still be changed.
let a = [1, 2, 3]
a.append(4) // This is NOT OK. You may not add a new value.
a[0] = 0 // This is OK. You can change an existing value.
A dictionary assigned to a constant can not be changed in any way.
let a = [1: "Awesome", 2: "Not Awesome"]
a[3] = "Bogus" // This is NOT OK. You may not add new key:value pairs.
a[1] = "Totally Awesome" // This is NOT OK. You may not change a value.
That is my understanding of this topic. Please correct me where needed. Excuse me if the question is already answered, I am doing this in part to help myself learn.
First of all, "The let keyword defines a constant" is confusing for beginners who are coming from C# background (like me). After reading many Stack Overflow answers, I came to the conclusion that
Actually, in swift there is no concept of constant
A constant is an expression that is resolved at compilation time. For both C# and Java, constants must be assigned during declaration:
public const double pi = 3.1416; // C#
public static final double pi = 3.1416 // Java
Apple doc ( defining constant using "let" ):
The value of a constant doesn’t need to be known at compile time, but you must assign the value exactly once.
In C# terms, you can think of "let" as "readonly" variable
Swift "let" == C# "readonly"
F# users will feel right at home with Swift's let keyword. :)
In C# terms, you can think of "let" as "readonly var", if that construct was allowed, i.e.: an identifier that can only be bound at the point of declaration.
Swift properties:
Swift Properties official documentation
In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by the varkeyword) or constant stored properties (introduced by the let keyword).
Example:
The example below defines a structure called FixedLengthRange, which describes a range of integers whose range length cannot be changed once it is created:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
Instances of FixedLengthRange have a variable stored property called firstValue and a constant stored property called length. In the example above, length is initialized when the new range is created and cannot be changed thereafter, because it is a constant property.