I am using the app TouchLua.
I need to turn a string from a table into an argument. This is the only way I would like to do the table.
b = {}
b[1] = "010,010,draw.blue"
function drawButtons()
for i = 1,2 do
draw.fillrect(tonumber(string.sub(b[i],1,3)), tonumber(string.sub(b[i],5,7)), tonumber(string.sub(b[i],1,3))+10, tonumber(string.sub(b[i],5,7)),string.sub(b[i],9))
end
end
drawButtons()
Assuming you want a function eval so that print( eval( "draw.blue" ) ) is roughly equivalent to print( draw.blue ), here is a quick and dirty version:
local function eval( s, e )
return assert( load( "return "..s, "=eval", "t", e or _G ) )()
end
-- global variable
draw = { blue = 2 }
print( draw.blue )
print( eval( "draw.blue" ) )
If you are using an older Lua version than 5.2, you will need loadstring instead of load and an additional setfenv call. Of course, instead of using load you can parse the string s and index the table e or _G manually.
The above code assumes that draw is a global variable. If you want the code to work with a local variable you need to use the debug library:
-- same for local variable
local localdraw = { blue = 3 }
print( localdraw.blue )
-- needs debugging information, so won't work with stripped bytecode!
local function locals()
local t, i, n, v = {}, 1, debug.getlocal( 2, 1 )
while n ~= nil do
t[ n ], i = v, i+1
n, v = debug.getlocal( 2, i )
end
return t
end
print( eval( "localdraw.blue", locals() ) )
Related
I am looking for a way to read numerical expressions in Fortran.
With numerical expression I mean dsqrt(0.5d0)/3.d0+1.d0 or something rather then the translated 1.235... real version.
With reading I mean
open(unit=UnitNumber,file="FileName")
read(UnitNumber, *) ....
I try to define in the reading statement the format, for instanceread(unitNumber,"(15F24.17)") but it does not help. I am
I am wondering if I can do it only internally, defining real(8), parameter :: dsqrt(0.5d0)/3.d0+1.d0 .
Maybe the use of FORMAT syntax could help?
As suggested by #agentp, interpreted languages like Python and Julia can parse a string directly as a piece of code, so utilizing such a feature may be convenient for your purpose. But if you definitely need to achieve the same goal in Fortran, another approach (with least effort!) may be simply to call eval() in such languages, for example:
module util
use iso_fortran_env, only: dp => real64
implicit none
contains
subroutine eval( expr, ans, x, y )
character(*), intent(in) :: expr
real(dp), intent(out) :: ans
real(dp), intent(in), optional :: x, y
character(len(expr)+200) cmd, sx, sy
integer u
sx = "" ; sy = ""
if ( present(x) ) write( sx, "(' x = ', es25.15, ' ; ')" ) x
if ( present(y) ) write( sy, "(' y = ', es25.15, ' ; ')" ) y
write( cmd, "(a)" ) &
"python -c ""from __future__ import print_function, division ; " // &
"from math import * ; " // trim(sx) // trim(sy) // &
"print( eval( '" // trim(expr) // "' ))"" > tmp.dat"
call system( trim( cmd ) )
open( newunit=u, file="tmp.dat", status="old" )
read( u, * ) ans
close( u )
call system( "rm -f tmp.dat" )
end subroutine
end module
program main
use util, only: dp, eval
implicit none
character(200) str
real(dp) ans
str = "sqrt( 2.0 ) + 1000.0"
call eval( str, ans )
print *, "ans = ", ans
str = "acos( x ) + 2000.0"
call eval( str, ans, x= -1.0_dp )
print *, "ans = ", ans
str = "10 * x + y"
call eval( str, ans, x= 1.0_dp, y= 2.0_dp )
print *, "ans = ", ans
end program
Results:
$ gfortran test.f90 # gfortran >=5 is recommended
$ ./a.out
ans = 1001.4142135623731
ans = 2003.1415926535899
ans = 12.000000000000000
More specifically, the above code simply invokes the built-in eval() function in Python via system(). But it is not very efficient because the resulting value is once written to an external file (and also the overhead to call Python itself). So if efficiency matters, it may be better to use more specific 3rd-party libraries, or for handiness, work with interpreted languages directly. (I suggest the latter approach if the calculation is not too demanding, because it saves much time for coding...)
Python:
from __future__ import print_function, division
from math import *
str = input( "Input an expression: " )
x = 1.0
y = 2.0
print( eval( str ) ) # if you type "x + 10 * y" in the prompt, you get 21
Julia:
println( "Input an expression: " )
str = readline()
x = 1.0
y = 2.0
println( eval( parse( str ) ) )
[ EDIT ]
If it is OK to use system() and write external files, another option may be to simply write a small Fortran code that contains the expression to be evaluated, compile and run it via system(), get the result via an external file. For example, if we replace the two lines in the above code (write( cmd, "(a)" ) ... and system( trim( cmd ) )) by the following, it gives the same result. This might be useful if we want to keep the code entirely written in Fortran, with minimal effort for modification.
open( newunit=u, file="tmp.f90" )
write( u, "(a)" ) "implicit none"
write( u, "(a)" ) "real :: x, y"
write( u, "(a)" ) trim(sx)
write( u, "(a)" ) trim(sy)
write( u, "(a)" ) "write(*,'(e30.20)') " // trim(expr)
write( u, "(a)" ) "end"
close( u )
call system( "gfortran -fdefault-real-8 -ffree-line-length-none tmp.f90 && ./a.out > tmp.dat" )
! Assuming bash on Linux or Mac (x86_64).
! -fdefault-real-8 is attached to promote 1.0 etc to 8-byte floating-point values.
call system( "rm -f tmp.f90" )
For the record, the library fparser allows you to do precisely what you asked for: evaluate a string as a mathematical expression within Fortran, without requiring any other programming languages.
No, there is nothing like this built in Fortran or any related programming languages. There are specific libraries for similar purposes (not necessarily too many in Fortran).
It is not clear at all to me why do you want that and how do you intend to use such an expression. It would have to be some specific type and you would need specific subroutines to evaluate such an expression.
This question already has answers here:
Obtaining current host name from Cray Fortran
(3 answers)
Closed 6 years ago.
I am running a fortran code on a cluster equiped with linux system. When the code begin to run, I want it to output some basic information of the node where it is running, especially the node name. How to do it in fortran.
If your code is parallelised with MPI - which is kind of common for a code running on a cluster - then just call MPI_Get_processor_name() that just does exactly this.
If not, just use the iso_c_binding module to call the C function gethostname(), which again just does that.
EDIT: here is an example on how to call gethostname() with the iso_c_binding module. I'm definitely not an expert with that so it might not be the most effective one ever...
module unistd
interface
integer( kind = C_INT ) function gethostname( hname, len ) bind( C, name = 'gethostname' )
use iso_c_binding
implicit none
character( kind = C_CHAR ) :: hname( * )
integer( kind = C_INT ), VALUE :: len
end function gethostname
end interface
end module unistd
program hostname
use iso_c_binding
use unistd
implicit none
integer( kind = C_INT ), parameter :: sl = 100
character( kind = C_CHAR ) :: hn( sl )
character( len = sl ) :: fn
character :: c
integer :: res, i, j
res = gethostname( hn, sl )
if ( res == 0 ) then
do i = 1, sl
c = hn( i )
if ( c == char( 0 ) ) exit
fn( i: i ) = c
end do
do j = i, sl
fn( j: j ) = ' '
end do
print *, "->", trim( fn ), "<-"
else
print *, "call to gethostname() didn't work..."
end if
end program hostname
If the information you want is contained in an environment variable the easy way is just to get its value from a call to get_environment_variable. For the hostname
program gethost
character*32 hostname
call get_environment_variable('HOST',hostname)
write(*,*) 'My gracious host is ',trim(hostname)
end program gethost
Is there an easy way to split a string like this:
M34a79 or M2ab943 or M4c4
into
M,34,a,79 or M,2,ab,943 or M,4,c,4
without any separators?
You can do it with a pair of gsub calls:
x = "M34a79 or M2ab943 or M4c4"
x, _ = x:gsub( "(%d)(%a)", "%1,%2" )
x, _ = x:gsub( "(%a)(%d)", "%1,%2" )
print( x )
M,34,a,79 or M,2,ab,943 or M,4,c,4
Might not work in all cases, but does work on your example.
If you don’t mind using the LPEG
library:
local lpeg = require "lpeg"
local C, Ct, P, R = lpeg.C, lpeg.Ct, lpeg.P, lpeg.R
local lpegmatch = lpeg.match
local extract
do
local digit = R"09"
local lower = R"az"
local comma = P","
local space = P" "
local schema = Ct( C(P"M")
* (digit^1 / tonumber)
* C(lower^1)
* (digit^1 / tonumber))
local extractor = Ct((schema + 1)^0)
extract = function (str)
return lpegmatch (extractor, str)
end
end
This will match all sequences of characters of the input
that consist of (in that order)
the letter M,
a sequence of 1 or more decimal digits,
a sequence of 1 or more lowercase characters, and
another sequence of 1 or more decimal digits.
When processing the input each match is put in a subtable,
the digits are converted to Lua numbers on the fly.
Since the question requested it, the leading M is included
in the entries.
Usage example:
local data = extract [[M34a79 or M2ab943 or M4c4]]
for i = 1, #data do
local elm = data[i]
print (string.format ("[%d] = { [1] = %q, [2] = %d, [3] = %q, [4] = %d },",
i, table.unpack (elm)))
end
Output:
[1] = { [1] = "M", [2] = 34, [3] = "a", [4] = 79 },
[2] = { [1] = "M", [2] = 2, [3] = "ab", [4] = 943 },
[3] = { [1] = "M", [2] = 4, [3] = "c", [4] = 4 },
Solution:
http://www.coronalabs.com/blog/2013/04/16/lua-string-magic/
function string:split( inSplitPattern, outResults )
...
end
function val(x)
x = x:gsub( "(%d)(%a)", "%1,%2" )
x = x:gsub( "(%a)(%d)", "%1,%2" )
Table = string.split(x,",")
for i = 1, #Table do
print( Table[i] )
end
end
val("M3a5")
returns M 3 a 5
I'm looking for a boolean interpolation character for string.format(as the title says).
I want something that will work this way:
print(string.format("nil == false: %b",(nil==false))
%b is just a placeholder, you'll get an error with that. I'm looking for 'b'. I can't
just do:
print("nil == false: " .. (nil==false))
because booleans can't be concatenated with strings. I could do:
val=(nil==false)
if val==false then truth="false" else truth="true" end
print("nil==false: ".. truth)
But it's too much work.
If you're wondering how to modify string.format so it supports bools, here's one way you can do it:
do
local format = string.format
function string.format(str, ...)
local args = {...}
local boolargs = {}
str = str:gsub("%%b", "%%%%b")
for i = #args, 1, -1 do
if type(args[i]) == "boolean" then
table.insert(boolargs, 1, args[i])
table.remove(args, i)
end
end
str = format(str, unpack(args))
local j = 0
return (str:gsub("%%b", function(spec) j = j + 1; return tostring(boolargs[j]) end))
end
end
print(string.format("%s is %b", "nil == false", nil==false))
It might be a bit confusing to follow. The idea is to gsub all "%b" in the string and replace it with double escape %%b so format doesn't try to interpret it. We let string.format do its stuff and we take the result and handle %b manually ourselves.
Well, first you should try reading the relevant section of the manual. That will let you discover that there is no format specifier for booleans.
What greatwolf suggests is a solution, i.e. converting the value explicitly to a string. If there is a possibility that your truth value may be nil, but you want to output it as false, this trick is useful:
truth = nil
print("nil==false: ".. tostring( not not truth ))
In this way both nil and false will be displayed as false.
Edit (to answer a comment)
In Lua 5.2 the %s specifier automatically convert the arguments to strings using tostring internally. Thus:
print( string.format( "%s %s %s", true, nil, {} ) )
prints:
true nil table: 00462400
otherwise you can create your own formatting function wrapping string.format:
local function myformat( fmt, ... )
local buf = {}
for i = 1, select( '#', ... ) do
local a = select( i, ... )
if type( a ) ~= 'string' and type( a ) ~= 'number' then
a = tostring( a )
end
buf[i] = a
end
return string.format( fmt, unpack( buf ) )
end
print( myformat( "%s %s %s", true, nil, {} ) )
I have two list like this :
def a = [100,200,300]
def b = [30,60,90]
I want the Groovier way of manipulating the a like this :
1) First element of a should be changed to a[0]-2*b[0]
2)Second element of a should be changed to a[1]-4*b[1]
3)Third element of a should be changed to a[2]-8*b[2]
(provided that both a and b will be of same length of 3)
If the list changed to map like this, lets say:
def a1 = [100:30, 200:60, 300:90]
how one could do the same above operation in this case.
Thanks in advance.
For List, I'd go with:
def result = []
a.eachWithIndex{ item, index ->
result << item - ((2**index) * b[index])
}
For Map it's a bit easier, but still requires an external state:
int i = 1
def result = a.collect { k, v -> k - ((2**i++) * v) }
A pity, Groovy doesn't have an analog for zip, in this case - something like zipWithIndex or collectWithIndex.
Using collect
In response to Victor in the comments, you can do this using a collect
def a = [100,200,300]
def b = [30,60,90]
// Introduce a list `c` of the multiplier
def c = (1..a.size()).collect { 2**it }
// Transpose these lists together, and calculate
[a,b,c].transpose().collect { x, y, z ->
x - y * z
}
Using inject
You can also use inject, passing in a map of multiplier and result, then fetching the result out at the end:
def result = [a,b].transpose().inject( [ mult:2, result:[] ] ) { acc, vals ->
acc.result << vals.with { av, bv -> av - ( acc.mult * bv ) }
acc.mult *= 2
acc
}.result
And similarly, you can use inject for the map:
def result = a1.inject( [ mult:2, result:[] ] ) { acc, key, val ->
acc.result << key - ( acc.mult * val )
acc.mult *= 2
acc
}.result
Using inject has the advantage that you don't need external variables declared, but has the disadvantage of being harder to read the code (and as Victor points out in the comments, this makes static analysis of the code hard to impossible for IDEs and groovypp)
def a1 = [100:30, 200:60, 300:90]
a1.eachWithIndex{item,index ->
println item.key-((2**(index+1))*item.value)
i++
}