How to get the name of the originally ran file in Julia - julia

I'd like to create a log file which is named after the originally run Julia file, for example here julia foo.jl I'd want foo.jl. From within a Julia session how can I get this information>

The global constant PROGRAM_FILE is set to the script name.

This can be done by inspecting the stack
# first get the top of the stack
f = stacktrace()[1]
# then get the file's name as a string, note the is absolute.
abs_filename = String(f.file)
println(abs_filename)
# to get only the filename use
println(basename(abs_filename))

Related

Avoid restarting julia REPL everytime you make an ammendment to a function

I am working on a julia code where I have several files and call functions from these files to a main function called run.jl. Every time I make changes to any one of these files I need to restart the julia REPL which is a bit annoying. Anyway to work around this.
For example
# --------------------------------- run.jl
include("agent_types.jl")
include("resc_funcs.jl")
using .AgentTypes: Cas, Resc
using .RescFuncs: update_rescuers_at_pma!, travel_to_loc
# ... some code
for i = 1:500
update_rescuers_at_pma!(model)
travel_to_loc(model)
end
# ------------------------------ resc_funcs.jl
function travel_to_loc(model)
println(get_resc_by_prop(model, :on_way_to_iz))
for resc_id in get_resc_by_prop(model,:on_way_to_iz)
push!(model[resc_id].dist_traject, model[resc_id].dist_to_agent) #This is just for checking purposes
model[resc_id].dist_to_agent -= model.dist_per_step
push!(model[resc_id].loc_traject, "on_way_to_iz")
end
#If we add new print statement here and execute run.jl it wont print
println(model[resc_id].loc_traject) #new amendment to code
end
But now when I go and update travel_to_loc function for example. I need to restart the julia repl before those changes are reflected. I am wondering if there is a way after you save the file (resc_funcs.jl in this case) those amendments are reflected when you execute run.jl.
The simplest workflow could be the following:
Select some folder to be your current working folder in Julia (eg. by using cd() command from Julia)
Create sample file MyMod.jl
module MyMod
export f1
function f1(x)
x+1
end
end
Add the current folder to LOAD_PATH and load Revise.jl
push!(LOAD_PATH, ".")
using Revise
Load the module and test it:
julia> using MyMod
[ Info: Precompiling MyMod [top-level]
julia> f1(3)
4
Try to edit the file eg. change x+1 to x+3
Run again
julia> f1(3)
6
Notes:
you will still need to restart REPL when your data structures change (you modify a definition of a struct object)
you could generate a full module package using Pkg.generate but I wanted to make things simplified.

how to pass an argument as a variable name in R

I need help with passing an argument as a variable name in an R script from the terminal. I'll run the script as follows:
R < script.R --args "hello"
And, in the script there should be something like this:
args <- commandArgs(trailingOnly = TRUE)
assign(args[1],24)
save(args[1], file="output.RData")
But, I need to take the argument as the variable name. What I mean is the following: If I run the script with "numbers" argument, the variable name inside the script should be numbers.
assign(args[1], 24)
does the trick. But, inside the save function, args[1] does not work. How can I pass it as a variable name?
Does it work if you try
saveRDS(get(args[1]),file="output.rds")
?
You won't get a text file with the save function. If you want its text version you would need to use `dump". This would "work" despirte the extention. The file ois still an .Rdata file event without the extension:
arg=1
argname="reports"
assign(argname, arg)
reports
#[1] 1
save(reports, file="test.txt")
rm(reports)
rm(argname)
rm(arg)
load("test.txt")
To use dump:
dump('reports', file="test2.txt")
This would appear in that file. It should be parse-able (and readable to humans) R code:
reports <-
1

Windows batch script - parse and expand the variable to pass as a string to external program?

I want to use a relative file path as a command line argument but as the example and assessment below will demonstrate, the variable passes \..\ as a string, it doesn't evaluate it.
Can I can force the command line to parse and expand the variable as a string?
: For example: I have a R script file I want to launch from the command line:
Set RPath=C:\Program Files\R\R-3.1.0\bin\Rscript.exe
SET RScript=%CD%\..\..\HCF_v9.R
SET SourceFile=%CD%\..\Source\
ECHO String used for Source Location - %SourceFile%
"%RPath%" "%RScript%" %SourceFile%
The inclusion of \..\ works in the call to R as an external program because the batch file can resolve it's own commands.
The variable of SourceFile however doesn't work because the SourceFile variable hasn't expanded \..\, it has just included it as part of the string and R can't process \..\
You can use the for replaceable parameters to resolve to the real path
for %%a in ("..\..\HCF_v9.R") do set "RScript=%%~fa"
#MC ND has provided the batch file approach; an R-centric approach would be to pass the current directory to R, and modify it there.
; batch file
Set RPath=C:\Program Files\R\R-3.1.0\bin\Rscript.exe
SET RScript=%CD%\..\..\HCF_v9.R
"%RPath%" "%RScript%" %CD%
# in R
srcpath <- commandArgs(TRUE)[1]
srcpath <- normalizePath(file.path(srcpath, "../Source"))

Standard ML / NJ: Loading in file of functions

I'm trying to write a bunch of functions in an SML file and then load them into the interpreter. I've been googling and came across this:
http://www.smlnj.org/doc/interact.html
Which has this section:
Loading ML source text from a file
The function use: string -> unit interprets its argument as a file name relative to sml's current directory and loads the text from that file as though it had been typed in. This should normally be executed at top level, but the loaded files can also contain calls of use to recursively load other files.
So I have a test.sml file in my current directory. I run sml, all good so far. Then I try use test.sml; and I get:
stdIn:1.6-1.14 Error: unbound structure: test in path test.sml
Not sure why this isn't working. Any ideas?
Thanks,
bclayman
As you mentioned, the function use has type string -> unit. This means it takes a string and returns unit. When you do use test.sml, you are not giving it a string. You need to do use "test.sml" (notice the quotes)

How to create a new output file in R if a file with that name already exists?

I am trying to run an R-script file using windows task scheduler that runs it every two hours. What I am trying to do is gather some tweets through Twitter API and run a sentiment analysis that produces two graphs and saves it in a directory. The problem is, when the script is run again it replaces the already existing files with that name in the directory.
As an example, when I used the pdf("file") function, it ran fine for the first time as no file with that name already existED in the directory. Problem is I want the R-script to be running every other hour. So, I need some solution that creates a new file in the directory instead of replacing that file. Just like what happens when a file is downloaded multiple times from Google Chrome.
I'd just time-stamp the file name.
> filename = paste("output-",now(),sep="")
> filename
[1] "output-2014-08-21 16:02:45"
Use any of the standard date formatting functions to customise to taste - maybe you don't want spaces and colons in your file names:
> filename = paste("output-",format(Sys.time(), "%a-%b-%d-%H-%M-%S-%Y"),sep="")
> filename
[1] "output-Thu-Aug-21-16-03-30-2014"
If you want the behaviour of adding a number to the file name, then something like this:
serialNext = function(prefix){
if(!file.exists(prefix)){return(prefix)}
i=1
repeat {
f = paste(prefix,i,sep=".")
if(!file.exists(f)){return(f)}
i=i+1
}
}
Usage. First, "foo" doesn't exist, so it returns "foo":
> serialNext("foo")
[1] "foo"
Write a file called "foo":
> cat("fnord",file="foo")
Now it returns "foo.1":
> serialNext("foo")
[1] "foo.1"
Create that, then it returns "foo.2" and so on...
> cat("fnord",file="foo.1")
> serialNext("foo")
[1] "foo.2"
This kind of thing can break if more than one process might be writing a new file though - if both processes check at the same time there's a window of opportunity where both processes don't see "foo.2" and think they can both create it. The same thing will happen with timestamps if you have two processes trying to write new files at the same time.
Both these issues can be resolved by generating a random UUID and pasting that on the filename, otherwise you need something that's atomic at the operating system level.
But for a twice-hourly job I reckon a timestamp down to minutes is probably enough.
See ?files for file manipulation functions. You can check if file exists with file.exists, and then either rename the existing file, or create a different name for the new one.

Resources