代码之家  ›  专栏  ›  技术社区  ›  Christian

什么时候“lambda动作”太多?

  •  12
  • Christian  · 技术社区  · 15 年前

    我经常发现自己使用lambda作为某种“局部功能”,以使我的生活更轻松地进行这些重复操作:

    Func<string, string> GetText = (resource) => this.resourceManager.GetString(resource);
    Func<float, object, string> FormatF1 = (f, o) => String.Format("{0:F1} {1}", f, o);
    Func<float, object, string> FormatF2 = (f, o) => String.Format("{0:F2} {1}", f, o);
    

    我不需要一遍又一遍地写string.format之类的东西,我可以很高兴地用formatf2(格式2)吹走,这样可以节省时间,当我需要更改格式时,只有一个地方可以进行编辑。 尤其是当我只需要给定函数中的功能时,我非常不愿意将它们转换为真正的函数。虽然上面的羊羔比较小…有时我会有更大的,比如(下面应该将数据添加到一个表中以进行打印输出):

    Action<string, string, string> AddSurfaceData = (resource, col, unit) => {
        renderTable.Cells[tableRowIndex, 0].Text = "\t" + this.GetText(resource);
        renderTable.Cells[tableRowIndex, 1].Text = FormatF2(paraHydReader.GetFloat(paraHydReader.GetOrdinal(col)), "");
        renderTable.Cells[tableRowIndex, 1].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Right;
        renderTable.Cells[tableRowIndex, 2].Text = " " + this.GetText(unit);
        renderTable.Cells[tableRowIndex, 2].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Left;
        ++tableRowIndex;
    };
    

    同样,我需要经常这样做,并且上述的所有好处也同样适用。但是,正如您所看到的,对于lambda表达式来说,这个表达式相当长。问题是:你什么时候画这条线?我的最后一个lambda太多了吗?还有什么其他方法(除了使用真正的函数或尝试将数据填充到容器中并循环它们)可以避免反复编写相同的代码?

    提前谢谢

    基督教的

    8 回复  |  直到 14 年前
        1
  •  11
  •   awe    15 年前

    它是您在一个方法中可能多次使用的东西,并且只在该方法中使用。我喜欢这个主意。如果它不会使代码难以读取,那么就执行它。我想说,如果您发现很难看到lambda函数的内容与方法的实际内容之间的关系,您应该重新考虑一下。在这种情况下,以单独的私有方法将其拉出可能会更干净。

    最后,这真的是一个品味问题…

        2
  •  6
  •   peSHIr    14 年前

    我同意awe:对于方法(甚至是类)内的小规模重用,这是完美的。就像 string.Format 例子。我经常用这个。它基本上与使用一个局部变量作为一个中间值是一样的,你使用了不止一次, but then for code .

    你的第二个例子似乎有点过分。不知怎的,这给了我一种私密的感觉 AddSurfaceData (可能是静态的,取决于其用途?)会更合适。这当然超出了你所处的环境,所以要运用你自己的判断力。

        3
  •  4
  •   Community CDub    8 年前

    lambda方法是匿名方法。

    这意味着你不应该给它起名字。

    如果您这样做(在您的例子中,您是通过引用分配一个名称),这只是声明函数的另一种方法。

    C已经有了一种声明函数的方法,它不是lambda方法,而是添加的 唯一地通过参数传递函数并将其作为返回值返回。

    以javascript为例:

    function f(var1,var2,...,varX)
    {
        some code
    }
    

    var f = function() {
        some code    
    }
    

    不同的语法(几乎)是一样的。

    如需了解与此不同的原因的更多信息: Javascript: var functionName = function() {} vs function functionName() {}

    另一个例子:在haskell中,可以定义两个函数:

     function1 :: Int -> Int
     function1 x = x + 2
    

     function2 :: Int -> Int
     function2 = \x -> x + 2
    

    相同的东西(这次我认为是非常相同的),不同的语法。我更喜欢第一个,更清楚一点。

    C 3.5作为javascript,有很多功能上的影响。其中一些应该被明智地使用,imho。

    有人说在引用中带有赋值的局部lambda函数是另一个方法中定义的方法的一个很好的替代品,类似于haskell中的“let”或“where”子句。

    我之所以说“相似”,是因为这两个词的语义非常不同,例如,在haskell中,我可以使用尚未声明的函数名,然后用“where”定义它,而在c中,使用函数/引用赋值时,我不能这样做。

    顺便说一下,我认为这是一个好主意,我不是禁止使用lambda函数,我只是想让人们考虑一下。 每种语言都有自己的抽象机制,明智地使用它。

        4
  •  2
  •   Niki    15 年前

    我喜欢这个主意。我不认为有更好的方法可以在不违反dry原则的情况下维护代码位置。我认为,如果你不习惯羔羊肉,阅读起来就更难了。

        5
  •  2
  •   Ruben Bartelink    15 年前

    +1.尼基一般都很好。

    不过,我不会为它们使用pascalcase命名。

    不过要小心——在大多数情况下,你所拥有的东西只是衣服中的一个提取方法,或者潜在的助手或扩展函数。例如。, GetText 是一种方法 FormatF* 可能是一个帮助方法…

        6
  •  2
  •   Wade    15 年前

    我不反对这个长例子。我看到您正在非常优雅地重新打包复合数据。

    这是短的,将推动你的同事调查的优势自愿制度化。请声明某种常量来保存格式字符串,并反复使用“that string.format-thing”。作为一个C程序员,我不需要在其他地方寻找自编函数就知道这是什么。这样,当我需要知道格式化后的字符串是什么样子时,我可以检查常量。

        7
  •  1
  •   Community CDub    8 年前

    我同意 volothamp 一般来说,但除此之外…

    想想其他必须维护您的代码的人。我认为这比您的第一个示例更容易理解,并且仍然提供您提到的维护好处:

    String.Format(this.resourceManager.GetString("BasicFormat"), f, o);
    String.Format(this.resourceManager.GetString("AdvancedFormat"), f, o);
    

    第二个示例似乎只是声明函数的另一种方法。我认为声明一个助手方法没有任何有用的好处。对于大多数编码人员来说,声明一个助手方法会更容易理解。

        8
  •  0
  •   Andrew Keith    15 年前

    我个人认为在不需要lambda函数的情况下使用lambda函数是不明智的。我个人不会使用lambda函数来替换简单的几行过程代码。lambda函数提供了许多增强功能,但使代码的读取稍微复杂一些。

    我不会用它来替换string.format。