Solved

second question about sale method

Posted on 2014-03-30
10
248 Views
Last Modified: 2014-03-31
0
Comment
Question by:rgb192
  • 5
  • 3
10 Comments
 

Author Comment

by:rgb192
ID: 39965626
Yes. I asked a question on that thread.
0
 

Author Comment

by:rgb192
ID: 39965629
I closed the previous question because expert gave answer to original question.  But on this link (this question) I have another question.
0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39966662
Now, my own reply to that question is that there is only one run in the foreach because there is only one function referenced in that array.

A lambda function is basically one that gets created by code when the script runs, rather than a function that is written in the code itself:

// A lambda function
$a_lamba_function = create_function( '$foo', 'print "{$foo}";' );

// A regular function
function bar($foo)
{
   print "{$foo}";
}

Open in new window


Both of the functions do exactly the same thing - they take in the parameter $foo and print it to the screen. The only difference is that the regular function is already written by you in advance and so the PHP compiler knows about it and how to run it when the script starts. The lambda function, however, doesn't exist until you run the create_function() line of code.

Now, in your code, you create one lambda function and then you tell the processor about it once:

$processor->registerCallback( $logger );

Open in new window

So now, whenever the processor does a sale, it will run that lambda function once for that sale.

So when you run sale on two products:
$processor->sale( new Product( "shoes", 6 ) );
print "\n";
$processor->sale( new Product( "coffee", 6 ) );

...it will run the lambda function once on the shoes product. Then when you run it again on the coffee product, it will again go through foreach() and only run the lambda function once.

If you copied that registerCallback line and ran it twice:

$processor->registerCallback( $logger );
$processor->registerCallback( $logger );

Open in new window


...then any time sale() was run, it would run the logger function twice for that product.
0
 

Author Comment

by:rgb192
ID: 39966704
Sorry about confusing question.

there is only one run in the foreach because there is only one function referenced in that array.
Which one. What is being run?  I just see lambda$x.   Why is each $processor->sale( new Product( "shoes", 6 ) ); a lambda function?

The only difference is that the regular function is already written by you in advance and so the PHP compiler knows about it and how to run it when the script starts. The lambda function, however, doesn't exist until you run the create_function() line of code.
Is this 'late binding' or 'late static binding'?


If you copied that registerCallback line and ran it twice:
I ran 3 times and each shoes and coffee were echoed 3 times each

<?php
require_once( "closures.php" );

$logger = create_function( '$product', 
                           'print "    logging ({$product->name})\n";' );

$processor = new ProcessSale();
$processor->registerCallback( $logger );
$processor->registerCallback( $logger );
$processor->registerCallback( $logger );

//$processor->sale( new Product( "shoes", 6 ) );
$temporary_variable=new Product("shoes", 6);
$processor->sale($temporary_variable);
print "\n";
$processor->sale( new Product( "coffee", 6 ) );
?>

Open in new window

shoes: processing logging (shoes) logging (shoes) logging (shoes) coffee: processing logging (coffee) logging (coffee) logging (coffee)


Is the array saved in the function allowing both shoes and coffee to be run 3x?
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39966827
Why is each $processor->sale( new Product( "shoes", 6 ) ); a lambda function?

That isn't the lambda function. The lambda function is $logger:

$logger = create_function( '$product', 
                           'print "    logging ({$product->name})\n";' );

Open in new window


It might be confusing because in the code, you see the function as $logger, but inside PHP's brain, it keeps track of lambda functions in a separate table and it calls them "lambda_#" like lambda_1, lambda_2, and so on. So $logger is just a variable that references the function that PHP calls lambda_8.

Imagine you are hired to be a salesperson in a store. Every morning, you are given the same list of instructions of how to make a sale:

1. Scan the item.
2. Slide a credit card in the credit card machine.
3. Give the receipt and the item to the buyer.

Every day, you are doing the same three things over and over again every time you make a sale, and you know these things really well because they are predefined instructions. You could turn the above into something that looks like this:

class Salesperson
{
  function sale($item,$credit_card,$buyer)
  {
    $this->scan_item($item);
    $receipt = $this->swipe_credit_card($credit_card);
    $this->give_receipt_and_item($receipt, $item, $buyer);
  }

  function scan_item($item)
  {
    // scan the item
  }

  function swipe_credit_card($card)
  {
    // send credit card data and get a receipt back
    return $receipt;
  }

  function give_receipt_and_item($receipt, $item, $buyer)
  {
    // give the stuff to the person who is buying the item
  }
}

Open in new window


Now let's say that halfway through your day, your boss comes up and tells you, "I want you to start telling customers 'Thank you, THEIR NAME, for shopping with us!' after you give them the receipt."

This is just the boss's wishes, but it's not an official employee rule, so it's not written in the instructions that you get each day.

You can think of your boss's request as a "lambda" function - something that simply comes up in the middle of the day. It could look like this:

$say_thank_you = create_function('$name', 'print "Thank you, {$name}, for shopping with us!";');

Open in new window


However, the sale method that I showed you above doesn't have any way to simply call the lambda function. It is strictly the same three functions over and over again.

So one way of doing this is to save an array into the Salesperson object and have that array hold onto any additional requests that your boss asks you to do:

class Salesperson
{
   private $special_boss_requests = array();

   ....rest of the code...

}

Open in new window


...but now you need a way to add to that array. You could either make the array public or the more "elegant" or "proper" way would be to add a method that manages the requests:

class Salesperson
{
   private $special_boss_requests = array();

   public function add_boss_request($request)
   {
     // Add the request to the list of things to do
     $this->special_boss_requests[] = $request;
   }

