Iterator-producing function in Nim: works when assigning the iterator, stuck when calling it directly - while-loop

I tried to make a procedure that creates an iterator, as follows:
proc makeCDFrom(start: int): iterator(): int =
result = iterator(): int =
var
i: int = start
while i >= 0:
echo "i:", i
yield(i)
dec(i)
let cdFrom6 = makeCDFrom(6)
for j in cdFrom6():
echo "j:", j
This appears to work as expected:
i:6
j:6
i:5
j:5
i:4
j:4
i:3
j:3
i:2
j:2
i:1
j:1
i:0
j:0
However, initially, I had tried with this slight variation:
proc makeCDFrom(start: int): iterator(): int =
result = iterator(): int =
var
i: int = start
while i >= 0:
echo "i:", i
yield(i)
dec(i)
# Note the direct call:
for j in makeCDFrom(6)():
echo "j:", j
When I try to run the above on https://play.nim-lang.org/, it appears to be stuck. Nothing gets displayed.
Why this difference?

Why?
Because there's a bug.
What can you do about it?
Report the bug to github.com/nim-lang/Nim
And in the meantime use either
let myClosureIter = makeCDFrom(6)
or define your iterator without the factory:
iterator makeCDFrom(start: int): int =
var
i: int = start
while i >= 0:
echo "i:", i
yield(i)
dec(i)
# Note the direct call:
for j in makeCDFrom(6):
echo "j:", j

With a slight change:
proc makeCDFrom(start: int): iterator(): int =
echo "called again"
result = iterator(): int =
var
i: int = start
while i >= 0:
echo "i:", i
yield(i)
dec(i)
And running locally, it's in an infinite loop:
called again
i:6
called again
j:6
called again
i:6
called again
j:6
called again
i:6
...

Related

assignments are not expressions, and only expressions are allowed in this context --- how to resolve this error

