我是函数式编程的新手,我想学习如何通过编写函数来构建程序(这样我就可以根据自己的需要选择使用单点编程)
我有一长串命令式代码,在伪代码中是这样的:
function do_complicated_stuff(input) {
//do some DB stuff and get information about A,B,C,D
//prepare Output A
//prepare Output B
//prepare Output C
//prepare Output D
if(condition) {
A = "I am A1"
B = "I am B1"
C = "I am C1"
D = "I am D1"
} else {
//do the same as above, but change to I am A2, B2, C2, D2
}
array = {A, B, C, D};
return array;
}
有没有办法把它写成函数应用程序而不是命令式代码?我想要简化的事情:我不想显式处理A,B,C,D所以我不想进行像do_other_stuff这样的函数调用(A,B,C,D,db_stuff_required_for_A,db_stuff_required_for_B)
很明显我希望有一个像do_other_stuff(one_item)
这样的函数,但如果one_item
为A
且condition
,则最终返回值应为“我是A1”如果condition
为false并且one_item
为B
,则为“我是B2”。
我知道如何以OOP方式执行此操作,我想我会有一堆对象知道如何处理他们自己的数据,我只需要调用item.other_stuff()然后就可以了解它。我将如何以更具功能性的方式编写相同的东西,组成许多简短的函数,这些函数最终能够为我提供所需的“我是L#”结果?请注意,对于有时重叠的八种情况中的每一种情况,您都需要不同的数据库信息,并且有时每种情况之间完全不同。所以它目前非常复杂而且不是很简单,因为我当前代码中的函数超过100行,并且明确地处理了所有8个案例。更糟糕的是,同样的事情以不同的方式再次完成,其他输出格式如“This is A1”。所以我想将输出与处理和数据库调用分开。假设我可以选择任何语言来重新实现此功能,因此请使用您想要的任何功能。我该怎么做?我需要哪些抽象/语言功能?
支持自己,这是一个实际的PHP代码,它不漂亮,只处理一半的情况(但我想扩展它以涵盖所有内容,当然,而不是使用旧代码)
function do_complicated_stuff(Buysellitem $item) {
$result = new stdClass();
global $user_currency;
$curr_obj = get_cached('getCurrenciesDAO', 'load', array($item->currencyID));
$price = CurrencyConverter::convert($curr_obj->abbr, $user_currency->abbr, $item->price);
$dollarPrice = CurrencyConverter::convert($curr_obj->abbr, 'USD', $item->price);
$item_cat_id = $item->categoryId;
if(!empty($item_cat_id)) {
$item_cat = DAOFactory::getCategoryDetailsDAO()->load($item_cat_id)->categoryNameEn;
}
$designer_obj = DAOFactory::getUsersDAO()->load($item->userID);
$item_images = DAOFactory::getBuysellitemimagesDAO()->queryByBuySellID($item->buySellID);
foreach($item_images as $cur_image) {
if($cur_image->isDefault) {
if(!empty($cur_image->aspectRatio) && $cur_image->aspectRatio > 0){
$main_image_height = round(498 / $cur_image->aspectRatio);
$main_image = DOMAIN . SELLIMG_PATH .
File_Controller::getImage($cur_image->buySellItemImagePath, 498, $main_image_height);
}else{
$main_image = '';
}
}
}
$designerName = decode_entities($designer_obj->companyName);
$trim_cat = !empty($item_cat) ? ' #' . strtolower(preg_replace('/\s+/', '', $item_cat)) : '';
$desc = decode_entities($item->description);
$trim_desc = str_short($desc, SHARE_LENGTH);
$item_link = SHARE_ITEM_LINK . $item->buySellID;
$item_name = str_short(decode_entities($item->buySellName), TW_SHARE);
if(!empty($price)) {
$decimals = $price < 10 ? 2 : 0;
$dollarDecimals = $price < 10 ? 2 : 0;
$priceFormatted = number_format($price, $decimals, '.', '');
$dollarPriceFormatted = number_format($dollarPrice, $dollarDecimals, '.', '');
//if the currency is SEK it doesn't have a sign, so show the abbreviation instead
$curr_abbr = empty($curr_obj->sign) ? $curr_obj->abbr : '';
$price_tag = ($item->discount > 0) ?
", at {$item->discount}% off":
" - {$curr_obj->sign}$priceFormatted$curr_abbr";
$d_price_tag = ($item->discount > 0) ?
", at {$item->discount}% off":
" - \$$dollarPriceFormatted";
} else {
$price_tag = '';
$d_price_tag = '';
}
$text = "{$item_name}$price_tag by $designerName";
$pi_html = "$item_link \n {$item_name}$d_price_tag by $designerName \n $trim_desc";
$tw_text = "$text$trim_cat #design";
$tu_html = "<a href='$item_link'><strong>$text</strong></a><br/>$desc";
$result->facebook = new stdClass();
$result->twitter = new stdClass();
$result->tumblr = new stdClass();
$result->pinterest = new stdClass();
if(empty($item->video)) {
$result->facebook->link = FB_LINK . '?' . http_build_query(array(
'u'=>$item_link,
'display'=>'popup',
'redirect_uri'=>FACEBOOK_TRACK
), '', '&');
$result->twitter->link = TW_LINK . '?' . http_build_query(array(
'original_referrer'=> DOMAIN . $_SERVER['PHP_SELF'],
'url'=>$item_link,
'related'=>'CityBlis',
'via'=>'CityBlis',
'text'=>$tw_text
), '', '&');
$result->tumblr->link = TU_LINK . '?' . http_build_query(array(
'source'=>$main_image,
'caption'=>$tu_html,
'clickthru'=> $item_link
), '', '&');
$result->pinterest->link = PI_LINK . '?' . http_build_query(array(
'url'=>$item_link,
'media'=>$main_image,
'description'=>$pi_html
), '', '&');
} else {
$video_link = youtube_vimeo($item->video);
$result->facebook->link = FB_LINK . '?' . http_build_query(array(
'link'=>$item_link,
'display'=>'popup',
'source'=>$video_link,
'picture'=>$main_image,
'redirect_uri'=>FACEBOOK_TRACK
), '', '&');
$result->twitter->link = TW_LINK . '?' . http_build_query(array(
'original_referrer'=> DOMAIN . $_SERVER['PHP_SELF'],
'url'=>$item_link,
'related'=>'CityBlis',
'via'=>'CityBlis',
'text'=>$tw_text
), '', '&');
$result->tumblr->link = TU_LINK . '?' . http_build_query(array(
'embed'=>$video_link,
'caption'=>$tu_html
), '', '&');
$result->pinterest->link = PI_LINK . '?' . http_build_query(array(
'url'=>$video_link,
'media'=>$main_image,
'description'=>$pi_html,
'is_video'=>'true'
), '', '&');
}
return $result;
}
function inline_product_share($input) {
$item = do_complicated_stuff($input);
$item->facebook->title = FB_TITLE;
$item->facebook->innerStyle = '';
$item->facebook->dimensions = '';
$item->facebook->follow = '';
$item->twitter->title = TW_TITLE;
$item->twitter->innerStyle = '';
$item->twitter->dimensions = '';
$item->twitter->follow = '';
$item->tumblr->title = TU_TITLE;
$item->tumblr->innerStyle = '';
$item->tumblr->dimensions = '';
$item->tumblr->follow = '';
$item->pinterest->title = PI_TITLE;
$item->pinterest->innerStyle = '';
$item->pinterest->dimensions = '';
$item->pinterest->follow = '';
return order_output($item);
}
//does the ordering of the output and returns the resultant string
function order_output($item) {
$style_string = "position:relative;display:inline-block;width:25px;height:25px;
overflow:hidden;margin-left:4px;vertical-align:top;border-radius:17px;
background-image: url(\"/i/iSpr.png\");"; //TODO: make it an absolute path when we put it up
$style = " style='$style_string;";
$item->facebook->style = $style . "background-color:#3c5897;background-position:-28px 0px;'";
$item->twitter->style = $style . "background-color:#2daae0;background-position:-55px 0px;'";
$item->tumblr->style = $style . "background-color:#2a4361;background-position:-82px 0px;'";
$item->pinterest->style = $style . "background-color:#ca1f25;background-position:-108px 0px;'";
return output_item($item->facebook) .
output_item($item->twitter) .
output_item($item->tumblr) .
output_item($item->pinterest);
}
//its only responsibility is to accept an object to return the output html
function output_item($item) {
ob_start();
?><div<?php echo $item->style?>><a target="_blank" title="<?php
echo $item->title?>"<?php
echo $item->innerStyle?> href="<?php
echo $item->link
?>"<?php
echo $item->follow?><?php
echo $item->dimensions?>><?php
echo $item->title?></a></div><?php
$output = ob_get_contents();
ob_end_clean();
return $output;
}
答案 0 :(得分:0)
我不相信我有足够的信息可以击中头部,因为你没有说A,B,C和D的性质。但是,如果它们像子类一样,我们想要对所有继承的操作执行某种操作,我们有iam
函数来对待它们。条件我不知道从哪里来,所以我把它作为一个参数添加到匿名函数索引中,它是从条件中删除的,是从创建函数的范围中关闭的。
function iam(item, index)
{
return "I am " . item . index; // Might be more advanced than this
}
function do_complicated_stuff(input, condition) {
array_of_abcd = db_readabcd(input);
index = (condition ? 1 : 2);
handle = function(item)
{
// function has index as free variable
return iam( item, index );
}
// Use map to iterate over the elelemts of the array
// applying handle on each one
return map(handle array_of_abcd);
}
此示例显示了函数式编程的两个属性。闭包和更高阶函数。 Scheme中也是如此:
(define (iam item index)
(string-append "I am "
item
index))
(define (do-complecated-stuff input condition)
(let ([array-of-abcd (db-readabcd input)] ; get data
[index (number->string (if condition 1 2))]) ; get index
; use map to iterate over elements with an anonymous function
(map (lambda (item) (iam item index)) array-of-abcd)))