Page 1 of 1

Wacky logic with looping and lambdas Rate Topic: -----

#1 hiddenghost  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 39
  • View blog
  • Posts: 621
  • Joined: 15-December 09

Posted 26 March 2012 - 04:02 AM

It must be stressed that this code is just for demonstration purposes
and won't be of much use in production itself.
The idea must be addapted to what you would like to use it for.

The explanations below are way too detailed just to make sure.
You can skip what you already know.

Here's the code in full.
<?php
// You can save this script as wacky_logic.php or what ever you like.
// url should be localhost/wacky_logic.php?time_do=time
// url should be localhost/wacky_logic.php?time_do=day_of_the_week
// url should be localhost/wacky_logic.php?time_do=day_of_the_year
$what = $_GET['time_do'];
$epoch = time();

$func['time'] = function() use($epoch){
    return date('h:s A', $epoch);
};

$func['day_of_the_week'] = function() use($epoch){ 
    return date('l', $epoch); 
};

$func['day_of_the_year'] = function() use($epoch){
    return date('z', $epoch);
};

$logic_continue = 0;
$logic_stop = count($func);
while($logic_continue < $logic_stop){
    if(key($func) === $what){
        $set_time_do = current($func);
        break;
    }
    $logic_continue++;
    next($func);
}

echo $set_time_do();


?>



Each part explained in detail.
Part 1
$what = $_GET['time_do'];


This code uses $_GET to retrieve 'time_do' from the url string. Nothing really special.
The value from 'time_do' is stored in $what.
Part 2
$epoch = time();


The current time on your server is stored in $epoch.
For future reference this script is for use on linux and uses the unix epoch time.
Part 3
$func['time'] = function() use($epoch){
    return date('h:s A', $epoch);
};


$func is an array with lambda functions assigned to it.
The first array member is 'time'.
There is closure and the $epoch variable is passed to $func['time'].

This a really cool element of php that came with version 5.3.

Closure means that an inner function uses the context of it's outer scope.
In this case it's the global scope of the script.
An example:
$outer_variable = 'when this displays you know closure has worked.';
function not_lambda(){
    return $outer_variable; // returns nothing and/or errors
}
$is_lambda = function() use($outer_variable){
    return $outer_variable; // returns value from $outer_variable
};
$is_lambda();



To use closure with php the function must have a use() construct after the function() construct.

Any variable inside the parenthesis of use() will get used by a lambda function.
Part 4
    return date('h:s A', $epoch);


Go to http://php.net/manua...nction.date.php and study up on using the date function.

Part 5
$logic_continue = 0;
$logic_stop = count($func);
while($logic_continue < $logic_stop){
    if(key($func) === $what){
        $set_time_do = current($func);
        break;
    }
    next($func);
    $logic_continue++;
}



The code in Part 5 is where the magic happens.
We want to achieve 3 things with this.
Logical choosing of the $func array functions.
A call to one of the $func functions.
Make that call by reference to save memory.

Part 5 is not really call by reference, but it simulates it by acting lazy
because the assignment to $set_time_do is not done unless the key from $func is equal to $what.

The while statement is using $logic_continue to peserve the limit of the loop so
just in case the the condition of key($func) === $what never evaluates to true the
while will be able to stop eventually.
$logic_stop will of course stop the loop.

next($func) advances to the next element in the $func array.
if(key($func) === $what) checks if the current key of $func is equal to the GET value stored in $what.
This is the where the logic comes into play.
Instead of a bunch of else ifs you have one loop that checks a condition.
It works really well if you have similar operators for multiple conditions, and the same input variable.
You would need to modify it some more to make it more versital.

Now for something a little awkward.

In the while loop $set_time_do is being assigned the value from current($func);.
The gives a copy of the function body of the array member of $func to $set_time_do.

Then when you echo $set_time_do(); you are calling the body of which ever $func passed
the key check through $set_time_do.

In this way it can be said that $set_time_do is any function in $func.

Now let's inspect the next() function.
It does return the body of the function so there truly is not call by reference, but the
body doesn't get used so when $set_time_do = current($func); there is a simulation of assignment
by reference. Only one copy is used for the assignment so memory is saved there.

