Check if input to macro is a vector - julia

I would like to check if the input to a macro is an vector and raise an exception if it is not. Currently, I have come up with this. Is there an idiomatic way of doing this?
macro doarray(arr)
if in(:head, fieldnames(typeof(arr))) && arr.head == :vect
println("Do Something")
else
throw(ArgumentError("$(arr) should be a vector"))
end
end

Related

How do I pass a variable to a macro and evaluate it before macro execution?

If I have a method
macro doarray(arr)
if in(:head, fieldnames(typeof(arr))) && arr.head == :vect
println("A Vector")
else
throw(ArgumentError("$(arr) should be a vector"))
end
end
it works if I write this
#doarray([x])
or
#doarray([:x])
but the following code rightly does not work, raising the ArgumentError(i.e. ArgumentError: alist should be a vector).
alist = [:x]
#doarray(alist)
How can I make the above to act similarly as #doarray([x])
Motivation:
I have a recursive macro(say mymacro) which takes a vector, operates on the first value and then calls recursively mymacro with the rest of the vector(say rest_vector). I can create rest_vector, print the value correctly(for debugging) but I don't know how to evaluate rest_vector when I feed it to the mymacro again.
EDIT 1:
I'm trying to implement logic programming in Julia, namely MiniKanren. In the Clojure implementation that I am basing this off, the code is such.
(defmacro fresh
[var-vec & clauses]
(if (empty? var-vec)
`(lconj+ ~#clauses)
`(call-fresh (fn [~(first var-vec)]
(fresh [~#(rest var-vec)]
~#clauses)))))
My failing Julia code based on that is below. I apologize if it does not make sense as I am trying to understand macros by implementing it.
macro fresh(varvec, clauses...)
if isempty(varvec.args)
:(lconjplus($(esc(clauses))))
else
varvecrest = varvec.args[2:end]
return quote
fn = $(esc(varvec.args[1])) -> #fresh($(varvecvest), $(esc(clauses)))
callfresh(fn)
end
end
end
The error I get when I run the code #fresh([x, y], ===(x, 42))(you can disregard ===(x, 42) for this discussion)
ERROR: LoadError: LoadError: UndefVarError: varvecvest not defined
The problem line is fn = $(esc(varvec.args[1])) -> #fresh($(varvecvest), $(esc(clauses)))
If I understand your problem correctly it is better to call a function (not a macro) inside a macro that will operate on AST passed to the macro. Here is a simple example how you could do it:
function recarray(arr)
println("head: ", popfirst!(arr.args))
isempty(arr.args) || recarray(arr)
end
macro doarray(arr)
if in(:head, fieldnames(typeof(arr))) && arr.head == :vect
println("A Vector")
recarray(arr)
else
throw(ArgumentError("$(arr) should be a vector"))
end
end
Of course in this example we do not do anything useful. If you specified what exactly you want to achieve then I might suggest something more specific.

Program doesn't enter if statement in Julia

There is this block of code in my program that I simplified here, while the initial value of previoF is false the program doesn't print "s1" and only prints "s0".
I tried looking at it in various ways, and I don't get what is wrong with the code.
Could it be that I am not writing the if statement the right way somehow ?
previoF = false
for f in filter(x -> endswith(x, "VMSource.vm"), readdir())
open(f,"a") do file
for ln in eachline(open(f))
if (previoF==false)
if(contains(ln,"Add"))
println("s1")
end
previoF=true
else
if(contains(ln,"Add"))
println("s0")
end
previoF=false
end
end
end
end

Why is this recursion function parameter nil?

walk is a recursive function that walks the given tree and if walked over a file do something with it.
The "do something with it" should be changed.
I could use coroutine.yield(f) in walk but I wanted to know my mistake first.
As you see the argument lootfunc is given by a reference and should be called within walk.
But it gives me the error seen below. So why is the parameter lootfunc nil?
local KEYWORDS = {
"%.db[x]?",
"%.ojsn",
}
local function loot(d)
if MATCH == "path" then -- only look to the path not to the content
for i,keyword in pairs(KEYWORDS) do
if string.find(d,keyword) then
--coroutine.yield(d)
print(d)
end
end
end
end
local function walk (path,lootfunc)
for file in lfs.dir(path) do
if file ~= "." and file ~= ".." then
local f = path..'/'..file
local attr = lfs.attributes (f)
if(type(attr) == "table") then
if attr.mode == "directory" then
walk (f) -- next round
elseif attr.mode == "file" then
lootfunc(f)
end
end
end
end
end
walk("/path/",loot)
shadowed.lua:73: attempt to call local 'lootfunc' (a nil value)
stack traceback:
(command line):1: in function 'lootfunc'
shadowed.lua:73: in function 'walk'
shadowed.lua:71: in function 'walk'
shadowed.lua:71: in function 'walk'
shadowed.lua:88: in main chunk
[C]: in function 'dofile'
(command line):1: in function <(command line):1>
[C]: in function 'xpcall'
(command line):1: in main chunk
[C]: ?
You are calling walk(f) in the function walk, there's only one argument, the second argument is filled with nil, so change:
if attr.mode == "directory" then
walk(f) -- next round
to
if attr.mode == "directory" then
walk(f, lootfunc) -- next round

Ada actual for "S" must be a variable

So here is a piece of my body file. I am getting the error "words.adb:75:42: actual for "S" must be a variable".
procedure Remove_Character(S : in out Ustring; C : in Character; Successful : out Boolean) is
begin
for I in 1..length(S) loop
if Element(S, I) = C then
Delete(S, I, I);
Successful := true;
return;
end if;
end loop;
Successful := false;
end Remove_Character;
function Is_Subset(Subset : Ustring; S : Ustring) return Boolean is
Could_Remove : Boolean;
begin
for I in 1..length(Subset) loop
Remove_Character(S , Element(Subset, I), Could_Remove);
if Could_Remove = false then
return false;
end if;
end loop;
return True;
end Is_Subset;
I understand where my error is coming from. Remove_Character uses S : in out Ustring while function Is_Subset uses S : in Ustring.
My question is how do I change the variable from Remove_Character into only an in Ustring?
Sorry if this is a tad jumbled, I'm fairly new to both programming and the site.
You can't, at least not directly.
I don't know what a UString is, but I presume the Delete procedure modifies it. If you changed the declaration of S in Remove_Character to S: in Ustring, you'd presumably get an error on the call to Delete.
The simplest approach I can think of would be to make a copy of S in Is_Subset:
Copy_Of_S: UString := S;
and then pass the (modifiable) copy to Remove_Character.
By "simplest", I mean it makes the smallest change to your existing code. But you should probably consider reorganizing it. Determining whether one UString is a subset of another by modifying one of the strings doesn't seem like the best approach; I'm sure there's a more efficient way to do it.
A minor and irrelevant point: this:
if Could_Remove = false then
is better written as:
if not Could_Remove then

Fortran procedure pointer points to a subroutine that does nothing

I have a code like this
:
procedure(),pointer :: p
if ()
p => job1
else
p => job2
endif
do i=1,a_big_number
call x(...)
call p(i,j,k)
enddo
The subroutine 'job1' does some work, but the subroutine 'job2' does nothing. In other words, under some circumstances, I need to finish 'x' and 'job1'. Under other circumstances, I only need to do 'x'. My question is how should I define job2. It seems simply using null() does not work. What I am doing right now is like:
subroutine job2(i,j,k)
integer,intent(in) :: i,j,k
end subroutine
However, this looks silly, and I got a lot compiling warning when I compiled the code because those arguments were not used. Is there a smarter way to do this?
You could nullify the procedure pointer in the case that there was nothing useful to do, and then test the association status prior to invoking the procedure through the pointer.
PROCEDURE(interface_that_matches_job1), POINTER :: p
IF (...) THEN
p => job1
ELSE
NULLIFY(p) ! Or p => NULL()
END IF
DO i = 1, a_big_number
CALL x(...)
IF (ASSOCIATED(p)) CALL p(i,j,k)
END DO
If your concern is really about the if statement in the loop, you could just put the if statement outside of the loop:
if (condition) then
do ii = 1, big_number
call x(...)
call p(i,j,k)
end do
else
do ii = 1, big_number
call x(...)
end do
end if
Then do some timings on this version and then on a version with the if inside the loop:
do ii = 1, big_number
call x(...)
if (condition) then
call p(i,j,k)
end if
end do
I'd rather guess that you won't see any significant difference between them, as the subroutine call in the loop may already giving you an overhead much larger as the one caused by the if statement.

Resources