I am trying to find the find the result of num1 raised to the power num2:
This is my code ->
fun power(num1 : Int, num2: Int): Int {
var result = 1
while (num2 != 0) {
return result *= num1
num2--
}
}
But the above code is producing the following error -->
Calculator.kt:30:16: error: assignments are not expressions, and only expressions are allowed in this context
return result *= num1
^
Calculator.kt:33:5: error: a 'return' expression required in a function with a block body ('{...}')
}
^
I have read a number of articles but not able to understand. Any help will be highly appreciated.
Thank you
An expression is something that evaluates to a value. An assignment is something that assigns a value to a variable or property.
x *= y is an assignment that is shorthand for x = x * y.
You cannot return an assignment, because it does not evaluate to a value. An assignment contains an expression on the right side of the equals sign, but as a whole does not represent an expression.
There are some other syntax problems you have. You can't modify a function paramter's value (num2-- isn't allowed).
The logic also doesn't make sense. return returns an expression immediately. To fix your code, you need to create a local variable from num2, and move the return statement to the end.
fun power(num1 : Int, num2: Int): Int {
var result = 1
var count = num2
while (count != 0) {
result *= num1
count--
}
return result
}
FYI, there's a function called repeat that is simpler than using a while loop with a counter. It runs the code inside the brackets by the number of times you give.
fun power(num1 : Int, num2: Int): Int {
var result = 1
repeat(num2) {
result *= num1
}
return result
}
You function contains multiple errors, I suggest you to study Kotlin, here a reference. Kotlin website has some more material.
Back to your problem, I have modified your function:
fun power(num1 : Int, num2: Int): Int {
var result = 1
var num2_local = num2
while (num2_local != 0) {
result *= num1
num2_local--
}
return result
}
Problems with your version:
you return from the function immediately
basic types args passed to kotlin functions are passed by const copy, this means that you cannot modify them (e.g num2--)
If you keep a local modifiable reference (var keyword) withing your function, then you achieve your goal

I am getting the val cannot be reassigned compile time error. But I have declared the variable as `var` only

val cannot be reassigned compile time error var variable. Can't we change the array value?
Error
Array.kt:11:3: error: val cannot be reassigned
Code:
import java.util.Scanner
fun main(args: Array< String>){
println("Enter the no")
val scanner = Scanner(System.`in`)
var nos = Array<Int>(5){0}
var i : Int = 1
for (i in 1..3){
nos[i] = scanner.nextInt()
i = i+1
}
println("Given values $nos")
}
The for (i in 1..3) ... statement redefines i for the scope of its body, where it becomes a val (it's actually a separate variable that shadows the i declared outside the loop).
You can fix the code by using different names for these variables, or, in your case, by simply removing var i: Int = 1 and i = i + 1:
val scanner = Scanner(System.`in`)
var nos = Array<Int>(5) { 0 }
for (i in 1..3) {
nos[i] = scanner.nextInt()
}
println("Given values $nos")
UPD (answering to the comment): You can iterate in the opposite direction or using a non-unit step by building a progression with functions downTo and step, both described here in the reference.
var i : Int = 1
for (i in 1..3){
nos[i] = scanner.nextInt()
i = i+1
}
In this code you declared not one, but two variables with the name i because the for header creates its own declaration. Within the loop, only the version declared in the for header is visible, and that one is a val by definition.
Having said that, I'm unclear on what you were trying to achieve since everything looks like it would work just the way you want it without trying to update i in the loop.

Nested inline iterators

Is it possible to have an inline iterator, which accepts another inline iterator as a parameter? My goal is to make a simple pipeline-like processing and get it unrolled into serial C code. An example which I can't get to work:
iterator test2(it: iterator(): int {.inline.}): int =
for i in it():
yield i*2
iterator test1(): int =
yield 10
yield 20
yield 30
for i in test2(test1()):
echo j
With the error:
test.nim(2, 14) Error: type mismatch: got (int) but expected one of:
iterator items[IX, T](a: array[IX, T]): T
iterator items[](E: typedesc[enum]): E:type
iterator items(a: string): char
iterator items[T](s: Slice[T]): T
iterator items[T](a: openArray[T]): T
iterator items[T](a: seq[T]): T
iterator items[T](a: set[T]): T
iterator items(a: cstring): char
> Process terminated with exit code 256
you have 2 options (at least)
define your iterator as {.closure.}
use templates to wrap the iterator and, which is a little ugly but works:
template runIterator(it, exec: untyped): typed =
block:
it(myIterator)
for i in myIterator() :
exec(i*2)
template defineTest1(name: untyped): typed =
iterator `name`(): int {.inline.} =
yield 10
yield 20
yield 30
template defineTest2(name: untyped): typed =
iterator `name`(): int {.inline.} =
yield 5
yield 10
yield 15
template exec(i: int): typed = echo i
runIterator(defineTest1, exec)
runIterator(defineTest2, exec)
edit:
the idea is to use a template instead of an inline iterator and to inject the code - so there is no second iterator but a template.
maybe this makes it clearer:
template test2(it, yielder, exec: untyped): typed =
for i in it() :
let `yielder` {.inject.} = 2 * i
exec
iterator test1(): int {.inline.} =
yield 10
yield 20
yield 30
iterator test1b(): int {.inline.} =
yield 5
yield 10
yield 15
test2(test1, i):
echo i
test2(test1b, i):
echo i

Define a static variable for a recursive function in OCaml

I have a recursive function fact, which can be called from either an expression inside it or an expression outside it.
I would like to associate fact with a variable v, such that each time fact is called from outside (another function), v is initialized, and its value can be changed inside fact, but never can be initialized when fact is called from inside.
The following code suits my need, but one problem is that v is defined as a global variable, and I have to do v := init before calling fact from outside, which I do not find beautiful.
let init = 100
let v = ref init
let rec fact (n: int) : int =
v := !v + 1;
if n <= 0 then 1 else n * fact (n - 1)
let rec fib (n: int) : int =
if n <= 0 then 0
else if n = 1 then (v := !v + 50; 1)
else fib (n-1) + fib (n-2)
let main =
v := init;
print_int (fact 3);
print_int !v; (* 104 is expected *)
v := init;
print_int (fib 3);
print_int !v;; (* 200 is expected *)
Could anyone think of a better implementation?
You can hide the function and value definitions within the body of a containing function as follows:
open Printf
let init = 100
let fact n =
let rec fact counter n =
incr counter;
if n <= 0 then 1 else n * fact counter (n - 1)
in
let counter = ref init in
let result = fact counter n in
(result, !counter)
let main () =
let x, count = fact 3 in
printf "%i\n" x;
printf "counter: %i\n" count (* 104 is expected *)
let () = main ()
You can adapt Martin's solution so that data is shared across various calls:
let fact =
let counter = ref 0 in
fun n ->
let rec fact = ... in
fact n
The idea is to transform let fact = fun n -> let counter = ... in ... into let fact = let counter = ... in fun n -> ...: counter is initialized once, instead of at each call of fact.
A classical example of this style is:
let counter =
let count = ref (-1) in
fun () ->
incr count;
!count
Beware however that you may get into typing trouble if the function was meant to be polymorphic: let foo = fun n -> ... is always generalized into a polymorphic function, let foo = (let x = ref ... in fun n -> ...) is not, as that would be unsound, so foo won't have a polymorphic type.
You can even generalize the counter example above to a counter factory:
let make_counter () =
let count = ref (-1) in
fun () ->
incr count;
!count
For each call to make_counter (), you get a new counter, that is a function that shares state across call, but whose state is independent from previous make_counter () counter creations.
With Ocaml's objects, you can do:
class type fact_counter = object ('self)
method get : int
method set : int -> unit
method inc : unit
method fact : int -> int
end;;
class myCounter init : fact_counter = object (self)
val mutable count = init
method get = count
method set n = count <- n
method inc = count <- count + 1
method fact n =
self#inc;
if n <= 0 then 1 else n * self#fact (n - 1)
end;;
Then you can obtain:
# let c = new myCounter 0;;
val c : myCounter = <obj>
# c#fact 10;;
- : int = 3628800
# c#get;;
- : int = 11
# c#set 42;;
- : unit = ()
# c#fact 10;;
- : int = 3628800
# c#get;;
- : int = 53
I hope you can easily see how to adapt myCounter to include fib ...

ocaml - function without args and global variables

I have a task to do in ocaml and can't find any help information so ask here ;) How to define function which give us something other in each call without using global variables ? I would like to do fun next() which return next odd numbers or next values of factorial.
Like this
# next();;
- : int = 1
# next();;
- : int = 3
# next();;
- : int = 5
# next();;
- : int = 7
Do you have any tips for me ?
Thanks in advance
Greg
let next =
let private_counter = ref (-1) in
fun () ->
private_counter := !private_counter + 2;
!private_counter
You can also encapsulate this in a "counter factory":
let make_counter () =
(* note the () parameter : at each call of make_counter(),
a new "next function" with a fresh counter is generated *)
let private_counter = ...