Related
I am new to Elixir language and I am having some issues while writing a piece of code.
What I am given is a 2D array like
list1 = [
[1 ,2,3,4,"nil"],
[6,7,8,9,10,],
[11,"nil",13,"nil",15],
[16,17,"nil",19,20] ]
Now, what I've to do is to get all the elements that have values between 10 and 20, so what I'm doing is:
final_list = []
Enum.each(list1, fn row ->
Enum.each(row, &(if (&1 >= 10 and &1 <= 99) do final_list = final_list ++ &1 end))
end
)
Doing this, I'm expecting that I'll get my list of numbers in final_list but I'm getting blank final list with a warning like:
warning: variable "final_list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
iex:5
:ok
and upon printing final_list, it is not updated.
When I try to check whether my code is working properly or not, using IO.puts as:
iex(5)> Enum.each(list1, fn row -> ...(5)> Enum.each(row, &(if (&1 >= 10 and &1 <= 99) do IO.puts(final_list ++ &1) end))
...(5)> end
...(5)> )
The Output is:
10
11
13
15
16
17
19
20
:ok
What could I possibly be doing wrong here? Shouldn't it add the elements to the final_list?
If this is wrong ( probably it is), what should be the possible solution to this?
Any kind of help will be appreciated.
As mentioned in Adam's comments, this is a FAQ and the important thing is the message "warning: variable "final_list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)" This message actually indicates a very serious problem.
It tells you that the assignment "final_list = final_list ++ &1" is useless since it just creates a local variable, hiding the external one. Elixir variables are not mutable so you need to reorganize seriously your code.
The simplest way is
final_list =
for sublist <- list1,
n <- sublist,
is_number(n),
n in 10..20,
do: n
Note that every time you write final_list = ..., you actually declare a new variable with the same name, so the final_list you declared inside your anonymous function is not the final_list outside the anonymous function.
I'm writing a genetic program in order to test the fitness of randomly generated expressions. Shown here is the function to generate the expression as well a the main function. DIV and GT are defined elsewhere in the code:
function create_single_full_tree(depth, fs, ts)
"""
Creates a single AST with full depth
Inputs
depth Current depth of tree. Initially called from main() with max depth
fs Function Set - Array of allowed functions
ts Terminal Set - Array of allowed terminal values
Output
Full AST of typeof()==Expr
"""
# If we are at the bottom
if depth == 1
# End of tree, return function with two terminal nodes
return Expr(:call, fs[rand(1:length(fs))], ts[rand(1:length(ts))], ts[rand(1:length(ts))])
else
# Not end of expression, recurively go back through and create functions for each new node
return Expr(:call, fs[rand(1:length(fs))], create_single_full_tree(depth-1, fs, ts), create_single_full_tree(depth-1, fs, ts))
end
end
function main()
"""
Main function
"""
# Define functional and terminal sets
fs = [:+, :-, :DIV, :GT]
ts = [:x, :v, -1]
# Create the tree
ast = create_single_full_tree(4, fs, ts)
#println(typeof(ast))
#println(ast)
#println(dump(ast))
x = 1
v = 1
eval(ast) # Error out unless x and v are globals
end
main()
I am generating a random expression based on certain allowed functions and variables. As seen in the code, the expression can only have symbols x and v, as well as the value -1. I will need to test the expression with a variety of x and v values; here I am just using x=1 and v=1 to test the code.
The expression is being returned correctly, however, eval() can only be used with global variables, so it will error out when run unless I declare x and v to be global (ERROR: LoadError: UndefVarError: x not defined). I would like to avoid globals if possible. Is there a better way to generate and evaluate these generated expressions with locally defined variables?
Here is an example for generating an (anonymous) function. The result of eval can be called as a function and your variable can be passed as parameters:
myfun = eval(Expr(:->,:x, Expr(:block, Expr(:call,:*,3,:x) )))
myfun(14)
# returns 42
The dump function is very useful to inspect the expression that the parsers has created. For two input arguments you would use a tuple for example as args[1]:
julia> dump(parse("(x,y) -> 3x + y"))
Expr
head: Symbol ->
args: Array{Any}((2,))
1: Expr
head: Symbol tuple
args: Array{Any}((2,))
1: Symbol x
2: Symbol y
typ: Any
2: Expr
[...]
Does this help?
In the Metaprogramming part of the Julia documentation, there is a sentence under the eval() and effects section which says
Every module has its own eval() function that evaluates expressions in its global scope.
Similarly, the REPL help ?eval will give you, on Julia 0.6.2, the following help:
Evaluate an expression in the given module and return the result. Every Module (except those defined with baremodule) has its own 1-argument definition of eval, which evaluates expressions in that module.
I assume, you are working in the Main module in your example. That's why you need to have the globals defined there. For your problem, you can use macros and interpolate the values of x and y directly inside the macro.
A minimal working example would be:
macro eval_line(a, b, x)
isa(a, Real) || (warn("$a is not a real number."); return :(throw(DomainError())))
isa(b, Real) || (warn("$b is not a real number."); return :(throw(DomainError())))
return :($a * $x + $b) # interpolate the variables
end
Here, #eval_line macro does the following:
Main> #macroexpand #eval_line(5, 6, 2)
:(5 * 2 + 6)
As you can see, the values of macro's arguments are interpolated inside the macro and the expression is given to the user accordingly. When the user does not behave,
Main> #macroexpand #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
:((Main.throw)((Main.DomainError)()))
a user-friendly warning message is provided to the user at parse-time, and a DomainError is thrown at run-time.
Of course, you can do these things within your functions, again by interpolating the variables --- you do not need to use macros. However, what you would like to achieve in the end is to combine eval with the output of a function that returns Expr. This is what the macro functionality is for. Finally, you would simply call your macros with an # sign preceding the macro name:
Main> #eval_line(5, 6, 2)
16
Main> #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
ERROR: DomainError:
Stacktrace:
[1] eval(::Module, ::Any) at ./boot.jl:235
EDIT 1. You can take this one step further, and create functions accordingly:
macro define_lines(linedefs)
for (name, a, b) in eval(linedefs)
ex = quote
function $(Symbol(name))(x) # interpolate name
return $a * x + $b # interpolate a and b here
end
end
eval(ex) # evaluate the function definition expression in the module
end
end
Then, you can call this macro to create different line definitions in the form of functions to be called later on:
#define_lines([
("identity_line", 1, 0);
("null_line", 0, 0);
("unit_shift", 0, 1)
])
identity_line(5) # returns 5
null_line(5) # returns 0
unit_shift(5) # returns 1
EDIT 2. You can, I guess, achieve what you would like to achieve by using a macro similar to that below:
macro random_oper(depth, fs, ts)
operations = eval(fs)
oper = operations[rand(1:length(operations))]
terminals = eval(ts)
ts = terminals[rand(1:length(terminals), 2)]
ex = :($oper($ts...))
for d in 2:depth
oper = operations[rand(1:length(operations))]
t = terminals[rand(1:length(terminals))]
ex = :($oper($ex, $t))
end
return ex
end
which will give the following, for instance:
Main> #macroexpand #random_oper(1, [+, -, /], [1,2,3])
:((-)([3, 3]...))
Main> #macroexpand #random_oper(2, [+, -, /], [1,2,3])
:((+)((-)([2, 3]...), 3))
Thanks Arda for the thorough response! This helped, but part of me thinks there may be a better way to do this as it seems too roundabout. Since I am writing a genetic program, I will need to create 500 of these ASTs, all with random functions and terminals from a set of allowed functions and terminals (fs and ts in the code). I will also need to test each function with 20 different values of x and v.
In order to accomplish this with the information you have given, I have come up with the following macro:
macro create_function(defs)
for name in eval(defs)
ex = quote
function $(Symbol(name))(x,v)
fs = [:+, :-, :DIV, :GT]
ts = [x,v,-1]
return create_single_full_tree(4, fs, ts)
end
end
eval(ex)
end
end
I can then supply a list of 500 random function names in my main() function, such as ["func1, func2, func3,.....". Which I can eval with any x and v values in my main function. This has solved my issue, however, this seems to be a very roundabout way of doing this, and may make it difficult to evolve each AST with each iteration.
I am trying to write a simple interpreter to control a Turtle using F#.
I have created the following recursive union type to represent the few commands that the Turtle will accept. The code will be represented by a "Command list" that shouldn't be too hard to execute with a simple recursive function.
type Command =
| Repeat of amount * Command list
| Forward of amount
| Turn of direction * amount
I want to make this interpreter white space delineated so the source could look as follows.
Forward 75
Repeat 4
Forward 10
Turn Right 50
Repeat 6
Forward 20
Turn Right 60
Repeat 8
Forward 15
Turn Left 30
Turn Right 10
Forward 25
I then have this function to separate everything into an int*string list based on the indentation level. So Repeat 4 would become (0, "Repeat 4"), Forward 10 would be (1, "Forward 10"), and Turn Left 30 would be (3, "Turn Left 30").
/// Creates indentation chart for generating a syntax tree by cycling
/// through a list of strings generated
/// by string.Split and counting the empty strings before each non-empty
//// string.
let indent strs =
let rec inner strs search cmds indent temp =
match strs, search with
| [], _ -> (indent,temp)::cmds
| ""::tail, Cmd -> inner tail Indent ((indent,temp)::cmds) 0 "" //
Newline started -> push cached counter and command string
| ""::tail, Indent -> inner tail Indent cmds (indent+1) temp // Next
level of indent -> increment indent counter
| h::tail, Cmd -> inner tail Cmd cmds indent (temp + " " + h)
| h::tail, Indent -> inner tail Cmd cmds indent (temp + h)
| h::tail, Start -> inner tail Cmd cmds indent (temp + h)
inner strs Start [] 0 "" |> List.rev
let splitIndent (text:string) = text.Trim().Split() |> Array.toList |>
indent
Now this is where I am stuck. I have the list of commands with their indentation levels, but I do not know how to dynamically create a recursive discriminated union. I know how to hardcode it in. It looks something like this,
let tree = [
Forward 75
Repeat (4, [
Forward 10
Turn (Right, 50)
Repeat (6, [
Forward 20
Turn (Right, 60)
Repeat (8, [
Forward 15
Turn (Left, 30)
])])
Turn (Right, 10)])
Forward 25]
but I do not know how to generate something like this based on different input strings.
I have read many StackOverflow posts related to trees, discriminated unions, and creating recursive types like this dynamically but I have not found anything that fits my needs. I have tried modifying the few examples that I have found and the closest I found was an answer by Tomas Petricek at F# transform list to a tree. Plugging in the union cases and the pattern matching for them to get this to work got me a lot closer, but it left off a lot of commands and duplicated some of the others.
This is the best that I have come up with so far, but it does not get all of the commands.
/// Takes the indent,command pairs list and produces a list of commands.
/// Some of these are nested in a tree structure based on their indent.
let buildProgram (diagram:(int*string) list) : Command list =
let rec collect indx lis commands =
match lis with
| [] -> commands
| x::xs ->
match fst x with
| i when i = indx ->
match split (snd x) with
| "Forward"::NUM n::tail -> collect i xs commands#[Forward
n]
| "Turn"::ARG a::NUM n::tail -> collect i xs
commands#[Turn(a,n)]
| "Repeat"::NUM n::tail -> commands#([(Repeat (n, (collect
(i+1) xs [])))] |> List.rev)
| i when i < indx ->
match split (snd x) with
| "Forward"::NUM n::tail -> collect (i-1) xs
commands#[Forward n]
| "Turn"::ARG a::NUM n::tail -> collect (i-1) xs
commands#[Turn(a,n)]
| "Repeat"::NUM n::tail -> commands#([(Repeat (n, (collect
(i-1) xs [])))] |> List.rev)
collect 0 diagram [] |> List.rev
How do you create a recursive discriminated union at runtime based on different inputs?
What you're trying to do there is to write a parser for your indentation-based syntax that would produce values of type Command.
You can certainly roll one by hand, but the general advice would be to use a parser combinator library such as FParsec. FParsec does have a steep learning curve, but it's "the way to go" for writing parsers in F#.
You will find this article particularly helpful if you decide to go with that - Parsing indentation based syntax with FParsec.
Right now I have an SML function:
method([1,1,1,1,2,2,2,3,3,3]);
returns:
val it = [[2,2,2],[3,3,3]] : int list list
but I need it to return:
val it = [[1,1,1,1],[2,2,2],[3,3,3]] : int list list
This is my current code:
- fun method2(L: int list) =
= if tl(L) = [] then [hd(L)] else
= if hd(tl(L)) = hd(L) then hd(L)::method(tl(L)) else [hd(L)];
- fun method(L: int list) =
= if tl(L) = [] then [] else
= if hd(tl(L)) = hd(L) then method(tl(L)) else
= method2(tl(L))::method(tl(L));
As you can see it misses the first method2 call. Any ideas on how I can fix this? I am completely stumped.
Your problem is here if hd(tl(L)) = hd(L) then method(tl(L)) else. This is saying if the head of the tail is equal to the head, then continue processing, but don't add it to the result list. this will skip the first contiguous chunk of equal values. I would suggest separating the duties of these functions a bit more. The way to do this is to have method2 strip off the next contiguous chunk of values, and return a pair, where the first element will have the contiguous chunk removed, and the second element will have the remaining list. For example, method2([1, 1, 1, 2, 2, 3, 3]) = ([1, 1, 1], [2, 2, 3, 3]) and method2([2, 2, 3, 3]) = ([2, 2], [3, 3]). Now, you can just keep calling method2 until the second part of the pair is nil.
I'm not quite sure what you are trying to do with your code. I would recommend creating a tail recursive helper function which is passed three arguments:
1) The list of lists you are trying to build up
2) The current list you are building up
3) The list you are processing
In your example, a typical call somewhere in the middle of the computation would look like:
helper([[1,1,1,1]], [2,2],[2,3,3,3])
The recursion would work by looking at the head of the last argument ([2,3,3,3]) as well as the head of the list which is currently being built up ([2,2]) and, since they are the same -- the 2 at the end of the last argument is shunted to the list being built up:
helper([[1,1,1,1]], [2,2,2],[3,3,3])
in the next step in the recursion the heads are then compared and found to be different (2 != 3), so the helper function will put the middle list at the front of the list of lists:
helper([[2,2,2], [1,1,1,1]], [3],[3,3])
the middle list is re-initialized to [3] so it will start growing
eventually you reach something like this:
helper([[2,2,2], [1,1,1,1]], [3,3,3],[])
the [3,3,3] is then tacked onto the list of lists and the reverse of this list is returned.
Once such a helper function is defined, the main method checks for an empty list and, if not empty, initializes the first call to the helper function. The following code fleshes out theses ideas -- using pattern-matching style rather than hd and tl (I am not a big fan of using those functions explicitly -- it makes the code too Lisp-like). If this is homework then you should probably thoroughly understand how it works and then translate it to code involving hd and tl since your professor would regard it as plagiarized if you use things you haven't yet studied and haven't made it your own work:
fun helper (xs, ys, []) = rev (ys::xs)
| helper (xs, y::ys, z::zs) =
if y = z
then helper(xs, z :: y :: ys, zs)
else helper((y::ys)::xs,[z],zs);
fun method [] = []
| method (x::xs) = helper([],[x],xs);
I am working on writing a recursive function in erlang that given an element X and a list, deletes the element X from the list and returns the new list. I believe I have written it correctly, however, when I run a test on it, I am thrown into an infinite loop..
delete(_,[]) -> [];
delete(X,[X|_]) -> [];
delete(X,[Y|YS]) ->
if X == Y -> YS;
true -> [Y] ++ delete(X,[YS]) % I believe the infinite loop is a result of this line..
end.
I am very new to erlang (this is my second project using the language), so troubleshooting is a bit difficult for me, but if anyone could provide some guidance, it would be much appreciated. Thank you in advance!
delete(_,[]) -> []; %% ok removing anything from an empty list gives an empty list
delete(X,[X|_]) -> []; %% big mistake. If you find the element you want to remove on top
%% of the list, you must remove it and continue with the rest of the list
delete(X,[Y|YS]) ->
if X == Y -> YS; %% this will never occurs since you already test this case
%% in the previous clause. An the result should be delete(X,YS), not YS.
true -> [Y] ++ delete(X,[YS]) %% correct
end.
I don't see where you have an infinite loop, but the second clause will make the recursive calls stop too early.
So your code should be:
delete(_,[]) -> [];
delete(X,[X|Rest]) -> delete(X,Rest);
delete(X,[Y|YS]) -> [Y] ++ delete(X,[YS]).
but a I would recommend to use list comprehension for a very short code and fast execution (it is the code used in lists:filter/2):
delete(X,L) -> [Y || Y <- L, Y =/= X].
% ^ ^ ^
% | | |_ when Y different from X
% | |_________ with all the elements Y from L
% |__________________ make a list
defining the function in the shell, you get:
1> D = fun D(_,[]) -> [];
1> D(X,[X|R]) -> D(X,R);
1> D(X,[Y|R]) -> [Y] ++ D(X,R) end.
#Fun<erl_eval.36.90072148>
2> D(4,[1,2,3,4,5,6]).
[1,2,3,5,6]
3> D1 = fun(X,L) -> [Y || Y <- L, Y =/= X] end.
#Fun<erl_eval.12.90072148>
4> D1(4,[1,2,3,4,5,6]).
[1,2,3,5,6]
5>
First off, I don't know why you would need the second clause. Basically it's saying "If the first item in the list matches the item to be removed, through the whole list away and return an empty one".
The easiest way to do this is to start with the list and an empty list to store the result. Then as we iterate over the items in the list, we add items that don't match to the result and ignore items that match the item we want deleted. This will remove all occurrences of X in List:
delete(X, List) -> delete(X, List, []). % Provide the same API as before
delete(_,[], Result) -> Result; % If the list is empty we are done.
delete(X,[Y|YS], Result) ->
case X == Y of
true ->
delete(X,[YS], Result);
false ->
delete(X,[Y|YS], Result)
end.
But why not use lists:filter/2? It makes it much simpler:
delete(X, List) ->
lists:filter(fun(Item) ->
Item /= X
end, List).