Nested function: Difference between revisions

From Rosetta Code
Content added Content deleted
(Java)
(→‎{{header|Go}}: Add Fortran.)
Line 71: Line 71:


Console.WriteLine(MakeList(". "));</lang>
Console.WriteLine(MakeList(". "));</lang>

=={{header|Fortran}}==
Fortran allows the user to define functions (and subroutines also) but from the start these are compiled as separate items and cannot themselves contain the definition of another function (or subroutine) - except for the special form allowing the definition of what is called an arithmetic statement function, such as follows:<lang Fortran> FUNCTION F(X)
REAL X
DIST(U,V,W) = X*SQRT(U**2 + V**2 + W**2) !The contained function.
T = EXP(X)
F = T + DIST(T,SIN(X),ATAN(X) + 7) !Invoked...
END</lang>
This (deranged) function contains within it the definition of function DIST (which must be achieved in a single arithmetic statement), and which has access to all the variables of its containing function as well as its own parameters. Such functions are defined following any declarations of variables, and precede the executable statements.

With the advent of F90 comes the CONTAINS statement, whereby within a function (or subroutine) but oddly, at its ''end'' (but before its END) appears the key word CONTAINS, after which further functions (and subroutines) may be defined in the established manner. These have access to all the variables defined in the containing routine, though if the contained routine declares a name of the containing routine then that outside name becomes inaccessible.

Such contained routines are not themselves allowed to contain routines, so that the nesting is limited to two levels - except that arithmetic statement functions are available, so that three levels could be employed. Languages such as Algol, pl/i, Pascal, etc. impose no such constraint.


=={{header|Go}}==
=={{header|Go}}==

Revision as of 12:28, 22 September 2016

Task
Nested function
You are encouraged to solve this task according to the task description, using any language you may know.

In many languages, functions can be nested, resulting in outer functions and inner functions. The inner function can access variables from the outer function. In most languages, the inner function can also modify variables in the outer function.

The Task

Write a program consisting of two nested functions that prints the following text.

1. first
2. second
3. third

The outer function (called MakeList or equivalent) is responsible for creating the list as a whole and is given the separator ". " as argument. It also defines a counter variable to keep track of the item number. This demonstrates how the inner function can influence the variables in the outer function.

The inner function (called MakeItem or equivalent) is reponsible for creating one of the list items. It accesses the separator from the outer function and modifies the counter.

References:

ALGOL 68

<lang algol68>PROC make list = ( STRING separator )STRING:

    BEGIN
       INT counter := 0;
       PROC make item = ( STRING item )STRING:
            BEGIN
               counter +:= 1;
               whole( counter, 0 ) + separator + item + REPR 10
            END; # make item #
       make item( "first" ) + make item( "second" ) + make item( "third" )
    END; # make list #

print( ( make list( ". " ) ) ) </lang>

C++

Works with: C++11

<lang cpp>#import <iostream>

  1. import <string>
  2. import <sstream>

std::string makeList(std::string separator) {

 int counter = 1;
 auto makeItem = [=](std::string item) mutable {
   return (std::ostringstream() << counter++ << separator << item << "\n").str();
 };
 return makeItem("first") + makeItem("second") + makeItem("third");

}

int main() {

 std::cout << makeList(". ");
 return 0;

}</lang>

C#

<lang csharp>string MakeList(string separator) {

   var counter = 1;
   var makeItem = new Func<string, string>((item) => {
       return counter++ + separator + item + "\n";
   });
   return makeItem("first") + makeItem("second") + makeItem("third");

}

Console.WriteLine(MakeList(". "));</lang>

Fortran

Fortran allows the user to define functions (and subroutines also) but from the start these are compiled as separate items and cannot themselves contain the definition of another function (or subroutine) - except for the special form allowing the definition of what is called an arithmetic statement function, such as follows:<lang Fortran> FUNCTION F(X)

      REAL X
      DIST(U,V,W) = X*SQRT(U**2 + V**2 + W**2)    !The contained function.
       T = EXP(X)
       F = T + DIST(T,SIN(X),ATAN(X) + 7)         !Invoked...
     END</lang>

