Language Reference >> Predefined Interfaces and Classes >> Generator

本文深入探讨了PHP中的生成器概念,包括其基本用法、如何使用send和yield进行双向通信,以及异常处理等高级特性。
<?php
// +----------------------------------------------------------------------
// | Language Reference >> Predefined Interfaces and Classes >> Generator
// +----------------------------------------------------------------------
// | Author: alexander <gt199899@gmail.com>
// +----------------------------------------------------------------------
// | Datetime: 2017-11-13 17:48
// +----------------------------------------------------------------------
// | Perfect Is Shit
// +----------------------------------------------------------------------

/**
 * Generator implements Iterator {
 *  --Methods--
 *      public mixed current ( void )
 *      public mixed getReturn ( void )
 *      public mixed key ( void )
 *      public void next ( void )
 *      public void rewind ( void )
 *      public mixed send ( mixed $value )
 *      public mixed throw ( Throwable $exception )
 *      public bool valid ( void )
 *      public void __wakeup ( void )
 *
 */

/**
 * current 返回当前产生的值
 */
function t(){
    for($i=1;$i<=10;$i++){
        yield $i;
    }
    return 100;
}
$gen = t();
//var_dump($gen->current());
var_dump($gen->getReturn());
// 输出 int(1)

/**
 * getReturn 返回生成器函数中return值
 * 确保使用getReturn的时候生成器函数返回return值而不是yield值,否则会报错;
 */
