Clojure: (double 0) vs (cast (class 0.0) 0) - clojure

I'm trying to dynamically cast values of a list - I don't need to, but I'm curious what the issue is here:
(double 0) ; => 0.0
(class 0.0) ; => java.lang.Double
(cast (class 0.0) 0) ; => ClassCastException Cannot cast java.lang.Long to
; java.lang.Double java.lang.Class.cast
I'm guessing it has something to do with the captial D in Double. Why can't I cast the way I've tried in the code above?

That's just not what cast does in Clojure - it is not a Java cast, because such casts make no sense in a language with dynamic rather than static types. Indeed there is really almost never a reason to call cast at all; I certainly haven't, in five years of Clojure programming. See the documentation for cast: it always returns exactly its input, never anything else. Its only effect is to throw an exception if the input doesn't match the class you wanted to cast to.

On the JVM, we have the primitive long and double types and the object Long and Double types. You're dealing with the objects (capial L, capital D), not the primitives. The hierarchy for the objects is as follows:
|- Object
|- Number
|- Long
|- Double
As you can see, though they're both a Number, a Long isn't a Double, so casting will fail.
To coerce to a Double, use that double function:
(class 0) ; => java.lang.Long
(class (double 0)) ; => java.lang.Double

Related

Using comparison operator in Ocaml produces type error

I'm an OCaml beginner using OCaml 4.12.0 on MacOS. This let expression:
let gg x y = (x -. y) < 5.0
at the toplevel results in:
Error: This expression has type float but an expression was expected of type
int
Explicitly adding type information, etc., did not fix the problem. In frustration, I visited the online REPL TryOCaml, and the expression was accepted without error, returning the type signature of:
val f : float -> float -> bool = <fun>
as expected. But I'd like utop to work on the Mac - what am I missing?
Very possibly you're using a library that overrides the built-in meaning of < in OCaml. Some people (not me) think the polymorphic comparison operators are a problem.
One problem with this (IMHO) is that it causes confusing results like this.
For example, the Jane Street Base library is documented as overriding the polymorphic comparison operators: https://ocaml.janestreet.com/ocaml-core/latest/doc/base/index.html
When you use Base (or Core, or Core_kernel and other Janestreet standard libraries) the comparison operator and its friends (like various equality operators) work only on values of type int. For all other values you have to use specialized comparison operators provided by the module that implements that type, e.g., to compare two floats,
Float.(3.14 < 4.14)
to compare strings,
String.("hello" <> "world")
And, using your example,
let gg x y = Float.(x -. y < 5.0)
or even
let gg x y = Float.(x - y < 5.0)
Notice that we don't need to use the ugly -. operators anymore and can use - (and other arithmetic operators) as they are all defined specifically for float in module Float.
Besides, the notation Foo.(<expr>) is a short-hand for let open Foo in <expr> and is called local open.

How to do an unsafe addition (addition without throwing OverflowException) in Crystal?

How do I able to add Int::MAX + 1 without getting OverflowException? I know I can do
def add_unsafe(a : Int, b : Int) : Int
((a.to_i128 + b.to_i128) % Int32::MAX).to_i
end
But is there any alternative to do this?
You're looking for wrapping operators. Most math operators have a wrapping variant prefixed with &. So in your case, that would be a &+ b.
Btw. your example doesn't work because to_i still does an overflow check. So calling add_unsafe(Int32::MAX, 1) raises an error.
A more accurate representation of wrapping behaviour would be (a.to_i128 + b.to_i128) % Int32::MAX. The &+ operator is obviously better, though.

c++ function overloading, what are the exact steps

I was reading about function overloading and found the following:
The compiler lists all functions with the same name and the same
number of arguments, and then it starts looking for a function using
the following rules by a fixed order and stops when there is a match.
1) A function that exactly has the same arguments' types as the call
to it.
2) bool-> int char->int float-> double... (-> means is converted to)
3) int-> double, double->int... (-> means is converted to)
For example:
void foo(int x)
{
return;
}
foo(True);//will trigger step 2.
could someone elaborate number 2 and 3? and add the full list?
1) A function that exactly has the same arguments' types as the call to it
So if im trying to call foo(1) it will first try to find any function named foo that takes a single argument of type int.
2) bool-> int char->int float-> double... (-> means is converted to)
So if i do foo(True) and it doesnt find anything in step 1, it will try converting True to an int and will do step 1) again
3) int-> double, double->int... (-> means is converted to)
If the 2) step doesnt find any suitable functions, it will try converting any int arguments into double, and so on.

Avoid casting floating point constant

I'm creating cargo that (among other things) will implement idiomatic angle measurment. When creating methods to convert between angle units I've found problem:
impl<T> Angle<T>
where T: Float {
pub fn to_deg(self) -> Self {
Deg(match self {
Rad(v) => v * cast(180.0 / f64::consts::PI).unwrap(),
Deg(v) => v,
Grad(v) => v * cast(180.0 / 200.0).unwrap() // how to get rid of this cast?
})
}
}
Runnable
The cast of 180.0 / 200.0 seem really unneded for me? Is there any way to get rid of this?
When I delete cast then I get:
src/angles.rs:42:28: 42:33 error: mismatched types:
expected `T`,
found `_`
(expected type parameter,
found floating-point variable) [E0308]
src/angles.rs:42 Grad(v) => v * 180.0 / 200.0
^~~~~
When you have a generic function with a type parameter, such as T, you don't get to choose the type. The type is forced on you by the caller of the function.
The error here is that you're trying to assign a specific f32/f64 type to a type T, which could be anything that implements Float.
You know in practice it's going to be either one of the floating-point types, but theoretically the type system won't stop someone from implementing Float on a string or an array, or a tuple of two function pointers, or any other bizarre thing that can't be assigned a float. When the compiler can't guarantee it'll always work, including in theory in the future, then it won't accept it.
If you want to assign a float value to T, you have to declare that this operation is possible, e.g. by adding f32: Into<T>, and using 180f32.into().

I get datatype, but what is the point of defining types in sml?

It seems like defining types in SML isnt that helpful:
type point = int * int
val origin : point = (0, 0)
But I could easily just use int * int for typing methods, no? Compared with datatype, with which it seems you can do more interesting things like:
datatype Point = PlanePoint of (int * int) | SpacePoint of (int * int * int)
val origin : Point = SpacePoint(0, 0, 0)
Out of curiosity, what are situations where you really just gotta have a type defined?
The reason is mostly type safety. I will try to explain with a simple example.
Say you have a module that uses 2 types that are represented with real * real
For example, a 2d point like in your example, and a line represented by a slope and a y intercept. Now if you're writing a function like lies_on_line which takes a a point and a line and returns a boolean whether the point lies on the line you have 2 choices for a signature:
val lies_on_line : (int * int) * (int * int) -> bool
Ord
val lies_on_line : point * line -> bool
It's obvious that the 2nd example makes it harder to make mistakes.
Also, while it's more of a benefit for modules, naming a type allows you to change its representation without changing code that uses the type (indirectly through the module).
It makes sense to define aliases for your types in the context of your problem domain. That way you can think in your design in terms of more relevant and meaningful types.
For instance if you are writing a word processor program then you have types like:
type Word = string
type Sentence = Word list
which may make more sense than string and string list.