This works because there is only an assigment if(key($func) === $what).

You can use this to 'mutate' a function so it becomes any function you want it to be.
Multiple levels can be used and because it uses a while incapsulation is only done with
functions and there isn't an huge chain of else if.

I'm sure you could imagine it could be used to check a ton of things in a series.
The while loop could also be used inside of a function so it could be reusable if
you have a lot of similar evaluations.

Multiple functions can be called this way too if the $set_time_do variable is instead an
array and a second while loop does the calling. If you use closure with this you'd have
a hay day proccessing functions dynamically that also can share input.

This example is just the tip of the iceburg with lambdas.
There are more reasons to use lambdas.
Lambdas can be used for one time call backs when you don't want to have to define a one time use function like:
function myFunc($multiply){
    return $multiply;
}
$a = 10;
$b = 7;
myFunc(function() use($a, $B)/>{ return $a*$b; });


When a lambda is assigned to a variable that variable is a pointer to the function assigned to it.
$lambdaMake = 1;
if($lambdaMake == 1){
    $valuesBecome = function(){
        return func_get_args();
    };
}else if($lambdaMake == 2){
    $valuesBecome = function(){
        return func_get_arg(0)*func_get_arg(1);
    };
}
print_r($valuesBecome(2, 4)); // displays an array


This allows alteration of the function at runtime.

You've seen the keyword use being used to grab parameters from the outer scope of the lambdas.
This allows a function defined as a lambda to retrieve values from those variables in the definition of the function.
function multiplyThenExponentIf($a, $b, $doExponent){
    $c = $a*b;
    if(1 === $doExpontent){
        return function() use($c){
            return $c*c; // $c to the power of two.
        };
    }else(0 === $doExponent){
        return $c;
    }
}

echo multiplyThenExponentIf(2, 5, 1); // This will multiply 2 and 5 then multiply 10*10.
echo multiplyThenExponentIf(2, 5, 0); // Just multiply 2 and 5.


This is called closure for those who are new to lambdas.
Being allowed access to the outer scope like this gives you flexibility when you want to encapsulate your code but you don't want to define a special function for it. You can keep your code shorter with this.

All that being said lambdas make it easier to:
  • Make runtime changes to code.
  • Write shorter ecapsulated code.
  • Use variable scope in a more efficient way.
  • Process input for function arguments by using a lambda as a function parameter.


One more thing.
When you make a lambda you need to make sure you use a semicolon after its definition because a lambda is a statement.
function() use(){
//code
};// semicolon



The main script is also attached to this post if you would like to just download and run it.

Is This A Good Question/Topic? 1
  • +

Replies To: Wacky logic with looping and lambdas

#2 codeprada  Icon User is offline

  • Changed Man With Different Priorities
  • member icon

Reputation: 943
  • View blog
  • Posts: 2,353
  • Joined: 15-February 11

Posted 04 April 2012 - 09:16 AM

Nice tutorial. Lambdas are pretty cool, sort of brings the Javascript feel to PHP.

In your wacky_logic.php script you know you could replace the entire while loop with echo $func[$what]();
Was This Post Helpful? 0
  • +
  • -

#3 hiddenghost  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 39
  • View blog
  • Posts: 621
  • Joined: 15-December 09

Posted 04 April 2012 - 10:23 PM

View Postcodeprada, on 04 April 2012 - 10:16 AM, said:

Nice tutorial. Lambdas are pretty cool, sort of brings the Javascript feel to PHP.

In your wacky_logic.php script you know you could replace the entire while loop with echo $func[$what]();


Thanks.

Actually replacing the while loop with just echo $func[$what] would remove the logic from it.
I was trying to assert the ability to check truth.
The example is so simple it kind of seems too expensive to use a loop, but it could be modified to do more complicated things that a simple echo with an index couldn't do.
But ya, that would work too. :tt2:
Was This Post Helpful? 0
  • +
  • -

#4 Dormilich  Icon User is online

  • 痛覚残留
  • member icon

Reputation: 3402
  • View blog
  • Posts: 9,620
  • Joined: 08-June 10

Posted 22 May 2012 - 05:27 AM

not to forget that time() is the default second parameter of date() ... ;)

(but that’s not the point here)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1