I'm new to F# - In nodejs - it's possible to extract & enumerate an objects properties. Is it possible to get this data in F#?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
for (const [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}
Related
What's the time complexity of converting a String into an Array in Swift, aka: Array("abc").
Is it O(n) or Swift uses some type of internal mechanism to optimize it as String conforms to Sequence protocol.
You're right to think about this in terms of the Sequence protocol. But Sequence is actually very simple in terms of requirements, and doesn't offer a way to do better than O(n) — the iterator mechanism is described in IteratorProtocol's documentation.
The key pieces of source, to see this in action, are found here:
https://github.com/apple/swift/blob/main/stdlib/public/core/Array.swift
#inlinable
public init<S: Sequence>(_ s: S) where S.Element == Element {
self = Array(
_buffer: _Buffer(
_buffer: s._copyToContiguousArray()._buffer,
shiftedToStartIndex: 0))
}
https://github.com/apple/swift/blob/main/stdlib/public/core/ContiguousArrayBuffer.swift (for _copyToContiguousArray)
// Add elements up to the initial capacity without checking for regrowth.
for _ in 0..<initialCapacity {
builder.addWithExistingCapacity(iterator.next()!)
}
// Add remaining elements, if any.
while let element = iterator.next() {
builder.add(element)
}
How do I convert a C# tuple into an F# tuple?
Specifically, I have a C# implementation of a Result type:
public class Result<T,E>
{
public Result(T data) => Ok = (true,data);
public Result(E data) => Error = (true,data);
public (bool,T) Ok { get; }
public (bool,E) Error { get; }
}
I want to take the tuple value of an Ok result or Error result and use it in my F# code.
Example:
let result = databaseService.getSomething(userIdValue) |> Async.AwaitTask |> Async.RunSynchronously
let isSuccessful,forms = result.Ok
However, I receive the following error:
Error FS0001 One tuple type is a struct tuple, the other is a
reference tuple
In conclusion, I am confused on how to convert a C# tuple into an F# tuple.
I found this link. But I wasn't able to leverage it for what I needed.
C# 7.0 tuple syntax produces ValueTuple values which are different from F# tuples (the older Tuple classes).
Luckilly since F# 4.1 you can use
let struct (isSuccessful, forms) = result.Ok
Notice the extra struct keyword in the pattern. You can use the same syntax to create new ValueTuple values, like let tup = struct (true, 42)
seq{
for bit in BitArray(10) do
yield bit
}
bit is of bool type. I checked with ILSpy and there's an explicit cast added in one of closures generated.
BitArray implements only plain (not generic) IEnumerable. How does F# know that it's a bool?
According to the F# 4.1 specification's Section 6.5.6 Sequence Iteration Expressions, F# does casting even for a non-generic IEnumerable if the IEnumerable has an Item property with a non-object type (highlighting mine):
An expression of the following form is a sequence iteration
expression:
for pat in expr1 do expr2 done
The type of pat is the same as the return type of the Current property on the enumerator value. However,
if the Current property has return type obj and the collection type ty
has an Item property with a more specific (non-object) return type
ty2, type ty2 is used instead, and a dynamic cast is inserted to
convert v.Current to ty2.
If we look at the source code for BitArray, we see that it does indeed have an Item property with type bool:
public bool this[int index] {
get {
return Get(index);
}
set {
Set(index,value);
}
}
Thus, F# will explicitly cast to bool while iterating.
I have a question.
When working with Dart, I can't check to see if 2 arrays are equal.
(in other languages, I can do with ==)
In fact, I just can do that == with String or number.
List arr1 = [1,2,3];
List arr2 = [1,2,3];
if (arr1 == arr2) {
print("equal");
} else {
print("not equal");
}
// Output: not equal.
So I wonder how does that make sense. I mean, How we can do if the == is just work for the cases of String or number (if the values compared are the same).
How do I have to do if I want to check that kind of comparison (equal) for List, Map, ..
It just work for String & number.
arr1 and arr2 are different instances of an object of type List. By default different instances are always different.
When a class implements a custom == operator it can override this behavior. Some classes have a custom implementation by default like int and String.
This can easily be done for immutable objects but not for mutable. One reason is that usually the hashCode is calculated from the values stroed in a class and the hashCode must not change for an instance because this can for example cause that an instance stored in a map can't be retrieved anymore when the hashcode of the key changed.
As a workaround there is a library that provides helper functions to compare lists/iterables.
import 'package:collection/equality.dart';
void main(List<String> args) {
if (const IterableEquality().equals([1,2,3],[1,2,3])) {
// if (const SetEquality().equals([1,2,3].toSet(),[1,2,3].toSet())) {
print("Equal");
} else {
print("Not equal");
}
}
In Unity3D we are able to make a field accessible inside the editor by marking it as public. This then allows assigning the field's variable in the GUI instead of hard-coding it. This C# code for example will show a "speed" field that can be manually edited during development. It will default to 10 if left unmodified:
public class Example : MonoBehaviour {
public float speed = 10.0F;
}
I tried doing this in F# with automatic properties:
type Example() =
inherit MonoBehaviour()
member val speed = 10.f with get,set
but this doesn't work. It does, however, work if I use explicit properties
[<DefaultValue>] val mutable speed : float32
but this has the drawback of not being able to specify a default value in the same expression.
Aren't explicit and automatic properties compiling down to the same thing, with the only difference being that explicit properties are always initialized to zero? And how can I declare the equivalent of the C# code in F#?
I think you are playing a little loosely with the terms "field" and "property".
The Unity editor doesn't bind properties automatically, and the first example you've provided is F#'s auto-properties. For the record, you couldn't bind the following C# in Unity editor pane either:
// does not bind in editor either
class Example : MonoBehavior {
public float speed { get; set; }
}
You have to use the code with [DefaultValue] and just initalize it in the constructor or alternatively have a let-bound private field that is tagged [SerializeField] and write your own property wrapper:
type Example () =
[<SerializeField>]
let mutable _speed = 10f
member this.speed
with get () = _speed
and set val = _speed <- val
I think you're confusing two different concepts: explicit fields and auto-properties. Under the hood, a property is more like a method than a field, although access/assignment are syntactically similar. The F# equivalent of your C# would be:
type Example() as this =
[<DefaultValue>] val mutable public speed: float32;
do this.speed <- 10.0f
Another way to implement this, which avoids the [<DefaultValue>] and imperative initialization, would be as follows (note the absence of default constructor on the first line):
type Example =
val mutable public speed : float32
new() = { speed = 10.0f }