In g++ I was using getopt_long to handle command-line options. Does there
exist the same thing for Gfortran?
I want to be able to pass aguments to some Fortran unit tests.
Currently I have the following. As one can notice I am taking care
of getting the key and value myself. When using C++ getopt_long
was doing this for me.
i = 1
Do
Call Get_command_argument (i, arg)
If (Len_trim (arg) == 0) Exit
pos = Index (arg, "=")
!!$ Long option argument.
If (arg(1:2) == "--") Then
If (pos == 0) Then
c = arg
val = ""
Else
c = arg(:pos-1)
val = arg(pos+1:)
End If
!!$ Short option argument.
Elseif (arg(1:1) == "-") Then
c = arg
val = arg(pos+1:)
!!$ Non option argument.
Else
c = arg
val = arg
End If
!!$------------------------------------------------------------
Select Case (c)
Case ("-b","--brief")
arg_brief = .True.
Case ("-h","--help")
arg_help = .True.
Case ("-v","-V","--version")
arg_version = .True.
! Output model geographical definition
Case ("-cunit")
arg_cunit = val
Case default
arg_nonopt = Trim (Adjustl (arg))
Write (*,*) "Warning: Non option argument"
End Select
i = i + 1
End Do
!!$-------------------------------------------------------------
!!$ [TODO] Get numbers from arg_cunit
If (arg_cunit .contains. "-") Then
If (arg_cunit .contains. ",") Then
!!$ "-" and "," are present.
Else
!!$ "-" only are present.
End If
Else If (arg_cunit .contains. ",") Then
!!$ "," only are present
End If
Look at COMMAND_ARGUMENT_COUNT and GET_COMMAND_ARGUMENT. e.g., in the gfortran manual. They are standard Fortran intrinsics.
Of course you can use GET_COMMAND_ARGUMENT as you already do but that is the easy part. The hard part of the problem is to fill your variables with various numerical, logical and string values according to those argument strings. That is what the the following does:
One can use a namelist for easy argument parsing. Just add the begin and end markers. It is not too flexible, though, but very simple!
A (very!) short google search for getopt reveals a couple of Fortran ports of this library (or similar ones which include parsing):
http://fortranwiki.org/fortran/show/getopt_long_module
http://www.dominik-epple.de/getoptions/
http://lagrange.mechse.illinois.edu/partmc/partmc-2.4.0/doc/html/getopt_8_f90_source.html
and
http://libsufr.sourceforge.net/doxygen/getopt_8f90_source.html (thanks to AstroFloyd)
Related
I have the following macro and it should allow me to build a struct with one or 2 arguments only!
macro baseStruct(name, arg)
if length(arg.args)==2 && isa(arg.args[1],Symbol) || length(arg.args)==1
aakws = Pair{Symbol,Any}[]
defaultValues=Array{Any}(nothing,1)
field_define(aakws,defaultValues,1,arg,first=true)
:(struct $name
$(arg.args[1])
function $name(;$(arg.args[1])=$(defaultValues[1]))
new(check($name,$(arg.args[1]);$aakws...))
end
end)
else length(arg.args)==2 && !isa(arg.args[1],Symbol)
aakws1 = Pair{Symbol,Any}[]
aakws2 = Pair{Symbol,Any}[]
defaultValues=Array{Any}(nothing,2)
field_define(aakws1,defaultValues,1,arg)
field_define(aakws2,defaultValues,2,arg)
:(struct $name
$(arg.args[1].args[1])
$(arg.args[2].args[1])
function $name(;$(arg.args[1].args[1])=$(defaultValues[1]),$(arg.args[2].args[1])=$(defaultValues[2]))
new(check($name,$(arg.args[1].args[1]);$aakws1...),check($name,$(arg.args[2].args[1]);$aakws2...))
end
end)
#baseStruct test(
(arg1,(max=100.0,description="this arg1",min=5.5)),
(arg2,(max=100,default=90))
)
The macro will expand to:
struct test
arg1
arg2
end
and the following instance:
test1=test(arg1=80.5)
should give:
test1(arg1=80.5,arg2=90)
#check_function returns the argument. It allows me to check the argument in a specific way.
check(str,arg;type=DataType,max=nothing,min=nothing,default=nothing,description="")
#do somthing
return arg
end
#field_define_function it takes the second parameter from the macro as Expr. and convert it to a array with Pair{Symbol, Any} and then assign it to aakws.
I can extend this Code for more arguments, but as you can see it will be so long and complex. Have anybody a tip or other approach to implement this code for more/unultimate arguments in a more efficient way?
I don't have the code for field_define or check, so I can't work your example directly. Instead I'll work with a simpler macro that demonstrates how you can splat-interpolate a sequence of Expr into a quoted Expr:
# series of Expr like :(a::Int=1)
macro kwstruct(name, arg_type_defaults...)
# :(a::Int)
arg_types = [x.args[1]
for x in arg_type_defaults]
# :a
args = [y.args[1]
for y in arg_types]
# build :kw Expr because isolated :(a=1) is parsed as assignment
arg_defaults = [Expr(:kw, x.args[1].args[1], x.args[2])
for x in arg_type_defaults]
# splatting interpolation into a quoted Expr
:(struct $name
$(arg_types...)
function $name(;$(arg_defaults...))
new($(args...))
end
end
)
end
This macro expands #kwstruct D a::Int=1 b::String="12" to:
struct D
a::Int
b::String
function D(; a = 1, b = "12")
new(a, b)
end
end
And you can put as many arguments as you want, like #kwstruct(F, a::Int=1, b::String="12", c::Float64=1.2).
P.S. Splatting interpolation $(iterable...) only works in quoted Expr, which look like :(___) or quote ___ end. If you're constructing with an Expr() call, just use splatting:
vars = (:b, :c)
exq = :( f(a, $(vars...), d) ) # :(f(a, b, c, d))
ex = Expr(:call, :f, :a, vars..., :d) # :(f(a, b, c, d))
exq == ex # true
All these following lines of code are Julia expressions:
x = 10
1 + 1
println("hi")
if you want to pass an expression to a macro, it works like this. Macro foo just returns the given expression, which will be executed:
macro foo(ex)
return ex
end
#foo println("yes") # prints yes
x = #foo 1+1
println(x) # prints 2
If you want to convert a string into an expression, you can use Meta.parse():
string = "1+1"
expr = Meta.parse(string)
x = #foo expr
println(x) # prints 1 + 1
But, obviously, the macro treats expr as a symbol. What am i getting wrong here?
Thanks in advance!
Macro hygiene is important "macros must ensure that the variables they introduce in their returned expressions do not accidentally clash with existing variables in the surrounding code they expand into." There is a section in the docs. It is easiest just to show a simple case:
macro foo(x)
return :($x)
end
When you enter an ordinary expression in the REPL, it is evaluated immediately. To suppress that evaluation, surround the expression with :( ).
julia> 1 + 1
2
julia> :(1 + 1)
:(1 + 1)
# note this is the same result as you get using Meta.parse
julia> Meta.parse("1 + 1")
:(1 + 1)
So, Meta.parse will convert an appropriate string to an expression. And if you eval the result, the expression will be evaluated. Note that printing a simple expression removes the outer :( )
julia> expr = Meta.parse("1 + 1")
:(1 + 1)
julia> print(expr)
1 + 1
julia> result = eval(expr)
2
Usually, macros are used to manipulate things before the usual evaluation of expressions; they are syntax transformations, mostly. Macros are performed before other source code is compiled/evaluated/executed.
Rather than seeking a macro that evaluates a string as if it were typed directly into the REPL (without quotes), use this function instead.
evalstr(x::AbstractString) = eval(Meta.parse(x))
While I do not recommend this next macro, it is good to know the technique.
A macro named <name>_str is used like this <name>"<string contents>" :
julia> macro eval_str(x)
:(eval(Meta.parse($x)))
end
julia> eval"1 + 1"
2
(p.s. do not reuse Base function names as variable names, use str not string)
Please let me know if there is something I have not addressed.
I'd like to write a simple macro that shows the names & values of variables. In Common Lisp it would be
(defmacro dprint (&rest vars)
`(progn
,#(loop for v in vars
collect `(format t "~a: ~a~%" ',v ,v))))
In Julia I had two problems writing this:
How can I collect the generated Expr objects into a block? (In Lisp, this is done by splicing the list with ,# into progn.) The best I could come up with is to create an Expr(:block), and set its args to the list, but this is far from elegant.
I need to use both the name and the value of the variable. Interpolation inside strings and quoted expressions both use $, which complicates the issue, but even if I use string for concatenation, I can 't print the variable's name - at least :($v) does not do the same as ',v in CL...
My current macro looks like this:
macro dprint(vars...)
ex = Expr(:block)
ex.args = [:(println(string(:($v), " = ", $v))) for v in vars]
ex
end
Looking at a macroexpansion shows the problem:
julia> macroexpand(:(#dprint x y))
quote
println(string(v," = ",x))
println(string(v," = ",y))
end
I would like to get
quote
println(string(:x," = ",x))
println(string(:y," = ",y))
end
Any hints?
EDIT: Combining the answers, the solution seems to be the following:
macro dprint(vars...)
quote
$([:(println(string($(Meta.quot(v)), " = ", $v))) for v in vars]...)
end
end
... i.e., using $(Meta.quot(v)) to the effect of ',v, and $(expr...) for ,#expr. Thank you again!
the #show macro already exists for this. It is helpful to be able to implement it yourself, so later you can do other likes like make one that will show the size of an Array..
For your particular variant:
Answer is Meta.quot,
macro dprint(vars...)
ex = Expr(:block)
ex.args = [:(println($(Meta.quot(v)), " = ", $v)) for v in vars]
ex
end
See with:
julia> a=2; b=3;
julia> #dprint a
a = 2
julia> #dprint a b
a = 2
b = 3
oxinabox's answer is good, but I should mention the equivalent to ,#x is $(x...) (this is the other part of your question).
For instance, consider the macro
macro _begin(); esc(:begin); end
macro #_begin()(args...)
quote
$(args...)
end |> esc
end
and invocation
#begin x=1 y=2 x*y
which (though dubiously readable) produces the expected result 2. (The #_begin macro is not part of the example; it is required however because begin is a reserved word, so one needs a macro to access the symbol directly.)
Note
julia> macroexpand(:(#begin 1 2 3))
quote # REPL[1], line 5:
1
2
3
end
I consider this more readable, personally, than pushing to the .args array.
I'm studying Scala and trying to use it in my recent projects. And problems come. Here's one of my problem about necessity of semicolons. This is my example:
var str = "123.4"
var d = str toDouble
if(d > 10)
println("Larger than 10")
These codes cannot be compiled. Because if(d > 10) println("Larger than 10") returns value and compiler thinks this value is a parameter of toDouble method. However, toDouble doesn't have a parameter. This causes error.
The easiest way to solve this is adding a semicolon at the end of line 2. Just like this:
var str = "123.4"
var d = str toDouble;
if(d > 10)
println("Larger than 10")
This confused me and I thought I don't need semicolons at all as I won't put two statements at same line. It makes me uncomfortable that some lines end with semicolon while the others don't. Also, does it makes sense?
Aggregating possible answers: To write same thing without syntax error you could use:
Semicolon
var d = str toDouble;
if (d > 10) println("Larger than 10")
Dot Syntax
var d = str.toDouble
if (d > 10) println("Larger than 10")
Parenthesis
var d = (str toDouble)
if (d > 10) println("Larger than 10")
Braces
var d = {str toDouble}
if (d > 10) println("Larger than 10")
Empty line separator
var d = str toDouble
if (d > 10) println("Larger than 10")
Choose the one which suits your style.
But in normal (non-DSL) code you will usually meet dotted version
A [most] usual use of semicolon is inside simple for expressions with several bindings.
for(i <- 1 to 4; j <- 1 until i) println(f"$j < $i")
Which by the way could be refactored to semicolonless version too:
for{i <- 1 to 4
j <- 1 until i} println(f"$j < $i")
Semicolons are sometimes required when using postfix operators. This is part of the reason why postfix operators are a language feature that you'll be warned about if you haven't explicitly enabled them. You could use the str.toDouble syntax instead.
As mentioned by Imm, postfix operators are an added feature. By importing scala.language.postfixOps you enable the compiler to acccept postfix syntax, hence this works
import scala.language.postfixOps
var str = "123.4"
var d = str toDouble
if(d > 10)
println("Larger than 10")
Yes, you need to put a semicolon sometimes, to make compiler understand that value next is not a parameter to the previous one. Like in your case:
var str = "123.4"
In code above, string ("123.4") does not takes any paramater so compiler automatically understands that it's end of line and any variable or function next to it is start of new line. But in case:
var d = str toDouble
As we can pass parameters to toDouble method, so compiler will understand that variable next to it is parameter for the same, to avoid these kind of situations we have to make put semicolon and make compiler understand about end of line.
Can I convert a symbol that is a product of products into an array of products?
I tried to do something like this:
syms A B C D;
D = A*B*C;
factor(D);
but it doesn't factor it out (mostly because that isn't what factor is designed to do).
ans =
A*B*C
I need it to work if A B or C is replaced with any arbitrarily complicated parenthesized function, and it would be nice to do it without knowing what variables are in the function.
For example (all variables are symbolic):
D = x*(x-1)*(cos(z) + n);
factoring_function(D);
should be:
[x, x-1, (cos(z) + n)]
It seems like a string parsing problem, but I'm not confident that I can convert back to symbolic variables afterwards (also, string parsing in matlab sounds really tedious).
Thank you!
Use regexp on the string to split based on *:
>> str = 'x*(x-1)*(cos(z) + n)';
>> factors_str = regexp(str, '\*', 'split')
factors_str =
'x' '(x-1)' '(cos(z) + n)'
The result factor_str is a cell array of strings. To convert to a cell array of sym objects, use
N = numel(factors_str);
factors = cell(1,N); %// each cell will hold a sym factor
for n = 1:N
factors{n} = sym(factors_str{n});
end
I ended up writing the code to do this in python using sympy. I think I'm going to port the matlab code over to python because it is a more preferred language for me. I'm not claiming this is fast, but it serves my purposes.
# Factors a sum of products function that is first order with respect to all symbolic variables
# into a reduced form using products of sums whenever possible.
# #params orig_exp A symbolic expression to be simplified
# #params depth Used to control indenting for printing
# #params verbose Whether to print or not
def factored(orig_exp, depth = 0, verbose = False):
# Prevents sympy from doing any additional factoring
exp = expand(orig_exp)
if verbose: tabs = '\t'*depth
terms = []
# Break up the added terms
while(exp != 0):
my_atoms = symvar(exp)
if verbose:
print tabs,"The expression is",exp
print tabs,my_atoms, len(my_atoms)
# There is nothing to sort out, only one term left
if len(my_atoms) <= 1:
terms.append((exp, 1))
break
(c,v) = collect_terms(exp, my_atoms[0])
# Makes sure it doesn't factor anything extra out
exp = expand(c[1])
if verbose:
print tabs, "Collecting", my_atoms[0], "terms."
print tabs,'Seperated terms with ',v[0], ', (',c[0],')'
# Factor the leftovers and recombine
c[0] = factored(c[0], depth + 1)
terms.append((v[0], c[0]))
# Combines trivial terms whenever possible
i=0
def termParser(thing): return str(thing[1])
terms = sorted(terms, key = termParser)
while i<len(terms)-1:
if equals(terms[i][1], terms[i+1][1]):
terms[i] = (terms[i][0]+terms[i+1][0], terms[i][1])
del terms[i+1]
else:
i += 1
recombine = sum([terms[i][0]*terms[i][1] for i in range(len(terms))])
return simplify(recombine, ratio = 1)