I'm trying to create a linked list in Julia.
I have:
mutable struct LLNode{T}
x::T
next::Union{LLNode{T},Void}
prev::Union{LLNode{T},Void}
end
mutable struct LinkedList{T}
count::Int
head::Union{LLNode{T},Void}
tail::Union{LLNode{T},Void}
end
Now, the above code compiles fine. I can also run:x = LLNode(0,nothing,nothing) fine. But when I run y = LinkedList(0,nothing,nothing) I get a no method matching LinkedList(::Int64, ::Void, ::Void) error. What gives?
VERSION returns v"0.6.2"
When you write LLNode(0,nothing,nothing), Julia is able to figure out that it needs to construct an LLNode{Int} based upon the type of the first argument. But in LinkedList(0, nothing, nothing), there's quite literally nothing for it to go on to determine what the type parameter should be, so it doesn't know what to construct.
Instead, you either need to explicitly choose what you want T to be:
julia> LinkedList{Int}(0, nothing, nothing)
LinkedList{Int64}(0, nothing, nothing)
or it can get the T based upon a not-nothing argument:
julia> LinkedList(0, LLNode(0, nothing, nothing), nothing)
LinkedList{Int64}(0, LLNode{Int64}(0, nothing, nothing), nothing)
The reason is that LinkedList requires parameter T. If you pass nothing as second and third argument there is no way for Julia to infer what T is.
Therefore you either have to explicitly specify it, e.g.:
julia> LinkedList{Int}(0, nothing, nothing)
LinkedList{Int64}(0, nothing, nothing)
or pass a second and/or third argument allowing to infer T, e.g. using your x:
julia> LinkedList(0, x, x)
LinkedList{Int64}(0, LLNode{Int64}(0, nothing, nothing), LLNode{Int64}(0, nothing, nothing))
As a side note --- you might want to check out https://github.com/ChrisRackauckas/LinkedLists.jl for an example of a fairly complete implementation of linked list.
Related
I'm going through the book "Haskell programming from first principles" and although the authors try to explain in detail how to reduce expressions, I still have trouble understanding how to read some expressions in the examples provided.
Let's assume the below expression:
(λx.x) Then if I understand things correctly this can be read as: "A lambda function, that accepts an argument x and returns (basically translating . as "returns") the same value x.
Now supposing that that we have the below expression:
(λxy.xy), how do we read that expression in plain English? To make it even more complex the authors then expand (λxy.xy) to (λxy.xy)(λz.a) 1. How are these z and a appearing to the above expression? I was hoping that if I can properly transform the expression to plain English I'd be able to understand where z and a come from.
In lambda calculus, values that are next to each other imply that the first value is being called as a function with the second value as an argument. (λxy.xy) is shorthand for (λx.λy.xy), which means a function that takes an argument x then an argument y, and calls x with argument y. (if you're wondering why there's a function returning a function, it's due to currying). To figure out what (λxy.xy)(λz.a) 1 means, we have to take it step by step:
Undo the shorthand: (λx. λy. xy) (λz. a) 1
Apply first function (λx): (λy. (λz. a) y) 1
Apply second function (λy): (λz. a) 1
Apply third function (λz): a
So, we end up with whatever a is (probably an externally defined constant).
I don't understand why the recursive function always gives me zero result, even if I put values inside the array.
it seems that size (a) == 0
recursive function binarySearch_R (a, value) result (bsresult)
real, intent(in) :: a(6), value
integer :: bsresult, mid
mid = size(a)/2 + 1
if (size(a) == 0) then
bsresult = 0 ! not found
else if (a(mid) > value) then
bsresult= binarySearch_R(a(:mid-1), value)
else if (a(mid) < value) then
bsresult = binarySearch_R(a(mid+1:), value)
if (bsresult /= 0) then
bsresult = mid + bsresult
end if
else
bsresult = mid ! SUCCESS!!
end if
end function binarySearch_R
program hji
read*, a
read*, value
print*, binarySearch_R
end program hji
Chapter 1: The dangers of implicit typing
The first thing I strongly recommend you do is to include the line
implicit none
after the program line. This will suppress implicit typing, and the resulting errors will give you some useful insight into what is happening.
If you did that, you'd get an error message:
$ gfortran -o binsearch binsearch.f90
binsearch.f90:23:12:
read*, a
1
Error: Symbol ‘a’ at (1) has no IMPLICIT type
binsearch.f90:27:25:
print*,binarySearch_R
1
Error: Symbol ‘binarysearch_r’ at (1) has no IMPLICIT type
binsearch.f90:24:16:
read*, value
1
Error: Symbol ‘value’ at (1) has no IMPLICIT type
It doesn't matter that a, value, and binarySearch_R were defined in the function. As the function is not part of the program block, the program doesn't know what these are.
With implicit typing active, it simply assumed that all three are simple real variables. (The type depends on the first letter of the variable name, i through n are integer, everything else is real)
Because this implicit typing can so easily hide coding errors, it's strongly, strongly suggested to always switch it off.
Which also means that we have to declare the variables a and value in the program:
program hji
implicit none
real :: a(6), value
...
end program hji
Chapter 2: How to introduce a function to the program?
So how does the program get access to the function? There are four ways:
The best way: Use a module
module mod_binsearch
implicit none
contains
recursive function binarySearch_R (a, value) result (bsresult)
...
end function binarySearch_R
end module mod_binsearch
program hji
use mod_binsearch
implicit none
real :: a(6), value
...
end program hji
Note that the use statement has to be before the implicit none.
This method leaves the function separate, but callable.
It automatically checks that the parameters (that's something we'll be coming to in a bit) are correct.
Have the function contained in the program.
Between the final line of code of the program and the end program statement, add the keyword contains, followed by the function code (everything from recursive function ... to end function ...).
This is the quick-and-dirty method. You have to be careful with this method as the function will automatically have access to the program's variables unless there's a new variable with that name declared inside the function.
The convoluted way: Interfaces
Create an interface block in the declaration section of your program's source code,
and repeat the interface information in there.
This still allows the compiler to check whether the function is invoked correctly, but it's up to you to ensure that this interface block is correct and matches the actual implementation.
The really, really ugly way: Declare it like a variable, invoke it like a function.
Please don't do that.
Chapter 3: Calling a function
When you call a function, you have to use the parentheses and give it all the parameters that it expects. In your case, you need to type
print *, binarySearch_r(a, value)
Chapter 4: Dynamic arrays as dummy parameters
In the successive recursive calls to the function, the array gets smaller and smaller.
But the dummy parameter is always the same size (6). Not only will this interfere with your algorithm, but this can also lead to dangerously undefined memory access.
Fortunately, specially for intent(in) dummy parameters, you can use dynamic arrays:
recursive function binarySearch_R(a, value)
real, intent(in) :: a(:), value
The single colon tells the compiler to expect a one-dimensional array, but not the length of it. Since you're already using size(a), it should automatically work.
Too long for a comment, but not an answer (and to any Fortran experts reading this, yes, there are one or two places where I gloss over some details because I think they are unimportant at this stage) ...
The way the code is written does not allow the compiler to help you. As far as the compiler is concerned there is no connection between the function and the program. As far as the program is concerned a is, because you haven't told the compiler otherwise, assumed to be a real scalar value. The a in the program is not the same thing as the a in the function - there is no connection between the function and the program.
The same is true for value.
The same is true for binarysearch_r - and if you don't believe this delete the function definition from the source code and recompile the program.
So, what must you do to fix the code ?
First step: modify your source code so that it looks like this:
program hji
... program code goes here ...
contains
recursive function binarySearch_R (a, value) result (bsresult)
... function code goes here ...
end function binarySearch_R
end program hji
This first step allows the compiler to see the connection between the program and the function.
Second step: insert the line implicit none immediately after the line program hji. This second step allows the compiler to spot any errors you make with the types (real or integer, etc) and ranks (scalar, array, etc) of the variables you declare.
Third step: recompile and start dealing with the errors the compiler identifies. One of them will be that you do not pass the arguments to the function so the line
print*, binarySearch_R
in the program will have to change to
print*, binarySearch_R(a, value)
With GHC version 8.0.2 the following program:
import Debug.Trace
f=trace("f was called")$(+1)
main = do
print $ f 1
print $ f 2
outputs:
f was called
2
3
Is it the expected behaviour? If yes, why? I expected the string f was called to be printed twice, one before 2 and one before 3.
Same result on TIO: Try it online!
EDIT
But this program:
import Debug.Trace
f n=trace("f was called:"++show n)$n+1
main = do
print $ f 1
print $ f 2
outputs:
f was called:1
2
f was called:2
3
Try it online!
I suspect those behaviours have something to do with laziness, but my questions remain: is this the expected behaviour and, if yes, why?
Hackage asserts this:
The trace function outputs the trace message given as its first
argument, before returning the second argument as its result.
I don't see it in the first example.
EDIT 2 Third example based on #amalloy comments:
import Debug.Trace
f n=trace "f was called"$n+1
main = do
print $ f 1
print $ f 2
outputs:
f was called
2
f was called
3
Your trace prints when defining f, not when calling it. If you want the trace to happen as part of the call, you should make sure it is not evaluated until a parameter is received:
f x = trace "f was called" $ x + 1
Also, when I run your TIO I don't see the trace appearing at all. trace is not really a reliable way to print things, because it cheats the IO model that the language is built on. The most subtle changes in evaluation order can disturb it. Of course for debugging you can use it, but as even this simple example demonstrates it is not guaranteed to help much.
In your edit, you quote the documentation of trace:
The trace function outputs the trace message given as its first
argument, before returning the second argument as its result.
And indeed this is exactly what happens in your program! When defining f,
trace "f was called" $ (+ 1)
needs to be evaluated. First, "f was called" is printed. Then, trace evaluates to, and returns, (+ 1). This is the final value of the trace expression, and therefore (+ 1) is what f is defined as. The trace has vanished, see?
It is indeed a result of laziness.
Laziness means that merely defining a value doesn't mean it will be evaluated; that will only happen if it's needed for something. If it's not needed, the code that would actually produce it doesn't "do anything". If a particular value is needed the code is run, but only the first time it would be needed; if there are other references to the same value and it is used again, those uses will just directly use the value that was produced the first time.
You have to remember that functions are values in every sense of the term; everything that applies to ordinary values also applies to functions. So your definition of f is simply writing an expression for a value, the expression's evaluation will be deferred until the value of f is actually needed, and as it's needed twice the value (function) the expression computes will be saved and reused the second time.
Lets look at it in more detail:
f=trace("f was called")$(+1)
You're defining a value f with a simple equation (not using any syntactic sugar for writing arguments on the left hand side of the equation, or providing cases via multiple equations). So we can simply take the right hand side as a single expression that defines the value f. Just defining it does nothing, it sits there until you call:
print $ f 1
Now print needs its argument evaluated, so this is forcing the expression f 1. But we can't apply f to 1 without first forcing f. So we need to figure out what function the expression trace "f was called" $ (+1) evaluates to. So trace is actually called, does its unsafe IO printing and f was called appears at the terminal, and then trace returns its second argument: (+1).
So now we know what function f is: (+1). f will now be a direct reference to that function, with no need to evaluate the original code trace("f was called")$(+1) if f is called again. Which is why the second print does nothing.
This case is quite different, even though it might look similar:
f n=trace("f was called:"++show n)$n+1
Here we are using the syntactic sugar for defining functions by writing arguments on the left hand side. Let's desugar that to lambda notation to see more clearly what the actual value being bound to f is:
f = \n -> trace ("f was called:" ++ show n) $ n + 1
Here we've written a function value directly, rather than an expression that can be evaluated to result in a function. So when f needs to be evaluated before it can be called on 1, the value of f is that whole function; the trace call is inside the function instead of being the thing that is called to result in a function. So trace isn't called as part of evaluating f, it's called as part of evaluating the application f 1. If you saved the result of that (say by doing let x = f 1) and then printed it multiple times, you'd only see the one trace. But the when we come to evaluate f 2, the trace call is still there inside the function that is the value of f, so when f is called again so is trace.
Coming from a C# background, I would say that the ref keyword is very useful in certain situations where changes to a method parameter are desired to directly influence the passed value for value types of for setting a parameter to null.
Also, the out keyword can come in handy when returning a multitude of various logically unconnected values.
My question is: is it possible to pass a parameter to a function by reference in Haskell? If not, what is the direct alternative (if any)?
There is no difference between "pass-by-value" and "pass-by-reference" in languages like Haskell and ML, because it's not possible to assign to a variable in these languages. It's not possible to have "changes to a method parameter" in the first place in influence any passed variable.
It depends on context. Without any context, no, you can't (at least not in the way you mean). With context, you may very well be able to do this if you want. In particular, if you're working in IO or ST, you can use IORef or STRef respectively, as well as mutable arrays, vectors, hash tables, weak hash tables (IO only, I believe), etc. A function can take one or more of these and produce an action that (when executed) will modify the contents of those references.
Another sort of context, StateT, gives the illusion of a mutable "state" value implemented purely. You can use a compound state and pass around lenses into it, simulating references for certain purposes.
My question is: is it possible to pass a parameter to a function by reference in Haskell? If not, what is the direct alternative (if any)?
No, values in Haskell are immutable (well, the do notation can create some illusion of mutability, but it all happens inside a function and is an entirely different topic). If you want to change the value, you will have to return the changed value and let the caller deal with it. For instance, see the random number generating function next that returns the value and the updated RNG.
Also, the out keyword can come in handy when returning a multitude of various logically unconnected values.
Consequently, you can't have out either. If you want to return several entirely disconnected values (at which point you should probably think why are disconnected values being returned from a single function), return a tuple.
No, it's not possible, because Haskell variables are immutable, therefore, the creators of Haskell must have reasoned there's no point of passing a reference that cannot be changed.
consider a Haskell variable:
let x = 37
In order to change this, we need to make a temporary variable, and then set the first variable to the temporary variable (with modifications).
let tripleX = x * 3
let x = tripleX
If Haskell had pass by reference, could we do this?
The answer is no.
Suppose we tried:
tripleVar :: Int -> IO()
tripleVar var = do
let times_3 = var * 3
let var = times_3
The problem with this code is the last line; Although we can imagine the variable being passed by reference, the new variable isn't.
In other words, we're introducing a new local variable with the same name;
Take a look again at the last line:
let var = times_3
Haskell doesn't know that we want to "change" a global variable; since we can't reassign it, we are creating a new variable with the same name on the local scope, thus not changing the reference. :-(
tripleVar :: Int -> IO()
tripleVar var = do
let tripleVar = var
let var = tripleVar * 3
return()
main = do
let x = 4
tripleVar x
print x -- 4 :(
I'm looking to call functions dynamically based on the contents found in an association list.
Here is an example in semi-pseudo-code. listOfFunctions would be passed to callFunctions.
listOfFunctions = [('function one', 'value one')
, ('function two', 'value two')
, ('function three', 'value three')]
callFunctions x = loop through functions
if entry found
then call function with value
else do nothing
The crux of the question is not looping through the list, rather, it's how to call a function once I have it's name?
Consider this use case for further clarification. You open the command prompt and are presented with the following menu.
1: Write new vHost file
2: Exit
You write the new vHost file and are not presented with a new menu
1: Enter new directive
2: Write file
3: Exit
You enter some new directives for the vHost and are now ready to write the file.
The program isn't going to blindly write each and every directive it can, rather, it will only write the ones that you supplied. This is where the association list comes in. Writing a giant if/then/else or case statement is madness. It would be much more elegant to loop through the list, look for which directives were added and call the functions to write them accordingly.
Hence, loop, find a function name, call said function with supplied value.
Thanks to anyone who can help out with this.
Edit:
Here is the solution that I've come up with (constructive critiques are always welcome).
I exported the functions which write the directives in an association list as every answer provided said that just including the function is the way to go.
funcMap = [("writeServerName", writeServerName)
,("writeServeralias", writeServerAlias)
,("writeDocRoot", writeDocRoot)
,("writeLogLevel", writeErrorLog)
,("writeErrorPipe", writeErrorPipe)
,("writeVhostOpen", writeVhostOpen)]
In the file which actually writes the hosts, that file is imported.
I have an association list called hostInfo to simulate some dummy value that would be gathered from an end-user and a function called runFunction which uses the technique supplied by edalorzo to filter through both the lists. By matching on the keys of both lists I ensure that the right function is called with the right value.
import Vhost.Directive
hostInfo = [("writeVhostOpen", "localhost:80")
,("writeServerName", "norics.com")]
runFunctions = [f val | (mapKey, f) <- funcMap, (key, val) <- hostInfo, mapKey == key]
You can simply include the function in the list directly; functions are values, so you can reference them by name in a list. Once you've got them out of the list, applying them is just as simple as func value. There's no need to involve their names at all.
Since I am farily new to Haskell I will risk that you consider my suggestion very naive, but anyways here it goes:
let funcs = [("sum", (+3),1),("product", (*3),2),("square", (^2),4)]
[f x | (name, f, x) <- funcs, name == "sum"]
I think it satisfies the requirements of the question, but perhaps what you intend is more sofisticated than what I can see with my yet limitted knowledge of Haskell.
It might be a bit of an overkill (I agree with ehird's reasoning) but you can evaluate a string with Haskell code by using the eval function in System.Eval.Haskell.
EDIT
As pointed out in the comments, hint is a better option for evaluating strings with Haskell expressions. Quoting the page:
This library defines an Interpreter monad. It allows to load Haskell modules, browse them, type-check and evaluate strings with Haskell expressions and even coerce them into values. The library is thread-safe and type-safe (even the coercion of expressions to values). It is, esentially, a huge subset of the GHC API wrapped in a simpler API. Works with GHC 6.10.x and 6.8.x
First we define our list of functions. This could be built using more machinery, but for the sake of example I just make one explicit list:
listOfFunctions :: [(Int, IO ())]
listOfFunctions = [(0, print "HI") -- notice the anonymous function
,(1, someNamedFunction) -- and something more traditional here
]
someNamedFunction = getChar >>= \x -> print x >> print x
Then we can select from this list however we want and execute the function:
executeFunctionWithVal :: Int -> IO ()
executeFunctionWithVal v = fromMaybe (return ()) (lookup v listOfFunctions)
and it works (if you import Data.Maybe):
Ok, modules loaded: Main.
> executeFunctionWithVal 0
"HI"
> executeFunctionWithVal 01
a'a'
'a'
Don't store the functions as strings, or rather, try storing the actual functions and then tagging them with a string. That way you can just call the function directly. Functions are first class values, so you can call the function using whatever name you assign it to.