Could any one explain why in the following code the name of the function acts in the first part as a * (multiplier)?
(defn bar
([a b] (bar a b 100))
([a b c] (* a b c)))
Giving bar two args (bar 2 3) yields (* 2 3 100)
If might be easier to see what's going on if you reformat it slightly:
(defn bar
([a b] (bar a b 100))
([a b c] (* a b c)))
This is a function with multiple arity - that is, it accepts more than one set of arguments. The first definition accepts two arguments named a and b, and second definition accepts three arguments named a, b, and c. When the first definition of the function is invoked it turns around and invokes the second definition of the function, passing in the a and b arguments which were given to the first definition, and sending the constant value 100 as the third argument. The second definition of bar simply takes the three arguments it's given and multiplies them together using (* a b c).
Hope this helps.
You have defined a function with two overloads - the first takes two arguments and the second three. The two-argument overload simply calls the three-argument version with 100 as the third argument.
Related
Is there a way in OCaml for a variable inside a function to keep its value between function calls? It should work like Pythons default argument, which is a reference to the same object in every function call or the function should rather yield and not explicitly return a value. The effect should be the following (if the function was to return natural numbers):
foo ();;
0
foo ();;
1
Yes this is possible. You need to define a local ref outside of the closure and access its value and modify it every time the closure is used like so:
let foo =
(* local variable x *)
let x = ref 0 in
(* the closure that will be named foo *)
fun () -> let r = !x in
x := r+1; r
I don't know why my code doesn't work.
fun lookup _ [] = 0
| lookup key ((k,v)::entries) =
if k = key
then v
else (lookup key entries)
That's what happened when I tested it in cmd.
val lookup = fn : ''a -> (''a * int) list -> int
- lookup (1,[(1,2),(2,3)]);
val it = fn : ((int * (int * int) list) * int) list -> int
There's nothing wrong with your code, you just didn't call lookup with enough arguments. You make a common mistakes among beginner SML programmers coming from other languages. I'll try to clarify that.
First, the most important thing to know about functions in Standard ML is this:
All functions in Standard ML take exactly one argument.
You might be confused at this point, because your lookup function looks as if it's taking two arguments. It kind of does, but not really.
There are two main "workarounds" (I'm using quotes because this is actually a great feature of the language) for representing functions that take multiple arguments:
1. Using curried functions
If you need to write a function which, conceptually, needs three arguments, then you'd write this:
fun quux a =
fn b =>
fn c =>
(* do something with a, b and c *)
So, quux is:
a function, which takes an argument a and returns
a function, which takes an argument b and returns
a function, which takes an argument c and returns
the result computed using a, b and c
How would you call quux? Like this, right?
((quux a) b) c
But function application is already left associative, so we can actually write this:
quux a b c
We don't need parentheses to "call" functions! In Standard ML parentheses don't mean "call this function". They're used just for grouping expressions together when you want to change associativity, like in mathematics: (1 + 2) * 3.
Because defining quux as above is really cumbersome, there's a syntactic shortcut in the language. Instead of writing this:
fun quux a =
fn b =>
fn c =>
(* do something with a, b and c *)
We can write just this:
fun quux a b c = (* do something with a, b and c *)
But, they're the same thing. quux is still a function which takes just argument a and returns a new function with argument b, which returns a new function which argument c.
Ok, so that was one way of representing multi-argument functions in Standard ML. It's also the one you used to define lookup.
2. Using tuples
Another common way of representing multi-argument functions is to accept a tuple (which may have from 2 to as many components as you wish). Here's the above example using a tuple now:
fun quux args =
case args of
(a,b,c) => (* do something with a, b and c *)
How could we call quux now? Like this:
quux (a,b,c)
Notice that I put a space between quux and the tuple. It's optional, but I do it all the time to keep remembering that function application in standard ML is not represented by parentheses. quux gets called because it's been put before the tuple (a,b,c). Tuples, however, do require parentheses, which is why you're seeing them above.
Again, as before, it's cumbersome to define quux like this:
fun quux args =
case args of
(a,b,c) => (* do something with a, b and c *)
So we can actually use another great feature of the language, pattern matching in argument position, that lets us write this:
fun quux (a,b,c) = (* do something with a, b and c *)
Ok, now we can really answer your question.
You defined lookup using the curried function syntax:
fun lookup _ [] = 0
But you "called" lookup using the tuple syntax, where 1 is the first element of the tuple and [(1,2),(2,3)] is the second element.
lookup (1, [(1,2),(2,3)])
Why doesn't the compiler complain, though. In this unfortunate case, it doesn't because it happens that the type of the first argument of lookup is a tuple. So, you've basically called lookup with a single argument.
What you wanted was this:
lookup 1 [(1,2),(2,3)]
Notice that I'm not defining a tuple anymore.
type foo = A of int * int | B of (int * int)
What is the difference between int * int and (int * int) there? The only difference I see is in pattern matching:
let test_foo = function
| A (f, s) -> (f, s)
| B b -> b
Is it just a syntactic sugar? How do you select which one to use? Is there any performance difference between these two forms?
Yes, there is a performance difference:
In memory A (23, 42) will contain a tag identifying it as an A and the two integers 23 and 42. B (23, 42) will contain a tag identifying it as a B and a pointer to a tuple containing the integers 23 and 42. So there will be one additional memory allocation when creating a B and one additional level of indirection when accessing the individual values inside a B. So in cases where you don't actually use the constructor arguments as a tuple, using A will involve less overhead than using B.
On the other hand your test_foo function will create a new tuple every time it is called with an A value, but when it is called with a B value it will simply return the tuple that already exists in memory. So test_foo is a cheaper operation for B than it is for A. So if you'll be using the constructor's arguments as a tuple and you will do so multiple times for the same value, using B will be cheaper.
So if you're going to be using the constructor arguments as a tuple, it makes sense to use a constructor taking a tuple because you can get at the tuple using pattern matching with less code and because it will avoid having to create tuples from the same value multiple times. In all other cases not using a tuple is preferable because it involves less memory allocation and less indirection.
As already said, the constructor of A takes two int, whereas the constructor of B takes an ordered pair.
so you can write
let bar = A (1, 2)
or
let bar = B (1, 2)
or
let bar = (1, 2)
let baz = B bar
but you cannot write
let bar = (1, 2)
let baz = A bar
Moreover, in your pattern matching, you can still match the content of B as two int, but you cannot match the content of A as value bound to an ordered pair
let test_foo = function
| A a -> a (* wrong *)
| B (f, s) -> (f, s) (* ok *)
They are two different types. The interpretation of this syntax is ambiguous at the * operator. It may be reduced into the form:
type x = Y * Z in which the '*' is associated with the type keyword in OCaml
or
int * int in which the * is used in the capacity of an operator that constructs a tuple
The default precedence takes it to the former. By putting a parenthesis around the (int * int) you override the default precedence and force the latter interpretation.
This is one of the tricky things in OCaml syntax -- even though it looks like you are declaring a constructor with a tuple data type (A of int * int), and even though when you use the constructor, it looks like you are giving a tuple to it (A (2,3)), that is not actually what is happening.
If you actually construct a tuple value and try to pass it to the constructor, it will not compile -- let x = (2,3) in A x. Rather, the * in the constructor definition and the (,) in the constructor use expression are simply the syntax for a constructor of multiple arguments. The syntax imitates that of a constructor with a tuple argument, but is actually separate. The extra parentheses are necessary if you want to actually make a constructor with a single tuple argument.
I'm trying to define an exception in OCaml that accepts a tuple pair of lists as an argument. However, this situation doesn't work?
# exception Foo of string list * string list;;
exception Foo of string list * string list
# let bar = (["a"], ["b"; "c"; "d"]);;
val bar : string list * string list = (["a"], ["b"; "c"; "d"])
# raise(Foo bar);;
Error: The constructor Foo expects 2 argument(s),
but is applied here to 1 argument(s)
However, if I do this, it works
# raise (Foo (["a"], ["b"; "c"; "d"]));;
Exception: Foo (["a"], ["b"; "c"; "d"]).
What's the deal? Thanks!
You're looking at this wrong (though I won't blame you: it's pretty surprising at first). It may seem to you that constructors follow the syntax Name of type where the type part follows normal type syntax (which lets it contain tuples).
In reality, tuples and constructors follow the exact same syntax: a constructor is merely a tuple with a name in front of it:
tuple/constructor == [name of] type [* type] [* type] ...
So, the * in a constructor definition are not part of the tuple syntax, they're part of the constructor syntax. You're literally defining a constructor as being this name, followed by N arguments as opposed to this name, followed by an argument which is a tuple.
The reason behind this subtle difference in behavior is one of performance. Right now, tuples and constructors are represented in memory as such:
[TYPE] [POINTER] [POINTER] [POINTER]
This is a fairly compact and efficient representation. If the multiple arguments of a constructor could indeed be accessed as a tuple, this would require the runtime to represent that tuple independently from the constructor (in order for it to be independently addressable) and so it would look like this:
[TYPE] [POINTER]
|
v
[TYPE] [POINTER] [POINTER] [POINTER]
This would use marginally more memory, require twice as many allocations when using a constructor, and reduce the performance of pattern-matching tuples (because of an additional dereference). In order to retain maximum performance, the name of type * type is represented using the first pattern, and you need to explicitly type name of (type * type) to cut off the * from the of and thus fall back on the second pattern.
Note that both patterns are accessed through the same pattern-matching and construction syntax: name (arg,arg). This means that type inference cannot deduce the pattern based on usage. This is no problem for normal constructors, which are always defined in a type definition, but it causes variants (which need no preliminary definition) to automatically fall back on the second version.
Additional reading on the memory representation of types here.
In this respect, OCaml's exception constructors are just like ordinary constructors:
Constr(1,2,3) is a special syntactic construct in which no triple occurs. On the other hand, a triple occurs in Constr((1,2,3)). The implementation matches this behavior, with Constr(1,2,3) being allocated as a single block, and Constr((1,2,3)) as two blocks, one containing a pointer to the other(the triple). In the run-time representation of Constr(1,2,3) there is no triple to get a pointer to, and if you need one you have to allocate a fresh one.
Note: Constr(((1,2,3))) is equivalent to Constr((1,2,3)). In Constr(((1,2,3))), the middle parentheses are interpreted as going around the expression (1,2,3), and parentheses around an expression are forgotten in the abstract syntax tree.
Foo is a constructor of an exception with 2 parameters. You'd have to decompose the tuple and pass each part into it.
# exception Foo of string list * string list;;
exception Foo of string list * string list
# let bar = (["a"], ["b"; "c"; "d"]);;
val bar : string list * string list = (["a"], ["b"; "c"; "d"])
# let a, b = bar in raise (Foo (a, b));;
Exception: Foo (["a"], ["b"; "c"; "d"]).
If you wish to use a tuple as the single parameter, you must define the exception using parens and pass the tuple in.
# exception Foo of (string list * string list);;
exception Foo of (string list * string list)
# let bar = (["a"], ["b"; "c"; "d"]);;
val bar : string list * string list = (["a"], ["b"; "c"; "d"])
# raise (Foo bar);;
Exception: Foo (["a"], ["b"; "c"; "d"]).
Say I have a function f(a, b, c). Is it possible to create function pointers g and h such that when you use g and h they use a predetermined value for one of the arguments?
For example (*g)(b, c) would be equivalent to f(1, b, c) and (*h)(b, c) would be equivalent to calling f(2, b, c).
The reason why I am doing this is that I am calling a function to which I can obtain a pointer (through dlsym) and this function has drastically different behaviour depending on what the first argument is (so much so that they shouldn't really be called the same thing). What's more the function pointer variable that is being used in the main program can only generally take two arguments as this is a special case where the imported function has three (but really only two are necessary, one is essentially a settings parameter).
Thanks.
I don't see why you can do this if you have defined the function g points to as
void gfunc(int b, int c) {
f (1, b, c);
}
g = &gfunc;
The better way to do this in C++ is probably using functors.