$gen = (function() {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;
// 输出:
// 1
// 2
// 3

/**
 * key 返回yield值的key
 * 如果没有key,返回0
 */
$gen = (function() {
    yield 1 => 2;
})();
var_dump($gen->key());
var_dump($gen->current());
// 输出:
// int(1)int(2)
$gen = (function() {
    yield 1;
})();
var_dump($gen->key());
var_dump($gen->current());
// 输出:
// int(0)int(1)

/**
 * next 生成器继续执行
 * 生成器已经执行到末尾,不会自动next到开始
 */
$gen = (function(){
    yield 1;
    yield 2;
    yield 3;
})();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
// 输出:
// int(1)int(2)int(3)NULL

/**
 * rewind 重置生成器
 * 如果生成器已经执行,则会抛出一个异常
 */

/**
 * send 向生成器传入一个值
 */
function printer()
{
    while (1) {
        $string = yield;
        echo $string . PHP_EOL;
    }
}

$printer = printer();
$printer->send('Hello world!');
$printer->send('How are you?');
// 输出:
// Hello world!
// How are you?
//

// +----------------------------------------------------------------------
/**
 * 以下是一个通过send和yield实现的双向通信的例子,从鸟哥那里拿来的
 * 需要注意的是:
 *      官网说法:send方法,向生成器传入一个值,并且把这个值作为当前执行yield的结果,并且继续执行生成器;
 *      也就是说,send方法做了三件事情;
 *      send方法返回的值很有意思,他返回生成器继续执行的下一个yield返回的值,注意,不是本次yield表达式返回的值,一定要注意;
 */
function gen()
{
    $ret = (yield 'yield1');
    var_dump($ret);
    $ret = (yield 'yield2');
    var_dump($ret);
}

$gen = gen();
// 这里输出当前生成器的值,第一个yield的值:yield1
var_dump($gen->current());
// 这里向生成器发送ret1,并且继续执行生成器到下一个yield,执行生成器遇到gen里面第一个var_dump,则输出第一个yield表达式的值,即为send传入的值ret1;
// 这里的var_dump($gen->send),则为send方法的返回值,send方法的返回值为下一个yield表达式返回的值,即为yield2;
// 所以这里输出:
//      string(4) "ret1"   (the first var_dump in gen)
//      string(6) "yield2" (the var_dump of the ->send() return value)
var_dump($gen->send('ret1'));
// 这里向生成器发送ret2,并且继续执行生成器,执行生成器遇到gen里面第二个var_dump,输出第二个yield表达式的值,即为send传入的值ret2;
// 由于生成器后面没有yield表达式,所以send方法返回为null
// 故输出:
//      string(4) "ret2"   (again from within gen)
//      NULL               (the return value of ->send())
var_dump($gen->send('ret2'));

// 输出:
// string(6) "yield1"
// string(4) "ret1"   (the first var_dump in gen)
// string(6) "yield2" (the var_dump of the ->send() return value)
// string(4) "ret2"   (again from within gen)
// NULL               (the return value of ->send())
// +----------------------------------------------------------------------

/**
 * throw 向生成器中抛入一个异常
 */
$gen = (function () {
    try {
        yield 1;
    } catch (Exception $e) {
        echo $e->getMessage();
    }
})();
$gen->throw(new Exception('gen throw exception'));
// 输出:
// gen throw exception

/**
 * valid 检查迭代器是否被关闭
 * 当前生成器中执行到最后,则为关闭,否则为开启
 */
$gen = (function () {
    yield 1;
})();

var_dump($gen->valid());
$gen->next();
var_dump($gen->valid());
// 输出:
// bool(true)bool(false)

/**
 * __wakeup 抛出一个异常以表示生成器不能被序列化;
 */
$gen = (function () {
    yield 1;
})();
var_dump($gen->__wakeup());
// 抛出异常
// Fatal error: Uncaught Exception: Unserialization of 'Generator' is not allowed in ...
### ETH to DMAOMR Conversion or Transaction in Blockchain In the context of blockchain and cryptocurrencies, converting or transacting between two different tokens (such as ETH and DMAOMR) typically involves interacting with smart contracts on a blockchain platform like Ethereum. Below is an explanation of how this process might be implemented. To convert or transact ETH to DMAOMR, one would usually interact with a decentralized exchange (DEX) or utilize a token swap mechanism through a smart contract. The following steps outline the technical aspects of such a transaction: #### Smart Contract Interaction A typical interaction with a smart contract for token conversion involves sending Ether (ETH) to a contract address that handles the conversion logic. This contract will then issue the equivalent amount of DMAOMR tokens based on predefined rules or market rates[^2]. ```javascript // Example: Interacting with a smart contract for token conversion const Web3 = require('web3'); const web3 = new Web3('https://mainnet.infura.io/v3/YOUR-INFURA-PROJECT-ID'); // Contract ABI and Address const contractABI = [/* ABI of the smart contract */]; const contractAddress = '0xYourSmartContractAddress'; // Initialize contract instance const contract = new web3.eth.Contract(contractABI, contractAddress); // Function to send ETH and receive DMAOMR async function convertEthToDmaomr(amount) { const account = '0xYourEthereumAccountAddress'; const gasPrice = await web3.eth.getGasPrice(); // Approve and send transaction const tx = { from: account, to: contractAddress, value: web3.utils.toWei(amount.toString(), 'ether'), gas: 2000000, gasPrice: gasPrice }; try { const receipt = await web3.eth.sendTransaction(tx); console.log('Transaction successful:', receipt.transactionHash); } catch (error) { console.error('Transaction failed:', error.message); } } ``` The above code demonstrates how to send ETH to a smart contract for conversion into another token. It assumes the existence of a smart contract capable of handling such transactions[^3]. #### Unit Conversion When dealing with blockchain transactions, it is essential to handle unit conversions correctly. For example, when retrieving the balance of an account, the result is often returned in Wei (the smallest unit of Ether). Converting this value to Ether or other units can be done using utility functions provided by libraries like Web3.js. ```javascript // Example: Retrieving and converting balance async function getBalance(address) { const balanceInWei = await web3.eth.getBalance(address); const balanceInEther = web3.utils.fromWei(balanceInWei, 'ether'); return `${balanceInEther} ETH`; } ``` This ensures that the balance is displayed in a human-readable format[^1]. #### Security Considerations When performing transactions involving cryptocurrency, security is paramount. Always validate the smart contract's address and ABI before interacting with it. Additionally, ensure that the network being used matches the intended blockchain (e.g., Ethereum Mainnet vs. Testnet)[^4].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值