Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Per Iteration Variable #418

Open
anzhi0708 opened this issue Apr 19, 2023 · 2 comments
Open

Feature Request: Per Iteration Variable #418

anzhi0708 opened this issue Apr 19, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@anzhi0708
Copy link
Contributor

anzhi0708 commented Apr 19, 2023

In this code snippet, the scope of the iteration variable i is global, and the anonymous function captures the variable by reference instead of by value during each iteration, which is consistent with Python but different from functional languages such as OCaml and Scala. To some extent, this behavior goes against intuition.

mut_arr = ![]
for! 0..<5, i =>
  mut_arr.push! ((x: Int)->i)
print! mut_arr

for! mut_arr, f =>
  print! f
  print! f(233)

print! "i = \{i}"

Output:

[<function <lambda> at 0x102d69b20>, <function <lambda> at 0x102d69bc0>, <function <lambda> at 0x102d69ee0>, <function <lambda> at 0x102d69f80>, <function <lambda> at 0x102d6a020>]
<function <lambda> at 0x102d69b20>
4
<function <lambda> at 0x102d69bc0>
4
<function <lambda> at 0x102d69ee0>
4
<function <lambda> at 0x102d69f80>
4
<function <lambda> at 0x102d6a020>
4
i = 4

Scala 3

import scala.collection.mutable.ArrayBuffer
  var functions = ArrayBuffer[()=>Int]()
  for i <- 1 to 10 do
    functions.append(()=>i)
  println(functions)
  println(functions(0)())
  println(functions(1)())
  println(functions(2)())

Output of Scala

ArrayBuffer(hello_world$package$$$Lambda$1391/0x00000008014a1c00@1f521c69, hello_world$package$$$Lambda$1391/0x00000008014a1c00@2b3abeeb, hello_world$package$$$Lambda$1391/0x00000008014a1c00@3aeb267, hello_world$package$$$Lambda$1391/0x00000008014a1c00@13a9cdae, hello_world$package$$$Lambda$1391/0x00000008014a1c00@1c972ae6, hello_world$package$$$Lambda$1391/0x00000008014a1c00@62a41279, hello_world$package$$$Lambda$1391/0x00000008014a1c00@146fa9c0, hello_world$package$$$Lambda$1391/0x00000008014a1c00@49f6c25e, hello_world$package$$$Lambda$1391/0x00000008014a1c00@6c13019c, hello_world$package$$$Lambda$1391/0x00000008014a1c00@2e66f1bd)
1
2
3
@anzhi0708 anzhi0708 added the enhancement New feature or request label Apr 19, 2023
@mtshiba
Copy link
Member

mtshiba commented Apr 23, 2023

I noticed that de-optimization changes the behavior with for!.

for_! = for!

arr = ![]
for_! 0..<5, i =>
    arr.push!(() -> i)

for! arr, f =>
    print! f, f()
<function <lambda> at 0x000001E1B8A3C720> 0
<function <lambda> at 0x000001E1B8B68540> 1
<function <lambda> at 0x000001E1B8B68680> 2
<function <lambda> at 0x000001E1B8B8B060> 3
<function <lambda> at 0x000001E1B8B8B100> 4

De-optimized, pure procedure for! is defined here.

def for__(iterable, body):
for i in iterable:
body(i)

This is what we wanted, but de-optimized version is much slower.

# iteration with 0..<1000000hyperfine "cargo r test.er" # optimized (normal) version
Benchmark 1: cargo r test.er
  Time (mean ± σ):      1.981 s ±  0.016 s    [User: 1.493 s, System: 0.158 s]
  Range (min … max):    1.964 s …  2.014 s    10 runshyperfine "cargo r test.er" # de-optimized version
Benchmark 1: cargo r test.er
  Time (mean ± σ):      3.168 s ±  0.120 s    [User: 2.562 s, System: 0.255 s]
  Range (min … max):    3.088 s …  3.475 s    10 runs

I will try to see if we can get the desired behavior without performance penalty.

@anzhi0708
Copy link
Contributor Author

Thanks for your reply! This is what I was looking for :-)

@mtshiba mtshiba reopened this Apr 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants