I am using Cleanide for Clean3.0 programming language.
What I am trying to do is to implement a function that receive name of a directory in my system, and return a list of all the files in that directory.
I don't know if the defintion of such function needs to be like File -> [string] or maybe something else, even that directory is a file maybe this is not the developers of Clean meant...
Thank a lot!
This functionality is not available in the StdEnv environment, but there are two libraries that can help with this:
The Directory library contains a module Directory which has a function getDirectoryContents :: !Path !*env -> (!(!DirError, [DirEntry]), !*env) | FileSystem env.
The Platform library contains a module System.Directory which has a function readDirectory :: !FilePath !*w -> (!MaybeOSError [FilePath], !*w).
In both cases the first argument is a path to the directory and the second argument is the *World, which is the typical way of Clean to perform impure operations (see chapter 9 of the language report).
Code examples
With Directory:
import Directory
Start w
# (dir,w) = getDirectoryContents (RelativePath []) w
= dir
With Platform:
import System.Directory
Start w
# (dir,w) = readDirectory "." w
= dir
Related
I have a test.jl Julia script file in a directory, e.g., /home/directory1. Assume that I want to save the output of this code as a .txt file in the same directory. My problem is that, obviously, the .txt file will be saved in the working directory of Julia, which by pwd() is somewhere else, e.g., /home/julia/.
I wonder how can I change the working directory in the test.jl script WITHOUT writting the directory address, /home/directory1 , manually? I know that I can change the working directory by cd("/home/directory1"), but the problem is that I don't want to write the address manually. Is there any way to get the directory address of test.jl within itself by a command?
You can get that information using macro #__FILE__
help?> #__FILE__
#__FILE__ -> AbstractString
Expand to a string with the path to the file containing the macrocall, or an empty string if evaluated by julia -e <expr>. Return nothing if the macro was missing parser source information. Alternatively see PROGRAM_FILE.
Example:
julia> open("c:\\temp\\some.jl","w") do f
println(f, "println(\"Running at \$(#__FILE__)\")")
end
julia> include("c:\\temp\\some.jl")
Running at c:\temp\some.jl
shell> julia "c:\temp\some.jl"
Running at c:\temp\some.jl
Functions like joinpath use the appropriate OS-dependent separator when joining two paths (ie / on Linux, \\ on Windows, etc). How do these functions know what separator to use?
Similarly, the root directory on Linux is /, but on Windows is probably C:\\. Is there a way to retrieve the OS-dependent root directory in Julia?
Note, I've had a look at the joinpath source on github, and it appears to use an undocumented function pathsep(a,b) and a global variable path_separator_re, but I can't see how either of these work.
It uses the Sys.isunix and Sys.iswindows functions in order to conditionally define the correct path_separator_re variables, etc.
https://github.com/JuliaLang/julia/blob/5c3f58039525972b24930f356821af8299f70a26/base/path.jl#L19-L41
if Sys.isunix()
# ...
const path_separator_re = r"/+"
# ...
splitdrive(path::String) = ("",path)
elseif Sys.iswindows()
# ...
const path_separator_re = r"[/\\]+"
# ...
function splitdrive(path::String)
m = match(r"^([^\\]+:|\\\\[^\\]+\\[^\\]+|\\\\\?\\UNC\\[^\\]+\\[^\\]+|\\\\\?\\[^\\]+:|)(.*)$", path)
String(m.captures[1]), String(m.captures[2])
end
else
error("path primitives for this OS need to be defined")
end
For the root directory, check out the homedir function, which uses libuv to determine it.
https://github.com/JuliaLang/julia/blob/5c3f58039525972b24930f356821af8299f70a26/base/path.jl#L52-L77
help?> homedir
search: homedir
homedir() -> AbstractString
Return the current user's home directory.
| Note
|
| homedir determines the home directory via libuv's uv_os_homedir. For details (for example on how to specify the home
| directory via environment variables), see the uv_os_homedir documentation.
I often create some DLLs with Haskell that I load in R, and this works very well.
But I have some code dealing with the xlsx library, I can compile it to a DLL without issue, but when I load the DLL in R, this totally crashes the R session. However this occurs on Windows only, there's no issue on Linux.
I managed to find a minimal example and there's something weird. This is my minimal example:
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE OverloadedStrings #-}
module TestDLL where
import Codec.Xlsx
import Control.Lens
import qualified Data.ByteString.Lazy as L
import Foreign
import Foreign.C
import Foreign.C.String (peekCString, newCString)
test :: IO ()
test = do
bs <- L.readFile "report.xlsx"
let value = toXlsx bs ^? ixSheet "List1" .
ixCell (3,2) . cellValue . _Just
putStrLn $ "Cell B3 contains " ++ show value
... some elementary functions here ...
If I compile this code to a DLL, loading this DLL in R crashes the R session on Windows. There's no such issue if I remove the test function. However the test function is not even exported (with foreign export) and it is not called by the other functions, isn't it weird ? If I don't export this function and if I don't use it, why the DLL deals with this function ?
And more importantly, why the R session crashes when I load the DLL, and how to fix that ?
Edit
I have a more minimal example now. This works:
test :: IO Xlsx
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs
And this crashes:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs ^? ixSheet "List1"
It looks like Windows has a problem with ^?.
Edit 2
No crash with this equivalent code:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
let xlsx = toXlsx bs
let sheets = _xlSheets xlsx
let mapping = DM.fromList sheets
return $ DM.lookup "List1" mapping
Windows has a problem with ^? ixSheet. Now let me try on my real example...
I don't have a solution (edit: I have one, see below) but I can say this is due to the limit of number of exported symbols.
When I compile the code
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
let xlsx = toXlsx bs
let sheets = _xlSheets xlsx
let mapping = DM.fromList sheets
return $ DM.lookup "List1" mapping
and I inspect the DLL with DependencyWalker, I see there are 48318 exported symbols. That's acceptable.
But for the other code:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs ^? ixSheet "List1"
the generated DLL reaches the maximal number of exported symbols: there are 65535=2^16-1 exported symbols. This DLL is "truncated".
Edit: A possible solution !
A possible solution consists in using a def file. In a file MyDef.def, list the functions you want to export, e.g. funexport and HsStart, like this:
EXPORTS
funexport
HsStart
and add MyDef.def at the end of the command line you use to compile:
ghc -shared foo.hs StartEnd.c -o foo.dll MyDef.def
I have just tested this solution and it works. However this is the first time I test it, so I would not guarantee yet. I'm also surprised that ghc does not automatically do that.
I want to use R's mathematical functions as provided in libRmath from Ocaml. I successfully installed the library via brew tap homebrew science && brew install --with-librmath-only r. I end up with a .dylib in /usr/local/lib and a .h in /usr/local/include. Following the Ocaml ctypes tutorial, i do this in utop
#require "ctypes.foreign";;
open Ctypes;;
open Foreign;;
let test_pow = foreign "pow_di" (float #-> int #-> returning float);;
this complains that it can't find the symbol. What am I doing wrong? Do I need to open the dynamic library first? Set some environment variables? After googling, I also did this:
nm -gU /usr/local/lib/libRmath.dylib
which gives a bunch of symbols all with a leading underscore including 00000000000013ff T _R_pow_di. In the header file, pow_di is defined via some #define directive from _R_pow_di. I did try variations of the name like "R_pow_di" etc.
Edit: I tried compiling a simple C program using Rmath using Xcode. After setting the include path manually to include /usr/local/include, Xcode can find the header file Rmath.h. However, inside the header file, there is an include of R_ext/Boolean.h which does not seem to exist. This error is flagged by Xcode and compilation stops.
Noob alert: this may be totally obvious to a C programmer...
In order to use external library you still need to link. There're at least two different ways, either link using compiler, or link even more dynamically using dlopen.
For the first method use the following command (as an initial approximation):
ocamlbuild -pkg ctypes.foreign -lflags -cclib,-lRmath yourapp.native
under premise that your code is put into yourapp.ml file.
The second method is to use ctypes interface to dlopen to open the library. Using the correct types and name for the C function call, this goes like this:
let library = Dl.dlopen ~filename:"libRmath.dylib" ~flags:[]
let test_pow = foreign ~from:library "R_pow_di" (double #-> int #-> returning double)
I wrote
let fact x =
let result = ref 1 in
for i = 1 to x do
result := !result * i;
Printf.printf "%d %d %d\n" x i !result;
done;
!result;;
in a file named "Moduletest.ml", and
val fact : int -> int
in a file named "Moduletest.mli".
But, why don't they work?
When I tried to use in ocaml,
Moduletest.fact 3
it told me:
Error: Reference to undefined global `Moduletest'
What's happening?
Thanks.
OCaml toplevel is linked only with a standard library. There're several options on how to make other code visible to it:
copy-pasting
evaluating from the editor
loading files #use directive
making custom toplevel
loading with ocamlfind
Copy-pasting
This self-describing, you just copy code from some source and paste it into toplevel. Don't forget that toplevel won't evaluate your code until you add ;;
Evaluating from the editor
Where the editor is of course Emacs... Well, indeed it can be any other capable editor, like vim for example. This method is an elaboration of the previous, where the editor is actually responsible for copying and pasting the code for you. In Emacs you can evaluate the whole file with C-c C-b command, or you can narrow it to a selected area with C-c C-r, and the most granular is to use C-c C-e, i.e., evaluate an expression. Although it is slightly buggy.
Loading with #use directive.
This directive accepts a filename, and it will essentially copy and paste the code from the file. Notice, that it won't create a file-module for you/ For example, if you have file test.ml with this contents:
(* file test.ml *)
let sum x y = x + y
then loading it with the #use directive, will actually bring to your scope, sum value:
# #use "test.ml";;
# let z = sum 2 2
You mustn't to qualify sum with Test., because no Test module is actually created. #use directive merely copies the contents of the file to the toplevel. Nothing more.
Making custom toplevels
You can create your own toplevel with your code compiled in. It is an advanced theme, so I will skip it.
Loading libraries with ocamlfind
ocamlfind is a tool that allows you to find and load libraries, installed on your system, into your toplevel. By default, toplevel is not linked with any code except standard library. Even, not all parts of the library are actually linked, e.g., Unix module is not available, and needed to be loaded explicitly. There're primitive directives that can load any library, like #load and #include, but they are not for a casual user, especially if you have excellent ocamlfind at your disposal. Before using it, you need to load it, since it is also not available by default. The following command, will load ocamlfind and add few new directives:
# #use "topfind";;
In a process of loading it will show you a little hint on how to use it. The most interesting directive, that is added is #require. It accepts a library name, and loads (i.e., links) its code into toplevel:
# #require "unix";;
This will load a unix library. If you're not sure, about the name of the library you can always view all libraries with a #list command. The #require directive is clever and it will automatically load all dependencies of the library.
If you do not want to type all this directives every time you start OCaml top-level, then you cam create .ocamlinit file in your home directory, and put them there. This file will be loaded automatically on a top-level startup.
I have tested your code and it looks fine. You should "load" it from the OCaml toplevel (launched from the same directory as your .ml and .mli files) in the following way:
# #use "Moduletest.ml";;
val fact : int -> int = <fun>
# fact 4;;
4 1 1
4 2 2
4 3 6
4 4 24
- : int = 24