Init or main function in Julia - program-entry-point

I've read that global variables have a sensible impact on performance.
In order to avoid them I've put everything inside a init function, as I read here.
Simple example, integer.jl:
function __init__()
n = 0
while n < 2
try
print("Insert an integer bigger than 1: ")
n = parse(Int8,readline(STDIN))
catch Error
println("Error!")
end
end
println(n)
end
When I run julia integer.jl from the command line, nothing happens. function main() doesn't work either.
What should I do to make it work?
(Also, can you correct any errors, non efficient code or non idiomatic syntax?)

The name __init__ is reserved as a name for a function in a module that is automatically run when the module is loaded, so unless that's what you're defining, don't use that name. You can call this function main (which has no special meaning) and then just call it like so:
function main()
# do stuff
end
main()

Related

Get list of variables in the current namespace in Julia

I have a question that is similar to, but different than this one. I have a function within a module, and I would like to see what variables are defined inside the function namespace. In the other post, they said to use varinfo, but that seems to only work in the Main namespace. For example if I run this
module Test
function hello()
a = 1
varinfo()
return a
end
end
import .Test
Test.hello()
I get this error
WARNING: replacing module Test.
ERROR: UndefVarError: varinfo not defined
Is there a way to get a list of variables within a given namespace? What I am looking for is a function that when called, outputs all the available variables (a in my example) as well as available modules within the namespace.
PS. I would like to add, that varinfo is incredibly limiting because its output is a Markdown.MD, which cannot be iterated over. I would prefer a function that outputs variables and values in some sort of list or dictionary if possible.
varinfo is showing only the global variables.
If you want the local variables, you need to use the Base.#locals macro:
module Test
function hello()
a = 1
println(Base.#locals)
return a
end
end
And now you can do:
julia> Test.hello()
Dict{Symbol, Any}(:a => 1)
1
Is this what you want?
module Test
function hello()
a = 1
println(Main.varinfo(#__MODULE__; all=true, imported=true))
return a
end
end

Evaluate a local variable inside a Julia macro

I'm writing a Julia macro that takes an expression and serializes it, so that I can run it somewhere else. The macro therefore takes the expression and replaces all symbols with variables. The expression is then serialized and evaluated somewhere else.
My problem is related to evaluating variables that are not in the global scope. I.e. the following works fine, as a is defined in the global scope:
macro myprintf(ex)
print(eval(ex))
end
# works
a = 2
#myprintf a
This throws an error as the macro doesn't see a, which is defined in the local scope of the loop (run in a new session):
macro myprintf(ex)
print(eval(ex))
end
# UndefVarError: a not defined
for j=1:3
a = 2
#myprintf a
end
Is there any way I can access a inside the macro if it is defined in a local scope such as a loop? I'm aware that I'm not necessarily using macros as intended as I am calling eval on the expression inside the macro definition. The overall idea is that I want to serialize the expression that's passed to the macro and evaluate it somewhere else later (e.g. in a different Julia session).
eval only works in global scope. But then I don't see how much use there is in replacing the variables by evaluated literals, resulting in an expression of literals.
Anyway, a different approach to the original problem could be mimick what R does: constructing thunks out of an expression plus its environment at the place where it was called. To recreate that in Julia, you'd have to
Figure out the free variables in the expression
Create an environment data structure of their values
Wrap the original expression in a closure such that it takes the local variables from the environment
Put everything into a new object
Example:
for j=1:3
a = 2
#saveexpr a + 2
end
should expand to something like
for j=1:3
a = 2
SerializedExpr(
(; a),
function (env)
let (a,) = env
a + 2
end
end,
:(a + 2))
end
If saving the closure is not feasible in your use case, I guess you have to either implement your own evaluator, or use something like JuliaInterpreter.jl.

Externally declared (global) variable in Fortran

I want to know if it's possible to declare a variable and have declaration carry over to another subroutine or program (hence become global)
For example
program main
implicit none
call mysub
print *, x
end program main
subroutine mysub
implicit none
integer, parameter :: x = 1
end subroutine mysub
Would print "1"
Is this possible? I want to do this because a program I'm working on has large sets of variables that I would rather avoid copying unless necessary.
The most straightforward way to do this in modern Fortran is with modules.
Consider
module globals
implicit none
integer :: x
end module globals
program main
use globals
implicit none
call mysub
print *,x
end program main
subroutine mysub
use globals
implicit none
x = 1
end subroutine mysub
In this paradigm you specify your "global" variables within the module and use that module everywhere you want access to them.
If you are just using this to declare contants (parameters) you can simplify this to:
module globals
implicit none
integer, parameter :: x=1
end module globals
program main
use globals
implicit none
print *,x
end program main
The older method to accomplish this involved common blocks and includeing files that declared them every procedure that accessed them. If you find a tutorial dealing with the common block method I advise you to ignore them and avoid their use in new code.

Julia: Variable not defined

The variable scope behavior seems quite strange. The code block
tp = 1
function test2()
println(tp)
end
works perfectly well while
function test()
if tp==0
tp=tp-1
end
end
gives the exception "tp not defined". What is wrong?
This is tricky due to the way variables are implicitly defined as local or global, and the fact that definitions later in a function can affect their scoping in the whole function.
In the first case, tp defaults to being a global variable, and it works as you expected. However, in the second case, you assign to tp. This, as is noted in the scope of variables section of the manual:
"An assignment x = y introduces a new local variable x only if x is neither declared global nor introduced as local by any enclosing scope before or after the current line of code."
So, by assigning to tp, you've implicitly declared it as a local variable! It will now shadow the definition of your global… except that you try to access it first. The solution is simple: explicitly declare any variables to be global if you want to assign to them:
function test()
global tp
if tp==0
tp=tp-1
end
end
The behavior here is finely nuanced, but it's very consistent. I know it took me a few reads through that part of the manual before I finally understood how this works. If you can think of a better way to describe it, please say something!

Lua - How do I dynamically call a module?

Here's some much-simiplified Lua code I'm working with. I need to know how to dynamically call another module ('zebra'):
avar = require "avar"
bvar = require "bvar"
function create(zebra)
print(zebra.new())
end
print(create(avar))
And here are two modules:
local Avar = {}
function Avar.new()
return "avar"
end
return Avar
local Bvar = {}
function Bvar.new()
return "new"
end
function Bvar.old()
return "old"
end
return Bvar
If I try to pass in the string "avar" to my 'create' function, it doesn't work. If I pass in the word 'avar' with no quotes, it does work, however, I don't understand what avar with no quotes is? It seems to be a blank table? Not sure how to pass a blank table as an argument in my main program.
But maybe I'm totally on the wrong path. How do I dynamically call modules?
You can require any time:
function create(zebraModuleName)
zebraType = require(zebraModuleName)
print(zebraType .new())
end
print(create("avar"))
print(create("bvar"))
avar without the quotes is a global variable you created. It is initialized to the value returned by the require function1, which is the value returned by the module you are invoking. In this case, its a table with the new field that happens to be a function.
1 Importing a modules in Lua is done via regular functions instead of a special syntax. The function call parenthesis can be ommited because parens are optional if you write a function call with a single argument and that argument is a string or a table.
Other than that, there are also some other things you are confusing here:
The table you are storing on avar is not empty! You can print its contents by doing for k,v in pairs(avar) do print(k,v) end to see that.
The avar, bvar and create variables are global by default and will be seen by other modules. Most of the time you would rather make them local instead.
local avar = -- ...
local bvar = -- ...
local function create (zebra)
-- ...
end
The create function clearly expects a table since it does table indexing on its argument (getting the new key and calling it). The string doesn't have a "new" key so it won't work.
You aren't really dynamically calling a module. You are requiring that module in a regular way and it just happens that you pass the module return value into a function.
create always returns nil so there is no point in doing print(create(avar)). You probablu want to modify create to return its object instead of printing it.
You can use standard require from lua language or build your own loader using metatables/metamethods.
1. create a global function:
function dynrequire (module)
return setmetatable ({},{
__index = function (table,key)
return require(module..'.'..key)
end
})
end
2. Create your project tree visible to package.path
./MySwiss/
\___ init.lua
\___ cut.lua
\___ glue.lua
\___ dosomething.lua
3. Make your module dynamic
you only need to put this line on your MySwiss/init.lua (as if you were namespacing a PHP class):
return dynrequire('MySwiss')
4. Require your module and use subproperties dynamically
On your script you only need to require MySwiss, and the folder file (or subfolders with dynrequire('MySwiss.SubFolderName').
var X = require('MySwiss')
X.glue()
Note that MySwiss doesn't have glue key. But when you try access de glue key the metamethod __index try to require submodule. You can the full project tree using this technique. The only downside is the external dependencies not packed this way.