This (deranged) function contains within it the definition of function DIST (which must be achieved in a single arithmetic statement), and which has access to all the variables of its containing function as well as its own parameters. Such functions are defined following any declarations of variables, and precede the executable statements.

With the advent of F90 comes the CONTAINS statement, whereby within a function (or subroutine) but oddly, at its end (but before its END) appears the key word CONTAINS, after which further functions (and subroutines) may be defined in the established manner. These have access to all the variables defined in the containing routine, though if the contained routine declares a name of the containing routine then that outside name becomes inaccessible.

Such contained routines are not themselves allowed to contain routines, so that the nesting is limited to two levels - except that arithmetic statement functions are available, so that three levels could be employed. Languages such as Algol, pl/i, Pascal, etc. impose no such constraint.

Go

<lang go>package main import "fmt"

func makeList(separator string) string {

   counter := 1
   makeItem := func(item string) string {
       result := fmt.Sprintf("%d%s%s\n", counter, separator, item)
       counter += 1
       return result
   }
   return makeItem("first") + makeItem("second") + makeItem("third")

}

func main() {

   fmt.Print(makeList(". "))

}</lang>

Haskell

<lang haskell>import Control.Monad.ST import Data.STRef

makeList :: String -> String makeList separator = concat $ runST $ do

 counter <- newSTRef 1
 let makeItem item = do
       x <- readSTRef counter
       let result = show x ++ separator ++ item ++ "\n"
       modifySTRef counter (+ 1)
       return result
 mapM makeItem ["first", "second", "third"]


main :: IO () main = putStr $ makeList ". "</lang>

J

J does not have nested scopes, so they must be emulated. (The design philosophy here is that nesting tends to become difficult to understand when taken too far, so the coder and designer should be mildly penalized with extra work for choosing nesting as opposed to some other problem solving approach.)

That said, emulating a single level of nesting is relatively trivial and does not reflect the complexities necessary for more elaborate (and more difficult to understand) cases:

<lang J>MakeList=: dyad define

 sep_MakeList_=: x
 cnt_MakeList_=: 0
 ;MakeItem each y

)

MakeItem=: verb define

 cnt_MakeList_=: cnt_MakeList_+1
 (":cnt_MakeList_),sep_MakeList_,y,LF

)</lang>

Example use:

<lang J> '. ' MakeList 'first';'second';'third' 1. first 2. second 3. third </lang>

Java

Works with: Java version 8

Since version 8, Java has limited support for nested functions. All variables from the outer function that are accessed by the inner function have to be _effectively final_. This means that the counter cannot be a simple int variable; the closest way to emulate it is the AtomicInteger class.

<lang java>import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function;

public class NestedFunctionsDemo {

   static String makeList(String separator) {
       AtomicInteger counter = new AtomicInteger(1);
       Function<String, String> makeItem = item -> counter.getAndIncrement() + separator + item + "\n";
       return makeItem.apply("first") + makeItem.apply("second") + makeItem.apply("third");
   }
   public static void main(String[] args) {
       System.out.println(makeList(". "));
   }

}</lang>

JavaScript

<lang javascript>function makeList(separator) {

 var counter = 1;
 function makeItem(item) {
   return counter++ + separator + item + "\n";
 }
 return makeItem("first") + makeItem("second") + makeItem("third");

}

console.log(makeList(". "));</lang>

Lua

<lang lua>function makeList(separator)

 local counter = 1
 local function makeItem(item)
   return counter .. separator .. item .. "\n"
 end
 return makeItem("first") .. makeItem("second") .. makeItem("third")

end

print(makeList(". "))</lang>

Objective-C

