I there a good way to antiquote a value directly to a set?
In Nix, we can use antiquotation to select an attribute based on a variable:
let
x = { a = "V" ; };
sel = "a";
in
x."${sel}"
result> "V"
But what if instead, we want to select the set, x, based on the antiquotation?
let
x = { a = "V" ; };
sel = "x";
in
"${sel}".a
result> (paraphrased) error: Expected a set but received a string.
Nix complains that it tried to retrieve attribute a from a set, but it wasn't given a set (x), it was given a string ("x"). I understand that we wouldn't want to generally coerce a string "x" into the in-scope value, x, but it seems weird to me that Nix wouldn't in this case where we are treating it specifically as a set. But I digress...
Anyway, I'd appreciate a demonstration of a simple pattern to overcome this problem. Or, better yet, a reusable construct such as (toSet sel).a that works as expected. Thanks!
If I understand correctly, you want to use a variable to pick another variable from the current scope.
The syntax you're using is for string interpolation, which will only ever return a string.
As far as I know, Nix does not provide a way to dynamically access the scope in such a way.
I don't expect that such a feature will be implemented, because such a construct seems quite fragile. Adding it to the language will make the language harder to reason about because it will be hard to tell whether a variable is used, or whether a string interpolation actually returns a string.
It's probably best to put all the things you might want sel to point to in a single attribute set. This will make the intent of the code clear to the reader.
let
selectables = {
x = { a = "V"; };
y = { a = "W"; };
};
selector = "x";
in
selectables.${selector}.a # the quotes weren't necessary
Related
Consider this F# code:
let isSalary employee =
let (fName,lName,Occupation,Department,SalaryType,
HoursPerWeek, AnnualSalary, HourlyWage
) = employee
SalaryType = "Salary"
if(employee.SalaryType = SalaryType) then
true
else
false
Im getting errors in here, any fixes to it?
First things first, please post error messages and a much more specific question. Thanks! But luckily, I can about deduce the error messages from this problem.
Next, if you want to mutate SalaryType after you've deconstructed your employee 8-tuple, you should write using the mutable keyword:
let mutable (fName, lName, Occupation, Department, SalaryType,
HoursPerWeek, AnnualSalary, HourlyWage) = employee
But you shouldn't. This is explained further below.
Next problem: there is no dot notation (no tuple.member) for accessing members of a tuple. It's only possible through deconstruction. So you can't employee.SalaryType.
Here's what looks to be the crux of the problem, and it's a mistake I made many times when I was learning functional programming, and it's a difficult paradigm shift to adapt to. You should not be attempting to mutate data, or in this case, variables. Variables, or values as they are called in F#, shouldn't change, as a broad rule. Functions should be pure.
What this means is that any parameters you pass into a function should not change after leaving the function. The parameter employee should be the same after you return to the calling scope.
There's a few syntactical errors you've made that make it pretty much impossible for me to deduce what you're trying to do in the first place. Please include this in the question.
Also, one last nitpick. As you know, the last expression in an F# function is it's return value. Instead of using an if statement, just return the condition you're testing, like this:
let ...
...
employee.SalaryType = SalaryType <- but remember, you can't use dot notation on tuples; this is just an example
Please read more on
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/
I just wanna know about this functionalities and what's effects if we don't use this on every single projects. Thanks for the explanation before.
Example:
int number = 2;
bool isTrue = true;
double floatNumber = 2.1;
Why we not use like this?
var number = 2;
var isTrue = true;
const floatNumber = 2.1;
There are various related Dart style guide rules
PREFER type annotating public fields and top-level variables if the type isn’t obvious.
CONSIDER type annotating private fields and top-level variables if the type isn’t obvious.
AVOID type annotating initialized local variables.
DO annotate when Dart infers the wrong type.
So for example for local variables the style guide even suggests to omit type annotations. The scope of the type annotations is limited to the function/method so the risk is low that inferred types can cause confusion.
For other situations the style guides suggests to add type annotations to avoid ambiguity.
There was a recent addition to Dart that allows to use integer literals to initialize double variables. This only works if the type annotation is added.
var val = 1;
print(val);
1
double val = 1;
print(val);
1.0
This example isn't too practical, because the feature is mostly used to pass literal double values to function/method/constructor parameters, but it demonstrates that the context is important for the decision when to explicitly specify the type using type annotations and when it is safe to omit.
There are also various linter rules that help to stay consistent.
https://pub.dartlang.org/packages/linter
https://dart-lang.github.io/linter/lints/
Is there a way to substitute the comparison of string fields in a F# record class to be case-insensitive without having to take full custom control of equality/comparison?
Subtracting Records from a Set using case-insensitive comparison is the closest I have found to an answer.
If you want to do it in a clean way, I would suggest introducing a wrapper type for case insensitive strings. That way you can have the notion of case insensitive comparisons reflected in the types, and don't have to change the default structural comparisons on the records.
[<CustomEquality; CustomComparison>]
type CIString =
| CI of string
override x.Equals y = ...
override x.GetHashCode() = ...
interface System.IComparable with
member x.CompareTo y = ...
I left out the implementation of the methods - there's nothing fancy there, just use ToUpperInvariant on the nested string whenever you access it.
Then you can modify your records like this:
type OldRecord = { field : string }
type NewRecord = { field : CIString }
and comparisons on the new type should show that { field = "TEST" } = { field = "test" }.
The other solution I suggested (reflection-based) would be easy to put in place for a simple case, but it's dodgy. Making it work in a sensible way for all the possible cases is a non-trivial exercise, if you can even establish what "sensible way" means here.
I have an object that can be neatly described by a discriminated union. The tree that it represents has some properties that can be easily updated when the tree is modified (but remaining immutable) but that are relatively expensive to recalculate.
I would like to store those properties along with the object as cached values but I don't want to put them into each of the discriminated union cases so I figured a member variable would fit here.
The question is then, how do I change the member value (when I modify the tree) without mutating the actual object? I know I could modify the tree and then mutate that copy without ruining purity but that seems like a wrong way to go about it to me. It would make sense to me if there was some predefined way to change a property but so that the result of the operation is a new object with that property changed.
To clarify, when I say modify I mean doing it in a functional way. Like (::) "appends" to the beginning of a list. I'm not sure what the correct terminology is here.
F# actually has syntax for copy and update records.
The syntax looks like this:
let myRecord3 = { myRecord2 with Y = 100; Z = 2 }
(example from the MSDN records page - http://msdn.microsoft.com/en-us/library/dd233184.aspx).
This allows the record type to be immutable, and for large parts of it to be preserved, whilst only a small part is updated.
The cleanest way to go about it would really be to carry the 'cached' value attached to the DU (as part of the case) in one way or another. I could think of several ways to implement this, I'll just give you one, where there are separate cases for the cached and non-cached modes:
type Fraction =
| Frac of int * int
| CachedFrac of (int * int) * decimal
member this.AsFrac =
match this with
| Frac _ -> this
| CachedFrac (tup, _) -> Frac tup
An entirely different option would be to keep the cached values in a separate dictionary, this is something that makes sense if all you want to do is save some time recalculating them.
module FracCache =
let cache = System.Collections.Generic.Dictionary<Fraction, decimal>()
let modify (oldFrac: Fraction) (newFrac: Fraction) =
cache.[newFrac] <- cache.[oldFrac] + 1 // need to check if oldFrac has a cached value as well.
Basically what memoize would give you plus you have more control over it.
Any way to declare a new variable in F# without assigning a value to it?
See Aidan's comment.
If you insist, you can do this:
let mutable x = Unchecked.defaultof<int>
This will assign the absolute zero value (0 for numeric types, null for reference types, struct-zero for value types).
It would be interesting to know why the author needs this in F# (simple example of intended use would suffice).
But I guess one of the common cases when you may use uninitialised variable in C# is when you call a function with out parameter:
TResult Foo<TKey, TResult>(IDictionary<TKey, TResult> dictionary, TKey key)
{
TResult value;
if (dictionary.TryGetValue(key, out value))
{
return value;
}
else
{
throw new ApplicationException("Not found");
}
}
Luckily in F# you can handle this situation using much nicer syntax:
let foo (dict : IDictionary<_,_>) key =
match dict.TryGetValue(key) with
| (true, value) -> value
| (false, _) -> raise <| ApplicationException("Not Found")
You can also use explicit field syntax:
type T =
val mutable x : int
I agree with everyone who has said "don't do it". However, if you are convinced that you are in a case where it really is necessary, you can do this:
let mutable naughty : int option = None
...then later to assign a value.
naughty <- Some(1)
But bear in mind that everyone who has said 'change your approach instead' is probably right. I code in F# full time and I've never had to declare an unassigned 'variable'.
Another point: although you say it wasn't your choice to use F#, I predict you'll soon consider yourself lucky to be using it!
F# variables are by default immutable, so you can't assign a value later. Therefore declaring them without an initial value makes them quite useless, and as such there is no mechanism to do so.
Arguably, a mutable variable declaration could be declared without an initial value and still be useful (it could acquire an initial default like C# variables do), but F#'s syntax does not support this. I would guess this is for consistency and because mutable variable slots are not idiomatic F# so there's little incentive to make special cases to support them.