   ....rest of the code...

}

Open in new window


Finally, you need to update the sale so that you actually perform the boss's requests:

class Salesperson
{
   private $special_boss_requests = array();

   public function add_boss_request($request)
   {
     // Add the request to the list of things to do
     $this->special_boss_requests[] = $request;
   }

  function sale($item,$credit_card,$buyer)
  {
    $this->scan_item($item);
    $receipt = $this->swipe_credit_card($credit_card);
    $this->give_receipt_and_item($receipt, $item, $buyer);
    
    // Now perform all the boss's special requests, passing the buyer's name to each one
    foreach($this->special_boss_requests as $request)
    {
       call_user_func($request, $buyer); 
    }
  }

   ....rest of the code...

}

Open in new window


So now you might see something like this:

// Start your day
$me = new Salesperson(); 

// You sell a pair of shoes to Joe Smith
$me->sale("shoes", "Joe Smith's credit card", "Joe Smith");

// ########################################################
// At this point, you're not saying thank you yet.
// ########################################################

// The boss comes up with the idea to say thank you (which is our lambda function)
$say_thank_you = create_function('$name', 'print "Thank you, {$name}, for shopping with us!";');

// The boss tells you to do it
$me->add_boss_request($say_thank_you);

// ########################################################
// Now when you perform a sale...
// ########################################################

// Sell some coffee to Mary Smith
$me->sale("coffee", "Mary Smith's credit card", "Mary Smith"); 

// ########################################################
// After doing everything, you say, "Thank you, Mary Smith, for shopping with us!"
// ########################################################

// Now the boss comes up with another idea - make sure you also tell them about our website!

// The boss comes up with the idea to say thank you (which is our lambda function)
$say_website_reminder = create_function('$name', 'print "Also, {$name}, make sure you visit our website at www.lambdashopping.com!";');

// The boss tells you to do it
$me->add_boss_request($say_website_reminder);

// ########################################################
// At this point, you now have $say_thank_you and $say_website_reminder in your special boss requests array, so any time you make a sale from this point on, you will say both things.
// ########################################################

// Sell a car to George Smith
$me->sale("car", "George Smith's credit card", "George Smith");

// ########################################################
// Now George Smith should get hear both things at the end.
// ########################################################

Open in new window


Overall, yes, this is considered late binding or dynamic binding, because the functions are being created after the code starts, and then being looked up and called by dynamic code.
0
 

Author Comment

by:rgb192
ID: 39967290
<?php
class Salesperson
{
  private $special_boss_requests=array();
  
  public function add_boss_requests($request)
  {
    //add the request to the list of things to do
    $this->special_boss_requests[]=$request;
  }
  
  function sale($item,$credit_card,$buyer)
  {
    $this->scan_item($item);
    $receipt = $this->swipe_credit_card($credit_card);
    $this->give_receipt_and_item($receipt, $item, $buyer);
    //now perform all the boss's special requests, passing the buyer's name to each one
    foreach($this->special_boss_requests as $request){
      call_user_func($request,$buyer);
    } 
  }

  function scan_item($item)
  {
    // scan the item
  }

  function swipe_credit_card($card)
  {
    // send credit card data and get a receipt back
    return $receipt;
  }

  function give_receipt_and_item($receipt, $item, $buyer)
  {
    // give the stuff to the person who is buying the item
  }
}

//start your day
$me=new Salesperson();
//you sell a pari of shoes to joe smith
$me->sale("shoes","joe smith credit card","Joe Smith");
//at this point you are not saying thank you yet
//the boss comes up with idea to say thank you which is our lambda function
$say_thank_you=create_function('$name','print "Thank you,{$name} for shopping with us!";');
//the boss tells you to do it
$me->add_boss_requests($say_thank_you);
//now when you perform a sale...
//sell coffee to mary smith
$me->sale("coffee", "mary smith credit card", "mary smith");
//after doing everying you say, thank you mary smith for shopping with us
//now the boss comes up with another idea-make sure you also tell them about our website
//the boss comes up with idea to say thank you which is our lambda function
$say_website_reminder=create_function('$name','print "Also{$name}, make sure you visit our website";');
//the obss tells you to do it
$me->add_boss_requests($say_website_reminder);
//at this point you now have $say_thank_you and say_website_reminder
//sell a car to george smith
$me->sale("car", "george smith credit card","george smith");
//now george smith should hear both at the end

Open in new window


Notice: Undefined variable: receipt in C:\Users\Acer\Documents\NuSphere PhpED\Projects\noname322.php on line 31

Notice: Undefined variable: receipt in C:\Users\Acer\Documents\NuSphere PhpED\Projects\noname322.php on line 31
Thank you,mary smith for shopping with us!
Notice: Undefined variable: receipt in C:\Users\Acer\Documents\NuSphere PhpED\Projects\noname322.php on line 31
Thank you,george smith for shopping with us!Alsogeorge smith, make sure you visit our website


I think swipe card was not used to return variable or populate $this->receipt

I think I understand the anonymous method create_function (adding many bosses tasks to an existing class without altering the the class) It may be above my skill level.
0
 
LVL 34

Accepted Solution

by:
gr8gonzo earned 500 total points
ID: 39967321
Sorry, change:
return $receipt;

To:
return "receipt";

It's all meant as illustration.

To be honest, I RARELY ever use anonymous methods / lambda functions. PHP is generally so flexible and loosely-typed that the predefined functions can often do what you need and they perform better.
0
 

Author Closing Comment

by:rgb192
ID: 39967403
Thanks for example, I think I am understanding.

I have a followup question

http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28401599.html
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now