In a paket.dependencies file, what is the meaning of the operator `==`? - paket

In a project's paket.dependencies file, I found thoses lines:
nuget Microsoft.AspNet.Mvc == 5.2.6
nuget Microsoft.AspNet.Razor == 3.2.6
nuget Microsoft.AspNet.WebPages == 3.2.6
I checked the official documentation without success.
My guess would be that == could fix a version number but to achieve this we can directly write nuget Microsoft.AspNet.Mvc 5.2.6.
What is the meaning of the operator ==?

It's called the "Use exactly this version" constraint. It really should be part of the paket.dependencies reference but instead it is found in: https://fsprojects.github.io/Paket/nuget-dependencies.html
I'll try to explain it with an example. Imagine that you depend on packages A & B.
Both A and B depend on C but in their respective nuget package dependency declaration they specify that:
A depend on C version >= 1.2.3 but < 2.0
B depend on C version >= 2.0
In this situation paket will fail to find a common version of C that suits both A and B.
I've seen cases in some projects where there is a dependency to a package like A that claims it won't work with versions >= 2.0 of package C. However when actually tested, A works just fine with the highest version of C. Therefore a line to force paket to override the version constraint A have on C can be added:
nuget C == 2.0
Of course, the long term solution is to ask the maintainer of A to update their nuget dependency declaration.

Paket is an Open Source project. Lets dig the source. The paket.dependencies file parse is available on GitHub. Here is the logic:
match splitVersion text with
| "==", version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.OverrideAll v,parsePrerelease [v] rest)
| ">=", version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.Minimum v,parsePrerelease [v] rest)
| ">", version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.GreaterThan v,parsePrerelease [v] rest)
| "<", version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.LessThan v,parsePrerelease [v] rest)
| "<=", version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.Maximum v,parsePrerelease [v] rest)
| "~>", minimum :: rest ->
let v1 = SemVer.Parse minimum
VersionRequirement(VersionRange.Between(minimum,twiddle v1),parsePrerelease [v1] rest)
| _, version :: rest ->
let v = SemVer.Parse version
VersionRequirement(VersionRange.Specific v,parsePrerelease [v] rest)
| _ -> failwithf "could not parse version range \"%s\"" text
source
So == will set the VersionRange to OverrideAll. This will have an impact on IsGlobalOverride.
member x.IsGlobalOverride =
match x with
| OverrideAll _ -> true
| _ -> false
source
To conclude == will override the package at the given version, when without, the current package at the given version will be used. This is a rough understanding, please and any thorough answer beside.

Related

How to list files of a given extension in OCaml

