Nim source file which after it's normalized - nim-lang

How is the Nim capability to be able to produce its source file which has all been normalized, i.e. evaluated/expanded all of the directives, templates, macros, etc.with their same arguments ?

Yes, via expandMacros. https://nim-lang.org/docs/macros.html#expandMacros.m%2Ctyped
It's possible to implement your own expandMacros macro like this:
import macros
macro myExpandMacros(body: typed): typed =
template inner(x: typed): typed = x
result = getAst(inner(body))
echo result.toStrLit
Usage example:
import macros, asyncdispatch
# Will echo expanded source code
# at compile time.
expandMacros:
proc test() {.async.} =
discard

Related

How can I pass a excel/csv file as a function parameter?

How can I pass a excel/csv file as a function parameter?
I have wrote a piece of code to copy content from one excel file to another excel file. Now I want to define it as a function so I just have to mention file name from which I want to transfer data to my existing file.
Thanks a lot in advance.
I am very new to Python Programming, and looking forward to learn a lot.
def feed_input_file(InputFile):
InputFile = "D:\\Python_Projects\\ABC.xlsx" #(I am passing Input file at the moment but I don't wanna pass it here)
#( Here I am trying to call my function parameter value)
Workbook1 = xl.load_workbook(feed_input_file(InputFile))
............
Still not quite sure what you are trying to do but if you want to create a function that will take a filename as an argument you could try something along the lines of:
def processFile(fn:str):
#Reads in the contents of file specified by fn
content = ''
with open(fn, 'a') as f:
data = f.read()
#Do something with data here to create content
return content
Then in your main part of the script
for filename in listofFiles:
fle_out = processFile(filename
#Do something here with file contents

File transfer for R extension in NetLogo - filename string with backslash and quotes

I need to use the R extension in NetLogo to do some network calculations. I am creating the network in NetLogo, exporting it to a text file, having R read the text file and construct a graph and calculate properties, then getting the calculation results. The export, read, calculate and get are being controlled by NetLogo through the R extension.
However, NetLogo and R have different default working directories. The problem I have about changing directories in R breaking the connection to the extensions (see R extension breaks connection to extensions directory in NetLogo) is affecting my attempts to use BehaviorSpace on the model.
My new approach is to not change the R working directory, but simply to provide the full path to R of the exported file.
r:clear
let dir pathdir:get-model
r:eval "library(igraph)"
; read network in R (avoid bug of R change working directory)
let runstring (word "r:eval \"gg <- read_graph(file = \"" dir "\\netlogo.gml\", format = \"gml\")\"")
print runstring
run runstring
This produces the correct string to run, output from print statement:
r:eval "gg <- read_graph(file = "C:\Users\Jen\Desktop\Intervention Effect\netlogo.gml", format = "gml")"
But I get an error on the run runstring that this nonstandard character is not allowed. Debugging by putting my constructed string into the run command directly, I have realised it is because I am now in a string environment and have to escape ('\') all my backslashes and quotes. That is, the command that would work if directly typed or included in the NetLogo code, will not work if it is provided as a string to be run.
I haven't yet been able to construct a string to put into the line run runstring that works, even by hand. This means I don't know what the string looks like that I am trying to create. Having identified the appropriate target string, I will need code to take the variable 'dir', convert it to a string, add the various \ characters to the dir, add the various \ characters to the quotes for the rest of the command, and join it so that it runs.
Can anyone provide some bits of this to get me further along?
Still struggling with this
I am now trying to work backwards. Find a string that works and then create it.
If I hard code the run command as follows, NetLogo closes. Even though if I copy the text between the quotes and enter it directly into R, it does what is expected.
let Rstring "gg <- read_graph(file = 'C:\\Users\\Jen\\Desktop\\Intervention Effect\\Networks\\netlogo.gml', format = 'gml')"
r:eval Rstring
The pathdir option ended up working. Here is example code for anyone who has a similar problem in the future.
let filename (word "Networks/netlogo" behaviorspace-run-number ".gml")
export-simple-gml filename
r:clearLocal
let dir pathdir:get-model
set filename (word dir "/" filename)
r:put "fn" filename
r:eval "gg <- read_graph(file = fn, format = 'gml')"
r:eval "V(gg)$name <- V(gg)$id" ; gml uses 'id', but igraph uses 'name'
I have a separate procedure for the actual export, which constructs a simplified gml file because the igraph import of gml format files is somewhat crippled. That's the procedure called within the code above, and the relevant piece is:
to export-simple-gml [ FN ]
carefully [ file-close-all ] [ ]
carefully [ file-delete FN ] [ ]
file-open FN
file-print <line to write to file>
...
end

matlab iterative filenames for saving

this question about matlab:
i'm running a loop and each iteration a new set of data is produced, and I want it to be saved in a new file each time. I also overwrite old files by changing the name. Looks like this:
name_each_iter = strrep(some_source,'.string.mat','string_new.(j).mat')
and what I#m struggling here is the iteration so that I obtain files:
...string_new.1.mat
...string_new.2.mat
etc.
I was trying with various combination of () [] {} as well as 'string_new.'j'.mat' (which gave syntax error)
How can it be done?
Strings are just vectors of characters. So if you want to iteratively create filenames here's an example of how you would do it:
for j = 1:10,
filename = ['string_new.' num2str(j) '.mat'];
disp(filename)
end
The above code will create the following output:
string_new.1.mat
string_new.2.mat
string_new.3.mat
string_new.4.mat
string_new.5.mat
string_new.6.mat
string_new.7.mat
string_new.8.mat
string_new.9.mat
string_new.10.mat
You could also generate all file names in advance using NUM2STR:
>> filenames = cellstr(num2str((1:10)','string_new.%02d.mat'))
filenames =
'string_new.01.mat'
'string_new.02.mat'
'string_new.03.mat'
'string_new.04.mat'
'string_new.05.mat'
'string_new.06.mat'
'string_new.07.mat'
'string_new.08.mat'
'string_new.09.mat'
'string_new.10.mat'
Now access the cell array contents as filenames{i} in each iteration
sprintf is very useful for this:
for ii=5:12
filename = sprintf('data_%02d.mat',ii)
end
this assigns the following strings to filename:
data_05.mat
data_06.mat
data_07.mat
data_08.mat
data_09.mat
data_10.mat
data_11.mat
data_12.mat
notice the zero padding. sprintf in general is useful if you want parameterized formatted strings.
For creating a name based of an already existing file, you can use regexp to detect the '_new.(number).mat' and change the string depending on what regexp finds:
original_filename = 'data.string.mat';
im = regexp(original_filename,'_new.\d+.mat')
if isempty(im) % original file, no _new.(j) detected
newname = [original_filename(1:end-4) '_new.1.mat'];
else
num = str2double(original_filename(im(end)+5:end-4));
newname = sprintf('%s_new.%d.mat',original_filename(1:im(end)-1),num+1);
end
This does exactly that, and produces:
data.string_new.1.mat
data.string_new.2.mat
data.string_new.3.mat
...
data.string_new.9.mat
data.string_new.10.mat
data.string_new.11.mat
when iterating the above function, starting with 'data.string.mat'

Basics on Empty List in Python

I am a newbie in Python, and I only have been programming in the language for the third day. I convert from Matlab because I am graduating from university and I just cannot afford the heavy cost of the software.
I am trying to add several filenames to a list, which fails. The following is my code:
import os
dirname = r"D:\MyFiles"
temp = os.listdir(dirname)
fl = []
for fn in temp:
if fn.startswith('L0116'):
fl = fl.append(fn)
What I don't understand is, the variable fl when initiated with [] returns as the list type, but then I fail to append the list with the above loop. I recheck my code using interactive prompt and I found out that the type changes to str and fails to append more.
I am stuck at this and I tried to google for about an hour without any clear clue to how I should do this.
Is there a better way? Or which part did I do it wrong?
Thank you so much for your help!
The append() method mutates the list in place. You should just append fn like this:
fl.append(fn)
don't try to assign the result of fl.append(fn) (which is None, by the way)
Also, don't use r"foo" strings for filenames. They are designed for use with regular expressions and using them for filenames or other kinds of strings will bite you. For example, you cannot end such a string with a backslash.
append works inplace, so no need to assign it to the list itself (fl = fl.append(fn)) just do fl.append(fn)
List comprehension:
import os
dirname = r"D:\MyFiles"
fl = [fn for fn in os.listdir(dirname) if fn.startswith('L0116')]
List append in python does not return a type, instead, you simply call the method like so:
import os
dirname = r"D:\MyFiles"
temp = os.listdir(dirname)
fl = []
for fn in temp:
if fn.startswith('L0116'):
fl.append(fn)
I haven't tested this code, but it should work. Your logic was resetting the list every time.

Comparing n number of files (binary)

I want to compare a number of files and find out which files which are the same, but they are not necessarily text files(So please don't suggest diff)
The files can be in any format (ie binary files).
I found out that I can run md5sum to find the hash of each file and then compare it manually to check if they are the same . But how can I automate this process ?
Ps : I also found that I can store the md5sums in a file using
md5sum <file-names> | cat >md5sum.txt
but I am stuck on how to automate this process.
I would prefer this to be done via a script (language no-bar).
If you can use languages like perl or python with builtin support for hashes/dictionnaries, it's really easy.
Loop over file names and signature and create a hash with md5sum as key and list of files with that md5 as value.
Then loop over content of hash and show entries with more than one item. These are files likely to be identical (you can't be really sure with a signature based approach).
As people are asking for code, maybe something like below. That is a perl implementation. I may add an equivalent python sample later if it is wanted.
#!perl
my $same = {};
for my $x (#ARGV){
my ($sig, $name) = split(/\s+/, `md5sum $x`);
if (!defined($same{$sig})){$same{$sig} = []}
push #{$same{$sig}}, $name;
}
for my $sig (keys %same){
if (#{$same{$sig}} > 1){
print "Files with same MD5 : ".join('-', #{$same{$sig}})."\n";
}
}
Say you put that in a file same.pl, you call it like:
perl same.pl
exemple of use:
$ md5sum F*
c9904273735f3141c1dd61533e02246a F1
c9904273735f3141c1dd61533e02246a F2
c9904273735f3141c1dd61533e02246a F3
d41d8cd98f00b204e9800998ecf8427e F4
$ perl same.pl F1 F2 F3 F4
Files with same MD5 : F1-F2-F3
Below is a possible python version (working with both python2 and python3).
#!python
import hashlib
def md5sum(filename):
f = open(filename, mode='rb')
buf = f.read(128)
d = hashlib.md5(buf)
while len(buf) == 128:
buf = f.read(128)
d.update(buf)
return d.hexdigest()
if __name__ == "__main__":
import sys
same = {}
for name in sys.argv[1:]:
sig = md5sum(name)
same.setdefault(sig, []).append(name)
for k in same:
if len(same[k]) > 1:
print("Files with same MD5: {l}".format(l="-".join(same[k])))
Note that if you are comparing really large number of files, providing file names on command line as in the above exemples may not be enough and you should use some more elaborate way to do that (or put some glob inside the script), or the shell command line will overflow.

Resources