1

我是函数式编程的新手,我想学习如何通过组合函数来构建我的程序(这样我就可以根据自己的需要选择使用哪些函数)

我有很长的命令式代码块,在伪代码中是这样的:

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)最终的返回值应该是“我是A1”,如果是假的并且是“我是B2” 。one_itemAconditionconditionone_itemB

我知道我将如何以 OOP 方式做到这一点,我想我会有一堆对象知道如何处理他们自己的数据,我只需要调用 item.other_stuff() 就可以了。我将如何以更实用的风格编写相同的东西,组合许多简短的函数来做一件事,最终给我想要的“我是 L#”结果?请注意,对于有时重叠并且有时在每种情况之间完全不同的八种情况中的每一种,您都需要不同的数据库信息。所以它目前非常复杂而且不是很简单,因为我当前代码中的函数超过 100 行,并且明确地处理了所有 8 种情况。更糟糕的是,同样的事情以不同的方式再次以不同的输出格式(如“这是 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
            ), '', '&amp;');
        $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
            ), '', '&amp;');
        $result->tumblr->link = TU_LINK . '?' . http_build_query(array(
                'source'=>$main_image,
                'caption'=>$tu_html,
                'clickthru'=> $item_link
            ), '', '&amp;');
        $result->pinterest->link = PI_LINK . '?' . http_build_query(array(
                'url'=>$item_link,
                'media'=>$main_image,
                'description'=>$pi_html
            ), '', '&amp;');
    } 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
            ), '', '&amp;');
        $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
            ), '', '&amp;');
        $result->tumblr->link = TU_LINK . '?' . http_build_query(array(
                'embed'=>$video_link,
                'caption'=>$tu_html
            ), '', '&amp;');
        $result->pinterest->link = PI_LINK . '?' . http_build_query(array(
                'url'=>$video_link,
                'media'=>$main_image,
                'description'=>$pi_html,
                'is_video'=>'true'
            ), '', '&amp;');
    }

    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;
}
4

1 回答 1

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)))
于 2013-08-20T20:59:57.717 回答