Some Questions

57 views
Skip to first unread message

Naveen Madraj Neelakandan

unread,
Jun 25, 2015, 1:38:12 AM6/25/15
to wren...@googlegroups.com
Hello Everyone,

I've just been looking through Wren over the past week or so and it looks really interesting! Got a few questions though.

a) How does recursion work in Wren? As you can see from the simple Wren fibonacci function (recursion.wren), I wasn't sure of how to make the recursive call to the fibonacci function, inside the fibonacci function. Maybe it is in the documentation somewhere but I couldn't find it.

b) Why does the attached file else-error.wren not compile? It appears the close parentheses of the if clause and the "else" keyword need to be on the same line for it to compile? This seems restrictive.

c) Whats the best way to contribute to Wren? Can I start hacking on the TODOs in the code like the documentation states?

Cheers,
Naveen
recursion.wren
else-error.wren

Michel Hermier

unread,
Jun 25, 2015, 2:07:46 AM6/25/15
to wren-lang

Hi,
The syntax is a little funky due to the fact that there is no expression separator, so the newline is significant. Therefore the "else" should be on the same line as the }

In addition your Fibonacci code use wrong variable n instead of num in the recursion call.

Cheers,
   Michel

--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/22f224b0-cbfe-4e4c-a6dc-94b5dbff1987%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Naveen Madraj Neelakandan

unread,
Jun 25, 2015, 2:39:09 AM6/25/15
to wren...@googlegroups.com
Hi Michel,

Thanks for the quick reply. I have fixed the variable naming error ( I'm prone to such errors when not inside the safety of an IDE :) ).
I still get an error stating that "fib_recursion is undefined" though, as I would expect as the function is bound to the var fib_recursion only in the outer scope.
Any comment on how to call the function recursively? 
I am sure there must be a better way than to employ a fixed-point combinator?

Thanks,
Naveen

Michel Hermier

unread,
Jun 25, 2015, 2:52:30 AM6/25/15
to wren-lang

I'm on a train right now, and will not have access to a computer for the next 5 days. In the test/benchmark there should be a Fibonacci implementation. Afaik it should use a class to perform the invocation. This looks odd, but Fn is not a first citizen in the language, since it is more object oriented then imperative. Therefore it is mostly here as a short hand with the extra arguments elimination for the class:
class MyFunc {
call(myargs...) {...}
}
In addition the var is only defined when the assignation is performed. This is the real reason behind the error.

Bob Nystrom

unread,
Jun 30, 2015, 11:00:33 AM6/30/15
to wren-lang
Sorry for the long delay. I got behind on other stuff in life and I'm gradually clawing my way back to the top of my pile of email and pull requests.

Here's a fixed version of your recursion program:

var fib_recursion
fib_recursion = new Fn {|num|
  if (num == 1 || num == 0) {
    return 1
  } else {
    return fib_recursion.call(num - 1) + fib_recursion.call(num - 2)
  }
}

IO.print(fib_recursion.call(4))

Let me walk you through the changes I made, from top to bottom:

Assign fib_recursion after it's declared

Like many other languages, a local variable does not come into scope until after its initializer has executed. That means you can't refer to a variable within its own initializer. In other words, this is an error:

var a = a // Error: a isn't in scope yet here.

You rarely run into this in normal initializers since the variable clearly doesn't even have a value yet. Where you see it is when the initializer is a recursive function declaration:

var a = new Fn { a } 

Here you still have the same problem where you are referring to a inside its own initializer. You can fix that by assigning the variable after it's declared:

var a
a = new Fn { a }

By the second line, a is already declared (and initialized to null), so it's fine to refer to it.

Put else on the same line as the preceding }

Newlines are significant in Wren and are used to terminate statements. When you have code like:

if (condition) {
  ...
} // <--
else ...

When it sees the newline after the "}", it interprets that to mean that the entire if statement is complete and there is no else clause. Then it gets to the else on the next line and generates a parse error.

We could, of course, make the parser smart enough to handle this, but I like keeping the grammar simple and I don't think it's a bad thing to encourage a certain formatting style.

Invoke functions using .call()

Wren doesn't allow you to call a function stored in a variable just by adding () after the variable name. In Wren, functions are just objects that implement a method named .call() to invoke their body.

The reasons for this are subtle and are explained in some detail here: https://github.com/munificent/wren/issues/158#issuecomment-72594167

In practice, you don't run into this very often since Wren encourages you to define methods more than functions. It's not as strictly class-based as Java, but it still generally encourages you to put stuff in classes.

A class-based implementation of your script could look like:

class Recursive {
  static fib(num) {
    if (num == 1 || num == 0) {
      return 1
    } else {
      return fib(num - 1) + fib(num - 2)
    }
  }
}

IO.print(Recursive.fib(4))

Note how the ".call" goes away. An even simpler implementation is:

class Recursive {
  static fib(num) { num <= 1 ? 1 : fib(num - 1) + fib(num - 2) }
}

:)

c) Whats the best way to contribute to Wren? Can I start hacking on the TODOs in the code like the documentation states?

Yes! You can also take a look at the issue tracker.

When I started hacking on Wren, it was just me, so many of the TODOs were originally written as kind of reminders to myself. That means they may not have as much context or detail as I'd like. Before you get started on something, it wouldn't hurt to ask here and I'll fill you in on some details.

In some cases, the reason it's still a TODO and hasn't been done yet is because it's more difficult than it initially seems. :)

If you just want to get your feet wet, one really helpful think you can do is just try writing Wren programs like you have here. Being a Wren user is surprisingly effective at finding bugs or highlighting missing features.

Welcome to Wren! :D

- bob


Naveen Madraj Neelakandan

unread,
Aug 1, 2015, 11:39:44 PM8/1/15
to Wren
Hi Bob,

I didn't realize you had replied back to this. Thanks for taking the time to write that up. Was much clearer!! Maybe some of that should go into the documentation.

Naveen
Reply all
Reply to author
Forward
0 new messages