How to exit a while loop prematurely - while-loop

Suppose I have an infinite while loop and I want to exit the loop. What is the proper way to do so? OCaml does not have break, so I might have to raise an exception to terminate the loop (try while true do ... raise My_exception ... done with My_exception -> ()). Is this the idiomatic way to exit infinite loops? Which exception should I raise inside the loop?

You can use a local exception to make sure that function calls inside your loop are not interfering with your control flow:
let exception Early_exit in
try while ...
raise Early_exit
done;
...
with Early_exit -> ...

Is this the idiomatic way to exit infinite loops?
Yes, it is a rather idiomatic way of exiting from a non-idiomatic infinite loop. There is even a ready to go exception for that, called Exit1, e.g.,
let main () =
try while true do
let continue = work () in
if not continue then raise Exit;
done
with Exit -> ()
With that said, the idiomatic and proper way to encode infinite loops is to use recursion. It is not only more legible but also has the natural way of exiting the loop, e.g., the same infinite loop in the functional style,
let rec main () =
if work () then main ()
1) Though it is better to define your own exception, like #octachron did, to eschew the possibility of clashing with some other code that also relies on this exception.

Related

Why does Iterator::next return an Option instead of just an item?

It seems to me that whether an option is the right type to return should be up to the implementor.
I notice that it goes away when I try to filter or using other collection methods on the items. Is this simply a replacement for has_next? Won't it have potential performance/memory implications?
Because it needs some way to communicate to the caller that there's nothing left to output.
fn main() {
let mut it = vec![1, 2, 3].into_iter();
assert_eq!(it.next(), Some(1));
assert_eq!(it.next(), Some(2));
assert_eq!(it.next(), Some(3));
assert_eq!(it.next(), None); // End of iterator.
}
As for a hypothetical has_next, that can complicate some iterator designs because it requires the iterator to know whether there is another element. This might require the iterator to compute the next element, then store it somewhere. It's also possible to forget to call has_next, or call it but ignore the result.
With next returning an Option, none of this is an issue; an iterator can compute the next item and return it whilst making it impossible for a caller to forget to ensure the returned value actually has something in it.
One thing this does not let you do is "peek" at the iterator to see if there's something more and then change logic based on that answer, without actually consuming the next item. However, that's what the peekable combinator is for, which gives you what amounts to a traditional has_next: peek().is_some().
On your concerns about performance: I've never seen anything to suggest there is any penalty. Anything using an iterator correctly has to check to see if it's reached the end. As for space, a Rust iterator doesn't need to cache the next item, so they're likely to be the same size or smaller than an iterator for a language that uses has_next.
Finally, as noted in comments, Option is not heap allocated. A None is equivalent to a false followed by some uninitialised space (since there's nothing in it), and a Some(v) is equivalent to a true followed by v.

Kotlin infinity loop on list in recursion

This follows infinite loop, in clojure such things just fine
tailrec fun passHeaders (xH: List<Int>)
{
while (xH.isNotEmpty())
{
passHeaders(xH.drop(1))
}
}
List.drop does not mutate the List, but rather produces a new List instance. Thus, you're while loop is infinite.
You don't provide a base case, that's why. Because in each call to passHeaders, xH is it's own copy, it will NEVER not be empty. Remember, when you call drop(), a new list is created.
while (xH.isNotEmpty())
What this says is "while my copy of xH is not empty, call passHeaders.
On the other hand:
if (xH.isNotEmpty())
Will probably do what you intend.
The first call to this function will never terminate if xH isn't empty. .drop() doesn't modify the original list.

Alternative to the try (?) operator suited to iterator mapping

In the process of learning Rust, I am getting acquainted with error propagation and the choice between unwrap and the ? operator. After writing some prototype code that only uses unwrap(), I would like to remove unwrap from reusable parts, where panicking on every error is inappropriate.
How would one avoid the use of unwrap in a closure, like in this example?
// todo is VecDeque<PathBuf>
let dir = fs::read_dir(&filename).unwrap();
todo.extend(dir.map(|dirent| dirent.unwrap().path()));
The first unwrap can be easily changed to ?, as long as the containing function returns Result<(), io::Error> or similar. However, the second unwrap, the one in dirent.unwrap().path(), cannot be changed to dirent?.path() because the closure must return a PathBuf, not a Result<PathBuf, io::Error>.
One option is to change extend to an explicit loop:
let dir = fs::read_dir(&filename)?;
for dirent in dir {
todo.push_back(dirent?.path());
}
But that feels wrong - the original extend was elegant and clearly reflected the intention of the code. (It might also have been more efficient than a sequence of push_backs.) How would an experienced Rust developer express error checking in such code?
How would one avoid the use of unwrap in a closure, like in this example?
Well, it really depends on what you wish to do upon failure.
should failure be reported to the user or be silent
if reported, should one failure be reported or all?
if a failure occur, should it interrupt processing?
For example, you could perfectly decide to silently ignore all failures and just skip the entries that fail. In this case, the Iterator::filter_map combined with Result::ok is exactly what you are asking for.
let dir = fs::read_dir(&filename)?;
let todos.extend(dir.filter_map(Result::ok));
The Iterator interface is full of goodies, it's definitely worth perusing when looking for tidier code.
Here is a solution based on filter_map suggested by Matthieu. It calls Result::map_err to ensure the error is "caught" and logged, sending it further to Result::ok and filter_map to remove it from iteration:
fn log_error(e: io::Error) {
eprintln!("{}", e);
}
(|| {
let dir = fs::read_dir(&filename)?;
todo.extend(dir
.filter_map(|res| res.map_err(log_error).ok()))
.map(|dirent| dirent.path()));
})().unwrap_or_else(log_error)