<lang objc>NSString *makeList(NSString *separator) {

 __block int counter = 1;
 
 NSString *(^makeItem)(NSString *) = ^(NSString *item) {
   return [NSString stringWithFormat:@"%d%@%@\n", counter++, separator, item];
 };
 
 return [NSString stringWithFormat:@"%@%@%@", makeItem(@"first"), makeItem(@"second"), makeItem(@"third")];

}

int main() {

 NSLog(@"%@", makeList(@". "));
 return 0;

}</lang>

OCaml

<lang ocaml>let make_list separator =

 let counter = ref 1 in
 let make_item item =
   let result = string_of_int !counter ^ separator ^ item ^ "\n" in
   incr counter;
   result
 in
 make_item "first" ^ make_item "second" ^ make_item "third"

let () =

 print_string (make_list ". ")</lang>

Interestingly, on my computer it prints the numbers in reverse order, probably because the order of evaluation of arguments (and thus order of access of the counter) is undetermined:

Output:
3. first
2. second
1. third

Perl

<lang perl>sub makeList {

   my $separator = shift;
   my $counter = 1;
   sub makeItem { $counter++ . $separator . shift . "\n" }
   makeItem("first") . makeItem("second") . makeItem("third")

}

print makeList(". ");</lang>

PHP

Works with: PHP version 5.3+

<lang php><? function makeList($separator) {

 $counter = 1;
 $makeItem = function ($item) use ($separator, &$counter) {
   return $counter++ . $separator . $item . "\n";
 };
 return $makeItem("first") . $makeItem("second") . $makeItem("third");

}

echo makeList(". "); ?></lang>

Python

Works with: Python version 3+

<lang python>def makeList(separator):

   counter = 1
   def makeItem(item):
       nonlocal counter
       result = str(counter) + separator + item + "\n"
       counter += 1
       return result
   return makeItem("first") + makeItem("second") + makeItem("third")

print(makeList(". "))</lang>

Ruby

<lang ruby>def makeList(separator)

 counter = 1
 makeItem = lambda {|item|
   result = "#{counter}#{separator}#{item}\n"
   counter += 1
   result
 }
 makeItem["first"] + makeItem["second"] + makeItem["third"]

end

print makeList(". ")</lang>

Scheme

<lang scheme>(define (make-list separator)

 (define counter 1)
 
 (define (make-item item)
   (let ((result (string-append (number->string counter) separator item "\n")))
     (set! counter (+ counter 1))
     result))
 
 (string-append (make-item "first") (make-item "second") (make-item "third")))

(display (make-list ". "))</lang>

Standard ML

<lang sml>fun make_list separator =

 let
   val counter = ref 1;
   fun make_item item =
     let
       val result = Int.toString (!counter) ^ separator ^ item ^ "\n"
     in
       counter := !counter + 1;
       result
     end
 in
   make_item "first" ^ make_item "second" ^ make_item "third"
 end;

print (make_list ". ")</lang>

Swift

<lang swift>func makeList(_ separator: String) -> String {

 var counter = 1
 
 func makeItem(_ item: String) -> String {
   let result = String(counter) + separator + item + "\n"
   counter += 1
   return result
 }
 
 return makeItem("first") + makeItem("second") + makeItem("third")

}

print(makeList(". "))</lang>

zkl

zkl functions don't have direct access to another functions scope, they are not nested. If a function is defined in another function, the compiler moves it out and hands you a reference to the function. So, you are unable to modify variables in the enclosing scope unless you are given a container which can be modified. Partial application can be used to bind [copies] of scope information to a function, that information is fixed at the point of application and becomes strictly local to the binding function (ie changes do not propagate). A Ref[erence] is a container that holds an object so it can be modified by other entities. <lang zkl>fcn makeList(separator){

 counter:=Ref(1);  // a container holding a one. A reference.
 // 'wrap is partial application, in this case binding counter and separator
 makeItem:='wrap(item){ c:=counter.inc(); String(c,separator,item,"\n") };
 makeItem("first") + makeItem("second") + makeItem("third")

}

print(makeList(". "));</lang>

Output:
1. first
2. second
3. third