DISQUS

Eddie Awad’s Blog: Two Oracle PL/SQL Features You Probably Don’t Know About

  • Laurent Schneider · 2 years ago

    I had a good explanation of mutual recursion at school, a long time ago.


    Simple recursion : you see yourself in a mirror, and in the mirror you see a small mirror where you see you again, and again.


    Mutual recursion is : a boy is drawing a girl, the girl is drawing the boy (with a drawing of herself, drawing him, ...).


    In Pascal, you had to add the keyword forward to do this.


    Have a nice day,
    Laurent

  • Eddie Awad · 2 years ago

    Great analogy Laurent. Back in the old school days, I remember that the classic examples to demonstrate programming recursion were factorials and fibonacci numbers.

  • Don Seiler · 2 years ago

    Could you not put the declarations in the package header?

  • Eddie Awad · 2 years ago

    Don, yes you could, assuming that by package header you meant package specification, and assuming that your modules are created inside a package. In fact, that's one of the solutions I stated in my post: The second option is to declare my_func2 in the package specification.


    However, what if you do not have a package? Instead you have CREATE FUNCTION for example.

  • Laurent Schneider · 2 years ago

    Do not you need a package to use mutual recursion?

  • Eddie Awad · 2 years ago

    Laurent, mutual recursion does not have to be coded in a package. The following stored function for example works like a charm:


    <pre> CREATE OR REPLACE FUNCTION odd_or_even (n NATURAL)
    RETURN VARCHAR2
    IS
    l_return_var VARCHAR2 (4);

    FUNCTION odd (n NATURAL )
    RETURN BOOLEAN; -- forward declaration

    FUNCTION even (n NATURAL)
    RETURN BOOLEAN
    IS
    BEGIN
    IF n = 0
    THEN
    RETURN TRUE;
    ELSE
    RETURN odd (n - 1); -- mutually recursive call
    END IF;
    END even;

    FUNCTION odd (n NATURAL)
    RETURN BOOLEAN
    IS
    BEGIN
    IF n = 0
    THEN
    RETURN FALSE;
    ELSE
    RETURN even (n - 1); -- mutually recursive call
    END IF;
    END odd;
    BEGIN
    IF even (n)
    THEN
    l_return_var := 'even';
    ELSIF odd (n)
    THEN
    l_return_var := 'odd';
    ELSE
    l_return_var := 'oops';
    END IF;

    RETURN l_return_var;
    END odd_or_even;
    /
    </pre>

    Of course, as a general rule, I keep away from using standalone functions and procedures and use packages instead.

  • Laurent Schneider · 2 years ago

    LOL ! There you have encapsulated two functions in one... it is almost a package!


    Seriously, you cannot have


    create function f1 return number is begin return f2; end;
    /


    create function f2 return number is begin return f1; end;
    /

  • Eddie Awad · 2 years ago

    Ah! I see what you mean. Right, you have to "package" the two mutually recursive functions one way or another.

  • Siri · 2 years ago
    Just curious to know, how often one (have to) use 'mutual recursive functions' in a common work place?

    ~ Siri
  • Jeremy Bradshaw · 1 year ago
    The main reason you might not want to declare the mutually recursive procedures in the package specification, is that you might not want them visible from the outside, or you may only want one visible from the outside. Abstraction/information-hiding is a powerful concept.
  • Wiz · 1 year ago
    hello,

    I'm wondering if there is any way that someone could update and add a function to a package without loosing the other functions and or variables declared previously in that package

    best regards,
    Wiz
  • Steven Feuerstein · 1 year ago
    Wiz,

    You can add subprograms to a package without losing other subprograms, but when you change a package and recompile, you lose package "state" - which means that the values of package level variables will no longer be valid and available in your session. No way to avoid this, except to reorganize your package into two separate packages: one that contains your subprograms and another that contains the variables.

    Steven Feuerstein