Error Handling in Go

I have a go code like this,
main()
{
do something
do something
.
.
.
do something
}
Now, I don't know which "do something" is throwing an error. Is it possible in Go to catch the error and print it? How?
Go language did not include exception handling mechanism. However, it has panic/recover mechanism which gives a little bit of exception handling.
You probably want recover. Alternatively, check the return values from those functions. It's idiomatic in go to call the error value ok, and immediately check it.
meh, ok := do_something()
if !ok {

Is there some clever way to write a lua object so that it doubles up as an iterator?

Lets say I have some "object" that I've defined elsewhere. Maybe it represents a set of items, but is more complex than a simple table. Whatever it may be, it would be logical to iterate over it.
As such, it has a iterator method defined. So I can write this:
local myObject = AbstractObject:new()
for obj in myObject:iterator() do
obj:foo()
end
What I'm wondering is if there is some metamethod trickery that I can do, which will allow me to write this:
local myObject = AbstractObject:new()
for obj in myObject do
obj:foo()
end
So is there?
One slight change to your example would make the semantics a lot less painful:
local myObject = AbstractObject:new()
for obj in myObject() do
obj:foo()
end
That way, you can use a metatable to define the __call metamethod to return myObject:interator(), with code that looks something like this in AbstractObject:new():
setmetatable(newobject, {__call = function() return newobject:iterator() end})
Without the iterator construction, you'll be effectively reusing a single iterator for multiple iterations, which means you'll need to keep the iterator state in the object/creation closure, and reset it after it finishes so the next call will restart the iteration again. If you really want to do this, the best solution would really be to write something for the specific iteration implementation, but this would perform the generic iteration:
local iterator
--table.pack is planned for 5.2
local pack = table.pack or function(...)
local t = {...}
t.n = select('#',...)
return t
end
--in 5.1 unpack isn't in table
local unpack = table.unpack or unpack
function metamethods.__call(...)
if not iterator then
iterator = newobject:iterator()
end
local returns = pack(iterator(...))
if returns[1] == nil then
--iteration is finished: next call will restart iteration
iterator = nil
end
return unpack(returns, 1, returns.n)
end
Again: This should really be adjusted to fit your use case.
The object used after in must be a function, which will be called repeatedly by the generic for loop.
I'm not sure if you can make a table or user object callable like a function, but even then the problem would be that your object can only have one internal iterator state - i.e. it would not allow multiple iterations over the same object (neither concurrently nor sequentially), unless you are somehow explicitly resetting it.
As answered by Stuart, you could use the __call metamethod suitably to return the iterator, but then you would have to write
for obj in myObject() do
obj:foo()
end
This is not quite what we want.
Reading a bit more in PiL, I see that there are more components used in the for loop: the invariant loop state, and the current value of the control variable, which are passed to the iterator function in each call. If we don't provide them in the in expression, they are initialized to nil.
Thus, my idea would be to use these values to distinguish the individual calls.
If you can create a next(element) function for your collection which returns for each element the next one, the implementation would be simple:
metatable.__call = function(_state, _last)
if(_last == nil) then
return obj:first()
else
return obj:next(_last)
end
end
But often we would not have something like this, then it gets more complicated.
I thought about using coroutines here, but these still need a factory method (which we want to avoid).
It would result in something similar like what Stuart wrote (i.e. saving the iterator state somewhere in the object itself or in some other variable related to the object), and using the parameter and/or the iterators result to decide when to create/clean the iterator object/state.
Nothing won here.