... is not a function error

18 views
Skip to first unread message

Edwin Tomlins

unread,
Mar 30, 2023, 1:23:33 AM3/30/23
to Pencil Code
Hi all,

I have a piece of code which uses a button.  When the button is pressed, a function is called.

It works fine the first time I press the button, but every subsequent press it throws an error "It says: "roll is not a function" Is there a missing comma?".  I don't quite understand why this error is being thrown, and why it's only thrown on the second press, not the first press.  Can you see what I'm doing incorrectly?

http://mrtomlins.pencilcode.net/edit/Zilch

Thanks

Andy Petusky

unread,
Dec 23, 2023, 9:04:15 PM12/23/23
to Pencil Code
Hi Mr. Tomlins,

You've run into a namespace collision, a situation in which a variable referenced in a function is (unintentionally) the same as one already declared in the containing scope.  Your problem is that the reference to "roll" within the function body does not create a new variable,  but rather points to the variable which references the function.  As a result, the variable roll is reassigned to the results of the function call "random [1..6]" when the function is first called.  Subsequent calls to roll reference a number, not a function.

In your case, the issue arises here because of how CoffeeScript declares variables when it compiles to JavaScript.   There are several  potential workarounds. Perhaps the conceptually most simple approach is to give the variable within the function body a different name.  For example:

#Roll 5 dice
ret = []
roll = (n) ->
  for i in [0..n-1]
    roll2 = random [1..6]  # I CHANGED THE REFERENCE TO roll HERE AND IN SUBSEQUENT LINES IN THE BODY OF THE FUNCTION.
    score = 0
    if roll2 is 1
      score += 100
    if roll2 is 5
      score += 50
    else
      score += 0
    ret.push [roll2,score]
    debug ret
  return ret

button 'Roll five', ->
#  ret = []
  currentroll = roll(5)

Arguably a better approach is to include another parameter in your function definition (even though you won't reference that parameter it when you call the function). Even if you use the exact same variable name (as I do below), it won't cause problems.

#Roll 5 dice
ret = []
roll = (n, roll) ->   #I INCLUDE A SECOND PARAMETER, roll.  THIS CREATES A NEW VARIABLE THAT EXISTS (ONLY) WITHIN THE FUNCTION BODY
  for i in [0..n-1]
    roll = random [1..6]
    score = 0
    if (roll is 1)
      score += 100
    if (roll is 5)
      score += 50
    else
      score += 0
    ret.push [roll,score]
    debug ret
  return ret
button 'Roll five', ->
#  ret = []
  currentroll = roll(5)

If you are interested in digging deeper into this, you might check out some notes I put together at pencilcoder.net, a project I'm working on which is not directly connected to Pencil Code, but assumes use of the Pencil code platform.  Specifically, check out these notes: https://pencilcoder.net/notes/CustomFunctions_Notes.html#BeyondTheLesson-Scope.

Sincerely,
Andy
Reply all
Reply to author
Forward
0 new messages