Cicada ---> Online Help Docs ---> Cicada scripting ---> Functions

Function arguments

Notice that the definition of a Cicada function doesn’t specify any argument list. That means functions in Cicada are automatically able to handle different argument types, variable numbers of arguments, etc. Here is a simple function that can take any arguments whatsoever, as long as there are at least 2 of them.


    > arg2 :: { code, return args[2] }
   
   
    > arg2(5, 3+9, 'C')                            | return a number
   
    12
   
    > arg2(pi, { a := 3, b := 4; return a*b })     | return a function!
   
    { 3, 4 }
   

Cicada functions also don’t specify return types, and as our last example shows a single function can return different kinds of values even from the same return statement. And of course different return statements within the same function can return different types of objects.

What happens if we stick a code marker (or semicolon) inside the function’s argument list? When we try this experiment, we’ll find out is that anything after the function arguments’ code marker isn’t created, or doesn’t run, until the function runs its arguments.


    PrintArgs :: {
       code
       
       print("Before running args: ", args, "\n")
       args()
       print("Afterwards: ", args, "\n")
    }
   

If we call


    PrintArgs( 0.3, " 4", code, " word ", 10 )
   

then the function prints


    Before running args: 0.3 4
    Afterwards: 0.3 4 word 10
   

We can even put coding statements in the function arguments.


    PrintArgs( " *** announcement *** ", code, print("I am an argument list.\n") )
   

which causes the output


    Before running args: *** announcement ***
    I am an argument list.
    Afterwards: *** announcement ***
   

In fact an argument list can run any code whatsoever. A few tricky points: if we define variables, etc. inside of an argument list then they will only exist inside that function’s args variable; this inside the argument list refers to args, not the variable space where the function was called (that will be parent); and return inside of args only stops execution of args’s code.

If we can run the args list, surely we can also pass it parameters? Write a new function to test this:


    > doArgs :: { code, args(9, "lives"), return args }
   
   
    > doArgs( args, code, print(top(args), " arguments were passed\n") )
   
    2 arguments were passed
    { { } }
   

This example is complicated, particularly the function call (2nd command entered at the prompt). On this line, within the parentheses, ‘args’ refers to two different things depending on which side of the code marker it falls on. Before the code marker, args holds the same value it had when the function was called, except wrapped in a second layer of curly braces. But after the code marker, ‘args’ was the parameter list that ran doArgs passed to its arguments, containing the number 9 and the string "lives". Each function call temporarily replaces the existing args variable with its own argument list; the old args comes back when each function exits.

Here’s another example showing more explicitly how args changes across the code marker.


    f :: {
       code
       
       g( print(args, " --> "), code, print(args) )
    }
   
    g :: { code, args("B") }
   

That is, f() runs g(), which in turn runs its own arguments. Now run f().


    > f("A")
   
    A --> B
   

Focus on the line in which function f() calls function g(). The part of args before the code marker is built before g() is run, so here args still has its old value ‘A’. The part of args after the code marker is called by g(), so here args is ‘B’.

Finally, function arguments can contain return statements just like normal functions.


    > doTwice :: { num :: double, code, num = args[1], return args(args(num)) }
   
   
    > doTwice(3, code, return new(args[1]^2))       | calculate (3^2)^2
   
    81
   

To summarize, Cicada’s function arguments are themselves functions. If the syntax for function calls were not so standardized the author would have chosen curly braces, so imagine:


    *** doTwice{ 3, code, return new(args[1]^2) } ***
   

This way of writing a function makes it clear how the arguments are just some function object that’s ordinarily invisible, but appears as args when we run doTwice(). This syntax is not legal by the way --- but if you want to allow it, just duplicate the line defining function calls in cicada.c and change the parentheses to curly braces.


Prev: Defining functions (properly)    Next: Code substitution


Last update: May 8, 2024