Elixir:为生成器分配变量(变量范围?)

Elixir: to assign variable in for generator(variable scope?)

我正在解决,find the largest prime factor of the number, Project Euler problem3

以下 Elixir 代码抛出警告,并且不在 if 块(赋值)中求值我认为:

num = 13195

range = num
         |> :math.sqrt
         |> Float.floor
         |> round

for dv <- 2..range do
  if rem(num, dv) == 0 and div(num, dv) != 1 do
    num = div(num, dv)
  end
end

num
|> IO.puts

警告是:

$ elixir 3.exs
warning: variable "num" is unused
  3.exs:10

warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable)
  3.exs:10

13195

$ elixir -v
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.5.3

如何更新(分配)num? (以下 Python 和 Javascript 代码适用于相同的问题):


# 3.py
from math import ceil, sqrt

num = 600851475143

for div in range(2, ceil(sqrt(num)) + 1):
    if num%div == 0 and num/div != 1:
        num /= div

assert int(num) == 6857

// 3.js
var num = 600851475143;

var range = Array.from({length: Math.trunc(Math.sqrt(num))}, (x, i) => i + 2)

for (const div of range) {
  if (num%div === 0 && num/div != 1) {
      num /= div;
  }
}

var assert = require('assert');

assert(num === 6857)

您实际上是在创建一个新变量并从外部作用域隐藏该变量

你可以这样改写

num = 13195

range =
  num
  |> :math.sqrt()
  |> Float.floor()
  |> round

num =
  2..range
  |> Enum.reduce(num, fn elem, acc ->
    if rem(acc, elem) == 0 and div(acc, elem) != 1 do
      div(acc, elem)
    else
      acc
    end
  end)

IO.puts num

更多关于阴影的信息:

+------------------------------------------------------------+
| Top level                                                  |
|                                                            |
|  +------------------------+     +------------------------+ |
|  | Module                 |     | Module                 | |
|  |                        |     |                        | |
|  | +--------------------+ |     | +--------------------+ | |
|  | | Function clause    | |     | | Function clause    | | |
|  | |                    | |     | |                    | | |
|  | | +----------------+ | |     | | +----------------+ | | |
|  | | | Comprehension  | | |     | | | Comprehension  | | | |
|  | | +----------------+ | |     | | +----------------+ | | |
|  | | +----------------+ | | ... | | +----------------+ | | |
|  | | | Anon. function | | |     | | | Anon. function | | | |
|  | | +----------------+ | |     | | +----------------+ | | |
|  | | +----------------+ | |     | | +----------------+ | | |
|  | | | Try block      | | |     | | | Try block      | | | |
|  | | +----------------+ | |     | | +----------------+ | | |
|  | +--------------------+ |     | +--------------------+ | |
|  +------------------------+     +------------------------+ |
|                                                            |
+------------------------------------------------------------+

Any variable in a nested scope whose name coincides with a variable from the surrounding scope will shadow that outer variable. In other words, the variable inside the nested scope temporarily hides the variable from the surrounding scope, but does not affect it in any way.

source