Sorry for the rather vague title, but I don't know what is wrong with my code.

Here is a Ruby version of what I'm trying to do:

def collect_modulos(base, num)
    result = []
    arr = (1..(num - 1)).to_a        
    while !arr.empty? do
        b = []
        0.upto(num - 1) do |val|
            value = (base * b[-1]) % num
            break if value == b[0]
        arr = arr - b

In plain English: Given a prime number denominator num, I want to get all the numerators of all simple fractions < 1 sorted by their decimal expansions, i.e., in the case of num == 7, I want the result to be

0.142857 = 1/7,
0.428571 = 3/7,
0.285714 = 2/7,
0.857142 = 6/7,
0.571428 = 4/7,
0.714285 = 5/7,

i.e., I want to return the numerators 1,3,2,6,4,5. In the cases where there's more than one cycle of repeating decimal expansions, the code should create more than one list.

My effort in the Wolfram Language:

    collection = Select[collection,Not[MemberQ[smallList]]]

Attempting to evaluate the function collectModulos[10,7] should yield the result {1,3,2,6,4,5}, and collectModulos[14,11] should yield {{1, 3, 9, 5, 4}, {2, 6, 7, 10, 8}}, but instead results in the following message:

Set::setraw: Cannot assign to raw object {1,2,3,4,5,6}.

Set::setraw: Cannot assign to raw object {1,2,3,4,5,6}.

Set::setraw: Cannot assign to raw object {1,2,3,4,5,6}.

General::stop: Further output of Set::setraw will be suppressed during this calculation.

The evaluation also gets stuck in an endless loop.

UPDATE: Since this post asked about an error message and wasn't about the code itself, really, it seems the only way I could let people know what I ended up doing was to post my corrected code here as an edit:

This works as intended.

createLists[num_, base_: 10] := 
  Module[{collection = Range[1, num - 1], bigList = {}},
   If[Mod[base, num] == 0, Return[Nothing]];
   While[Length[collection] >= 1,
    smallList = {collection[[1]]};
    flag = 0;
    While[flag == 0,
     newValue = Mod[base*Last[smallList], num];
     If[newValue == First[smallList], flag = 1, 
      AppendTo[smallList, newValue]]
    AppendTo[bigList, smallList];
    collection = Select[collection, Not[MemberQ[smallList, #]] &];
    ]; bigList;
  • $\begingroup$ I can't say why your function isn't behaving properly in general, but your errors are due to you trying to redefine the variable collection. When you use With to localize a variable, you need to treat it as constant. Use Module instead, unless you understand the difference. $\endgroup$ – Jason B. Sep 12 '18 at 21:21
  • $\begingroup$ OK, that helps. The function is still broken, but now I know where the error is coming from. With Module I'm just getting empty lists. But: progress! $\endgroup$ – pgblu Sep 12 '18 at 21:23

Unlike Ruby, Mathematica is an expression rewriting language. With[{collection=Range[1,num-1]} ... first evaluates Range[1,num-1], then rewrites every instance of collection in the body of the With block to reflect the result. Thus, collection = Select[ ... ] becomes the nonsensical {1,2,3,4,5,6} = Select[ ... ]. It might work if you replace With by Module.

  • $\begingroup$ Why are you using Return? It doesn't do what you think it does. Don't use it until you understand it, and once you understand it, you'll never use it ツ. A sequence of expressions separated by ; yields the result of evaluating the last one, no need to Return the result. $\endgroup$ – John Doty Sep 12 '18 at 21:31
  • $\begingroup$ Yeah, I agree that explicit Return isn't needed here. I do understand what it does. $\endgroup$ – pgblu Sep 12 '18 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.