I want to retrieve the list of direct files (i.e. no recursive search) of a given directory and a given extension in OCaml.
I tried the following but:
It does not look OCaml-spirit
It does not work (error of import)
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun x -> Str.last_chars x 4 = ".osc2") (Array.to_list list_files)
I got the error (I am using OCamlPro):
Required module `Str' is unavailable
Thanks
You can use Filename.extension instead of Str.last_chars:
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun x -> Filename.extension x = ".osc2") (Array.to_list list_files)
and then use the pipe operator to make it a bit more readable:
let list_osc2 =
Sys.readdir "tests/osc2/expected/pp"
|> Array.to_list
|> List.filter (fun x -> Filename.extension x = "osc2")
I don't know how you expect this to work in OCamlPro though, as it doesn't have a filesystem as far as I'm aware.
To use the Str module, you need to link with the str library. For example, with ocamlc, you need to pass str.cma, and with ocamlopt, you need to pass str.cmxa. I don't know how to do that with OcamlPro.
In any case, Str.last_chars is not particularly useful here. It doesn't work if the file name is shorter than the suffix. By the way, your code would never match because ".osc2" is 5 characters, which is never equal to last_chars x 4.
The Filename module from the standard library has functions to extract and check a file's extension. You don't need to do any string manipulation.
I don't know what you consider “ugly as hell”, but apart from the mistake with string manipulation, I don't see any problem with your code. Enumerating the matches and filtering them is perfectly idiomatic.
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun name -> check_suffix name ".osc2") (Array.to_list list_files)

How to sort a list using Jane Core?

I'm trying to achieve this
open Core
let%test _ = List.sort ~cmp:Int.compare [1;2;3] = [1;2;3]
But it fails with
61 | let%test _ = List.sort ~cmp:Int.compare [1;2;3] = [1;2;3]
^^^^^^^^^^^
Error: The function applied to this argument has type
compare:('a -> 'a -> int) -> 'a list
This argument cannot be applied with label ~cmp
Okay I find out. The problem was that googling for ocaml core list lead me to outdated docs. The label name is ~compare
So this works
let%test _ = List.sort ~compare:Int.compare [1;2;3] = [1;2;3]
The latest docs: https://ocaml.janestreet.com/ocaml-core/latest/doc/ (this may not be what you're searching, you can find other versions at https://ocaml.janestreet.com/ocaml-core/)
The Janestreet Core library is changing its interface with time. The old name of the keyword parameter was cmp and it was changed to compare for the consistency with the other parts of the library,
let%test _ = List.sort ~compare:Int.compare [1;2;3] = [1;2;3]
The latest docs: https://ocaml.janestreet.com/ocaml-core/latest/doc/
Older versions could be found here: https://ocaml.janestreet.com/ocaml-core/
(this may not be what you're searching, you can find other versions at )

Haskell: how to make a list of files and a list of directories out of one common list

This is a newbie question. Suppose I want to separate a list of files and directories into a list of files and a list of directories:
getFilesAndDirs :: [FilePath] -> ([FilePath], [FilePath])
getFilesAndDirs paths =
let ...
in (dirs, files)
Probably this is a hopeless duplicate, I just miss the right keywords.
What is the right way to do (and call) this?
The files and the directories occur randomly.
The Data.List package has the partition :: (a -> Bool) -> [a] -> ([a],[a]) function which splits a list of as into a tuple of two lists of as based on a predicate.
The problem is however that when we check if a file is a directory, we probably will use isDirectory :: FilePath -> IO Bool so we can not directly use this as a predicate (since IO Bool is not equal to Bool).
We can write our own partitionM however, and use that one:
import Data.Bool(bool)
import Data.Foldable(foldrM)
partitionM :: (Foldable t, Monad m) => (a -> m Bool) -> t a -> m ([a], [a])
partitionM p = foldrM (selectM p) ([],[])
selectM :: Monad m => (a -> m Bool) -> a -> ([a], [a]) -> m ([a], [a])
selectM p x (ts,fs) = p x >>= return . bool (ts, x:fs) (x:ts,fs)
we can then use it like:
import System.Directory(isDirectory)
getFilesAndDirs :: [FilePath] -> IO ([FilePath], [FilePath])
getFilesAndDirs = partitionM isDirectory
Note that it is an IO ([FilePath], [FilePath]), since we need to perform I/O to check if a path is indeed a directory (and not a file).
You can use do notation to orchestrate the impure parts of your program, and then use the built-in (pure) functions like partition to do the actual work. Here's an example:
module Q47755054 (getFilesAndDirs) where
import Data.List (partition)
import Data.Bifunctor (bimap)
import System.Directory (doesDirectoryExist)
tagPath :: FilePath -> IO (FilePath, Bool)
tagPath path = do
isDirectory <- doesDirectoryExist path
return (path, isDirectory)
getFilesAndDirs :: [FilePath] -> IO ([FilePath], [FilePath])
getFilesAndDirs paths = do
taggedPaths <- mapM tagPath paths
return $ bimap (fmap fst) (fmap fst) $ partition snd taggedPaths
Notice that this uses the built-in mapM function to get an impure list of values (IO [(FilePath, Bool)]), but due to the do syntax and the <- binding, taggedPaths 'looks' like a pure value ([(FilePath, Bool)]), and therefore you can pass it to partition.
Notice, additionally, that tagPath is just a module-level helper function that isn't exported by the module.
module SeparateFiles where
import Data.String
import System.FilePath.Posix
type Path = FilePath
getFilesAndDirs :: Path -> [(Path,Path)]
getFilesAndDirs path = [splitFileName path]
I understand that you want to split your FilePath extracting into a file and directory. I provide you a very short example.

OCaml - Creating a function which prompts for floats and returns a list of floats

I'm teaching myself OCaml and I sometimes need to create a function where I'm not really sure what the proper solution should be. Here's one that I'm a little confused about.
I need a function that will prompt the user for individual float values and return everything entered in a float list. I can create this function but I'm not sure if its the proper/best way to do it in Ocaml.
Here's my attempt.
let rec get_floats() =
match
(
try Some(read_float())
with
| float_of_string -> None
)
with
| None -> []
| Some s -> s :: get_floats();;
This code works buts I'm at a loss deciding if its a 'proper OCaml' solution. Note, to exit the function and return the float list just enter a non-integer value.
(I hope that) this is a simple peephole rewrite involving no thought whatsoever of the function in your question:
let rec get_floats() =
try
let f = read_float() in (* as suggested by Martin Jambon *)
f :: (get_floats())
with
| float_of_string -> []
The idea I tried to apply here is that you do not need to convert the success/failure of read_float into an option that you immediately match: just do what you have to do with the value read, and let the with handle the failure case.
Now that I think of it, I should point out that in both your question and my rewrite, float_of_string is a fresh variable. If you meant to match a specific exception, you failed at it: all exception constructors, like datatype constructors, are Capitalized. You might as well have written with _ -> instead of with float_of_string ->, and a recent version of OCaml with all warnings active should tell you that your function (or mine) binds a variable float_of_string without ever using it.
Thanks everyone for the help. This works.
let rec get_floats() =
try
let x = read_float() in
x :: get_floats()
with
| _ -> [];;
List.iter (fun x -> print_endline(string_of_float x)) (get_floats());;

Selecting item from list in mathematica

I have a big list of rules in Mathematica, but I want to select the item that corresponds to certain criteria. Although I've been trying to use the Select and Take commands, I have been unable to get the desired output..
Example: Suppose I want to select the item from the list where A->1.2.
list={{A->1,B->2.1,C->5.2},{A->1.1,B->2.6,C->5.5},{A->1.2,B->2.7,C->5.7},{A->1.3,B->2.9,C->6.1}};
The desired output would be
{A->1.2,B->2.7,C->5.7}
I know it is possible to select items from lists, based on their value. But how do I do it from a list of rules?
Thanks
EDIT: apparently, Cases does the trick:
Cases[list, {A-> # | A-> Rationalize[#],
Rule[_, _] ..}] & /# {1.2}
This also searches for numbers in rational and non-rational form, which was another problem I found.
One possibility is to use Select
For example
Select[mylist, MemberQ[#, A -> 1] &]
gives
(* {{A -> 1, B -> 2.1, C -> 5.2}}*)
Other examples;
Select[mylist, MemberQ[#, A -> 1.1 | 1.2] &]
Select[mylist,
MemberQ[#, A -> 1.1 | 1.2 | 1.3] && FreeQ[#, C -> 6.1] &]
An alternative:
Select[list, A == 1.2 /. # &]
The advantage of this solution is that it uses Equal instead of MatchQ (or equivalent). 1.2 == 6/5 gives True (comparison in the mathematical sense) while MatchQ[1.2, 6/5] gives False (structural comparison). Of course it's always possible to do MatchQ[1.2, x_ /; x == 6/5] to work around this.
Also, this solution ignores the order of rules in the lists.
Or use Cases:
Cases[list, {A -> 1.2, ___}]
Another one:
Pick[#, A /. #, 1.2]& # list
"The desired output would be {A->1.2,B->2.7,C->5.7}"
So the above answers should be flattened :)
Cases[N#mylist, {___, A -> 1.2, ___}] // Flatten
Use N to translate things like 6/5 into 1.2.