Well, for implementing in any language, you have to translate into the terms of the language. One way is to use strings of characters, iterate through and transform the strings directly. This results in a large string for higher iterations. Then iterate through this resulting string and interpret the characters as turtle commands.
A variant of the string-of-chars, would be to use an array-of-some-kind-of-symbol-type. This same macro-expansion approach will still work.
Another way would be to translate the productions into functions which make the graphics calls directly and make (mutually-)recursive calls to other productions. You need some way of controlling the depth of the recursion. Easiest is to pass an extra variable that gets incremented at each call and check this against a global max_depth variable in each production function.
Another way would be to hybridize the above two approaches, use a set of strings or arrays to model the L-system and perform the recursion in a separate handler function (which can be the same for many different L-systems, ie. it's abstracted, de-coupled). When recursive handle_production()
function detects depth == max_depth
it interprets the symbol as a turtle command instead of recursing.
HTH. There are a number of different approaches exhibited in the answers to my code-golf question: “Sorry, young man, but it's Turtles all the way down!”