Okay so I am new to the Lua language so this could be a super stupid question, but I have come across the following statement and I have no idea what it means (even after some searching)
if (...) then
-- Doing some stuff
end
What does the ... mean?
... is used in vararg functions. Its value is a list of all the "extra" arguments (i.e. those that follow the last named argument of the current function.)
(...) (like any other expression in parentheses) adjusts the result to one value (the first one in the list.)
So that if statement effectively means "if the first variadic argument exists and is not false or nil."
Examples:
local function f1(...)
if (...) then
return true
else
return false
end
end
local function f2(x, ...)
if (...) then
return true
else
return false
end
end
print(f1()) -- false
print(f1(1)) -- true
print(f1(1, 2)) -- true
print(f1(1, nil)) -- true
print(f1(nil, 2)) -- false
print(f2()) -- false
print(f2(1)) -- false
print(f2(1, 2)) -- true
print(f2(1, nil)) -- false
print(f2(nil, 2)) -- true
At the top level (i.e. not inside a function . . . end form) it still works the same way, but the current function is a chunk (i.e. script or module.)
If it is a module, (...) gives the module name. But then the if(...) test would not be useful because the first argument is always a string.
If it's a script, (...) gives the first command-line argument (and the if(...) tests whether any arguments were given.)
... is used in the function parameter to indicate that the function is variadic. It can be used inside the function as an expression, representation the function's extra arguments.
For instance, this function takes a fixed argument plus variable arguments:
function vafun(num, ...)
if (...) then
for _, v in ipairs{...} do
print(v)
end
else
print("empty var")
end
end
The if(...) tests if the variable arguments part is empty.
vafun(3, 4, 5)
vafun(3)
vafun()
Output:
4
5
empty var
empty var
Related
I have created MyList abstract class to implement the list, the reason for not using already present list implementation is I am learning Scala and this was exercise for the same course. I am writing a zipWith function to create a new list with concatenation of individual items for example:
list 1: list = [1,2,3]
list 2: listOfStrings = ["Hello", "This is", "Scala"]
and I am expecting output like: [1-Hello, 2-This is, 3-Scala]
I wrote zipWith function as mentioned below:
override def zipWith[B, C](list: MyList[B], zip: (A, B) => C): MyList[C] = {
if(list.isEmpty) throw new RuntimeException("Lists do not have the same length")
else new Cons(zip(h, list.head), t.zipWith(list.tail, zip))
}
And I am trying to call this function using this statement:
println(list.zipWith[String, String](listOfStrings, (Int,String)=>_+"-"+_))
But I am getting an error:
I could not infer the type of the parameter $3 of expanded function:
($3, _$4) => _$3 + "-" + _$4.
Type for this variable is clearly mentioned as Int still I am getting this error. This could be solved using:
println(list.zipWith[String, String](listOfStrings, _+"-"+_))
I am not able to understand why earlier statement fails, even after giving the type for the required variable
The syntax (Int,String)=>_+"-"+_ doesn't mean what you think.
It represents a function taking two parameters with some name but unknown type: (Int: ???, String: ???) => _+"-"+_.
Thus the compiler is raising an error because it indeed have no clue about the types.
You should either:
write it with explicit variable names: (i: Int, s: String) => s"$i-$s". (Notice the usage of interpolation which is recommended over adding int and string),
or declare the function separately like this: val f: (Int, String) => String = _+"-"+_.
I think the compiler is confused on which variable to match each underscore. This explicit expression works for me:
println(list.zipWith[String, String](listOfStrings, (a:Int, b:String) => a+"-"+b))
I am trying to return a value if something occurs when iterating through a list. Is it possible to return a string if X happens when iterating through the list, otherwise return another string if it never happens?
let f elem =
if not String.contains str elem then "false" in
List.iter f alphlist;
"true";
This is not working in my implemented method sadly.
OCaml is a functional language, so you pretty much need to concentrate on the values returned by functions. There are ways to return different values in exceptional cases, but (IMHO) the best way to learn is to start just with ordinary old nested function calls.
List.iter always returns the same value: (), which is known as unit.
For this reason, the expression List.iter f alphlist will also always return () no matter what f does.
There is another kind of list-handling function that works by maintaining a value across all the calls and returning that value at the end. It's called a fold.
So, if you want to compute some value that's a kind of summary of what it saw in all of the string lists in alphlist, you should probably be using a fold, say List.fold_left.
Here is a function any_has_7 that determines whether any one of the specified lists contains the integer 7:
let any_has_7 lists =
let has_7 sofar list =
sofar || List.mem 7 list
in
List.fold_left has_7 false lists
Here's how it looks when you run it:
# any_has_7 [[1;2]; [3;4]];;
- : bool = false
# any_has_7 [[1;2]; [5;7]; [8;9]];;
- : bool = true
In other words, this function does something a lot like what you're asking for. It returns true when one or more of the lists contains a certain value, and false when none of them contains the value.
I hope this helps.
I am new to SML and I have written a program that takes 3 integer numbers (n,z,k) and wants to compare them with a value given in the program, if the statement is correct it will return true, else false. conditions and values should be equal simultaneously, I mean program will return true if all these numbers are equal to the value given in the program, so my if statement should check 3conditions at the same time.
my problem is that I don't know how I can write all these 3conditions in one if clause, because SML don't recognize for example & or ^ as and!
for example i want to check whether if(n==8 && k==5 && z==9). what should I use instead of &
here is the code:
fun EvalR (n: int , k: int , z:int) =
if (n=8 ???) then true
else false;
Since Ashkan Parsa referred to the CS317 SML Style Guide, I thought I would point out what you might derive from it.
Let function names start with a lower case, e.g. evalR.
Don't write if ... then true else false; simply write ....
Some disagree; type annotations certainly are helpful, but so is type inference.
As nazila says, the and operator in Standard ML is called andalso.
So,
fun evalR (n, k, z) =
n = 42 andalso k = 43 andalso z = 0
It might seem comfusing that the function body contains =s at the same time as the function being defined with a = to separate the function arguments from the function body. Just think of the latter =s as value operators and the first = as a part of declaring things (like types, values, functions, etc.)
I found it. we can use andalso in SML.
I am trying to delete the empty entries from a char list in sml.
This is my function but when I try to call it, it doesn't work and brings a fatal error.
fun no_spaces([]) = raise Empty
| no_spaces(e::f) = if(e = #" ") then no_spaces(f) else e::no_spaces(f);
no_spaces [#"a",#"a",#" ",#"d",#" "];
What am I doing wrong?
Thank you
P.S Or if this is not possible, then how can I delete empty spaces from a string?
I suspect that by raise Empty you meant to return the empty list rather than trigger a runtime error. You have indicated in the comments that you have fixed that particular bug, but it can't hurt to say a bit more about when you should return nil and when you should raise empty.
As a general rule of thumb, if you are defining a function which sends lists to lists and the output list is constructed by processing the elements of the input list one by one (e.g. return the list of even elements in an int list, which involves checking the parity of each element in turn) then your basis case should be something like fun f [] = [] because an empty input corresponds to nothing left to process, and if there is nothing left to process then there is nothing left to return.
But -- if the goal of the function on lists is to return an element of the list (such as the first even entry) then it is natural to raise Empty:
fun firstEven [] = raise Empty
| firstEven (x::xs) = if x mod 2 = 0 then x else firstEven xs;
Here raise Empty makes perfect: since [] doesn't contain any integer it doesn't contain a first even one to return. Thus, this is an error situation which (ideally) should be addressed with a handle somewhere in the calling function.
An argument could be made that raise Empty should never be used since SML provides an alternative error handling method which uses the option type constructor. The function firstEven could be rewritten
fun firstEven [] = NONE
| firstEven (x::xs) = if x mod 2 = 0 then SOME x else firstEven xs;
in this case the calling function would pattern match on the returned value(using the two patterns NONE and SOME x) rather than providing an exception handler. Conceptually this second approach is cleaner and possibly even more efficient (it seems to be in F#, see this, I'm not sure about SML).
See this for a discussion of the two error handling methods in SML.
I need a function that recursively returns (not prints) all values in a list with each iteration. However, every time I try programming this my function returns a list instead.
let rec elements list = match list with
| [] -> []
| h::t -> h; elements t;;
I need to use each element each time it is returned in another function that I wrote, so I need these elements one at a time, but I can't figure this part out. Any help would be appreciated.
Your function is equivalent to :
let rec elements list =
match list with
| [] -> []
| h :: t -> elements t
This happens because a ; b evaluates a (and discards the result) and then evaluates and returns b. Obviously, this is in turn equivalent to:
let elements (list : 'a list) = []
This is not a very useful function.
Before you try solving this, however, please understand that Objective Caml functions can only return one value. Returning more than one value is impossible.
There are ways to work around this limitation. One solution is to pack all the values you wish to return into a single value: a tuple or a list, usually. So, if you need to return an arbitrary number of elements, you would pack them together into a list and have the calling code process that list:
let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ()) (* Print four values *)
Another less frequent solution is to provide a function and call it on every result:
let my_function action =
action 1 ;
action 2 ;
action 3 ;
action 4
in
my_function print_int
This is less flexible, but arguably faster, than returning a list : lists can be filtered, sorted, stored...
Your question is kind of confusing - you want a function that returns all the values in a list. Well the easiest way of returning a variable number of values is using a list! Are you perhaps trying to emulate Python generators? OCaml doesn't have anything similar to yield, but instead usually accomplishes the same by "passing" a function to the value (using iter, fold or map).
What you have currently written is equivalent to this in Python:
def elements(list):
if(len(list) == 0):
return []
else:
list[0]
return elements(list[1:])
If you are trying to do this:
def elements(list):
if(len(list) > 0):
yield list[0]
# this part is pretty silly but elements returns a generator
for e in elements(list[1:]):
yield e
for x in elements([1,2,3,4,5]):
dosomething(x)
The equivalent in OCaml would be like this:
List.iter dosomething [1;2;3;4;5]
If you are trying to determine if list a is a subset of list b (as I've gathered from your comments), then you can take advantage of List.mem and List.for_all:
List.for_all (fun x -> List.mem x b) a
fun x -> List.mem x b defines a function that returns true if the value x is equal to any element in (is a member of) b. List.for_all takes a function that returns a bool (in our case, the membership function we just defined) and a list. It applies that function to each element in the list. If that function returns true for every value in the list, then for_all returns true.
So what we have done is: for all elements in a, check if they are a member of b. If you are interested in how to write these functions yourself, then I suggest reading the source of list.ml, which (assuming *nix) is probably located in /usr/local/lib/ocaml or /usr/lib/ocaml.