杀手级半独特编程语言功能[关闭]


25

当学习一种新的编程语言时,有时会遇到一种语言功能,这使您希望自己在其他已知的编程语言中拥有该功能。

在学习时对您来说还很新,您希望其他编程语言具有哪些语言功能。

一个示例是Python或C#中的生成器。其他示例可能包括Python中的列表推导,C ++中的模板或.NET中的LINQ或Haskell中的惰性评估。

您还遇到了哪些其他半独特的语言功能,这些功能是全新的并且对您有启发性?旧的编程语言是否还有其他独特且过时的功能?

Answers:


25

哈斯克尔几乎所有东西

  • 单子。是的-吓人的大字使解析器,IO,对列表的操作和其他操作变得非常容易(一旦您注意到通用模式)
  • 箭头。高级用户也一样;)
  • 标准商品,例如lambdas等。
  • 咖喱功能
  • 代数数据类型
  • 模式匹配

还有很多。

PS。是。如果有人问我,我是Haskell迷。


12
公平地说,您应该为该列表的大部分提供ML功劳。
优厚

1
好吧-除了Monad和IIRC箭。但是他们仍然是 -unique
马切伊Piechotka

否决票有任何特殊原因吗?
Maciej Piechotka 2010年

2
+1用于模式匹配。我把它展示给其他人,但他们不明白。我认为这是天才。
巴里·布朗

强制性的(steve-yegge.blogspot.com/2010/12/…)。顺便说一句,我几乎不会认为lambda是唯一的,python,C#,javascript等。Monads?大多数其他语言将其称为链接。jquery核心实质上是一组庞大的HTML / DOM和AJAX monad(Google:jQuery.fn)。如今,咖喱也相对普遍。
伊万·普赖斯

21

Lisp宏。

Lisp宏语言是Lisp,为方便起见具有一些预定义的语法功能。使用它们,可以为语言添加主要功能,例如选择对象的面向对象样式或类似Prolog的确定性匹配,而又不会显得不合适。它使setf宏成为可能,该宏在概念上非常强大: (setf A B)意味着,当您评估时,A您会得到B,并且可以扩展到您喜欢的任何限制。

C ++模板元编程具有类似的功能,但所用语言与常规C ++完全不同。


+1我希望有一天我能用Lisp语言编程。
奥利弗·韦勒

@Helper ...通过C ++模板[吓人的笑声]
mlvljr

@mlvjr:你很害怕。
David Thornley,2010年

事实上,它是唯一的,你永远都需要的语言外的现成功能。使用Lisp宏,您以后可以添加所有其他可能的功能。
SK-logic

18

Python的装饰器。

使用装饰器实现备忘录或功能计时非常容易。

功能计时器的示例。

class FuncTimer(object):
    """ Time how much time a function takes """
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
        self.start_time = time.time()
    def __call__(self, *args):
        self.memo['return'] = self.fn(*args)
        print("Function '%s' took %u seconds" % (self.fn.__name__, time.time() - self.start_time))
        return self.memo['return']

现在,如果您有想要计时的功能foo,则只需执行此操作,

@FuncTimer
def foo():
    # foo's implememtation goes here

你会看到类似的东西,

函数“ foo”花费了3秒钟。


Java具有注释,它们具有相似的用途和语法,但工作方式却非常不同
Casebash 2010年

1
+1:Python的装饰器给我的印象比语言中几乎所有其他功能都深刻。它们非常漂亮和简单!
亚当·佩恩特

也许您可以与我们分享一个简单的例子?我不知道Python是老实的。
ShdNx

@ShdNx,我只是添加了一个示例。
grokus

1
开始时间不应该算作通话的一部分吗?
熟练地

14

void*在C中进行强制转换。您可以将所有内容强制转换为原始字节,并对这些数据执行任何操作

(是的,如今独特...)


1
.Net语言中的对象非常相似。只有更多的类型安全等
马切伊Piechotka

您可以使用多种语言来投射对象。主要问题是许多语言
将原

5
@Maciej:即使在.NET中,您也无法真正将基元转换为Object。你把它们装箱,那是完全不同的野兽。此外,与施放void*... 仍然完全不同...
Dean Harding 2010年

1
Pointer在Pascal和Object Pascal中强制转换为相同的功能。
Frank Shearar 2010年

1
@DeanHarding:好吧-在C语言中int64_t,您不能始终将其强制转换void *(对不起-2年-答复)。
Maciej Piechotka

12

Python的收益

在Python(我相信C#)中,您可以定义一个所谓的生成器,该生成器在一条yield语句中暂停函数执行,返回值,并在随后的调用中,从中断处重新启动函数(在两次调用之间保留状态)。这对于生成仅对函数的当前值感兴趣的很长的值列表非常有用(这很常见)。它使您可以构建可能无限长的序列,同时仅占用内存中非常有限的空间。


1
产量已在问题中列出。
特立尼达

这一直可以追溯到BCPL。
彼得·泰勒

8

Lambda表达式(闭包,嵌套函数,匿名方法,无论您如何称呼它们)。

我首先在Perl中遇到了它们,立即爱上了它们,并想知道为什么其他语言没有它们。如今,我猜它已经不再那么独特了。甚至PHP也设法以某种方式破解了它们。但是当时它们是半独特的。


5
只要您回溯到Lisp(这是第二古老的编程语言),它就是唯一的。;-)
Michael H.

-1:不半唯一
Casebash


7

Delphi中的集合非常有用,几乎只是一个命名的布尔数组。它们对于保存带有32个复选框的设置表单非常有用。但是它们具有相同的集合理论函数(即差,交集,并集)。

我不确定它们是否过时,但我一直都在使用它们。


很好,但是用Java实现起来并不容易,例如:boolean []?
Mark C 2010年

是的,可以,但是我不这么简洁:TForm =(FF_1500 = 1,FF_CA251 = 5,FF_UB04 = 6,FF_MA10 = 7);TFormSet = TForm的集合;
彼得·特纳

7

发送

来自Erlang。将消息发送到另一个线程异步

Expr1 ! Expr2

接收

来自Erlang。从另一个线程接收消息。

receive
    Pattern1 [when GuardSeq1] ->
        Body1;
    ...;
    PatternN [when GuardSeqN] ->
        BodyN
end

5

C#属性

/// <summary>
/// Get ID
/// </summary>
public int ID
{
    get; set;
}

(Java)

/**
 * Name of user
 */
private String name;

/**
 * Gets name of user
 * @return Name of user
 */
public String getName() {
    return this.name;
}

/**
 * Sets name of user. 
 * @param name
 */
public void setName(final String name) {
    this.name = name;
}

2
是的,它们更好,但这是一个不好的例子。如果getter / setter实际上会做一些特殊的事情,并且C#版本的文档记录较少,则差异将小得多。
Bart van Heukelom 2010年

1
我的老板强烈反对C#的自动属性,每当对此争论不休时,我们两个人都不知道为什么另一个是对还是错。我之所以喜欢它们,是因为它们使代码更加整洁,并从长远来看为我节省了很多时间。
mbillard'9

2
只是不要允许这样做鼓励人们到处都使用吸气剂和吸气剂。仅应使用对对象的操作有意义的吸气剂和吸气剂。
David Thornley 2010年

3
它们不被称为C#属性,它们被称为自动属性
Jaco Pretorius

1
如今,自动属性非常普遍。Python,Objective-C ...
Casebash

5

C中的联盟

老实说,我还没有编写足够的C语言来自己编写这些代码,但是我已经与其他代码一起工作了。

归结为在处理原始位/字节的应用程序(例如网络或二进制数据存储)中打包不同数据的混合。在强类型语言中,没有简单的方法可以做到等效。

免责声明:

尽管联合在某些情况下非常有用,但是在大多数高级语言中都找不到联合,因为它们的类型不安全。IE,您可以使用并集使数据跨变量边界流失(在类型安全的世界中非常重要)。拥有权利的同时也被赋予了重大的责任。


2
恕我直言,有充分的理由。重新解释数据是步行拍摄自己的美丽方式(en.wikipedia.org/wiki/Aliasing_(computing))。更好地使用显式转换恕我直言。联盟做得正确的方式是恕我直言代数数据类型。
Maciej Piechotka

@Maciej我添加了必要的免责声明。虽然,我不确定它能否准确解释使用工会的危险,因为我对使用工会没有真正的了解。我只知道,在我看到他们使用代码的地方,与同等水平的语言相比,它更加简洁和易于使用。
Evan Plaice 2010年

问题在于,C是“高级语言”(仅是高级语言)。从K&R C开始,它有了很多规则,可以使用更快的可移植代码。代价是编译器可能会承担各种各样的事情,而有些事情会感到困惑。使用的大多数union是安全的,有些是习惯用法(尽管从技术上讲是不正确的)-请参阅cellperformance.beyond3d.com/articles/2006/06/…(尽管指针联合会带来更多的麻烦,但很容易伪造它)。
Maciej Piechotka 2010年

Delphi扩展了其record语法以支持工会:in_addr = record case integer of 0: (S_un_b: SunB); 1: (S_un_w: SunW); 2: (S_addr: u_long); end;
Frank Shearar 2010年

5

我真的很喜欢Ruby中exclude修饰符。看起来很自然,并且替换了很多没有代码就显得很混乱的场景。

puts "All good" unless input.nil?

你怎么会不喜欢 :D


6
Perl在Ruby之前就拥有它。我也爱它。
巴里·布朗

1
Nemerle有类似的关键字unlesswhen可以代替传统上最常用的分支方案if/else
MattDavey

5

花式python参数语法

我不确定这有多独特,但是在python中,您可以做一些很酷的事情,例如将关键字对自动编入字典并返回。与列表相同:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"


parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')

python文档(向下滚动以获得更多的参数粘贴内容)


1
+1表示能够传递列表中较深的参数,不必传递其之前所有可选参数的值。
eswald

4

C预处理程序。您甚至可以使用-更少或更多-ifdefs将通用代码编写到不同的平台。


2
有更好的预处理器,可以随时采取自己的额外步骤,并与所有语言一起使用。
David Thornley 2010年

我对ifdef,ifndef等非常满意。
ern0

3

Objective-C类别

类别提供了一种在运行时扩展对象功能的简便方法(考虑组成与继承)。经典示例是将拼写检查器添加到NSString类。

@interface NSString (SpellChecker)
- (BOOL) checkSpelling;
@end

对于低影响力的错误修复也很有用,因为类别的方法实现将覆盖其父级实现。


1
与C#中的扩展方法非常相似
Casebash

2

Rubyinject方法与Ruby 1.9 的Symbol#to_proc功能相结合,使人们可以编写一些非常简洁(但仍可读)的代码:

例如 (1..10).inject(:+)

将1到10的整数相加=> 55

看到这样的例子使我想学习Ruby,这是我刚刚开始做的。


9
为了公平起见,注射是Ruby的版本折/与foldl从象Lisp,哈斯克尔等语言/ foldr相似
mipadi

我真的不会称其为独特。
Daenyth's

1
问题的标题是“半唯一”,不是唯一。当然,结合注入(或映射等)和Symbol#to_proc所提供的代码的简洁性远远超出了C,Java和C ++等主流语言。
tcrosley

非常简洁(我喜欢),但是我不确定它是否与以下类似:Enumerable.Range(1,10).Aggregate((s,x)=> s + x); C#或其他语言提供的内容
FinnNk,2010年

1

JavaFX(RIP)中的绑定机制。通过bind关键字,您可以将变量的值绑定到表达式的值,并摆脱所有那些难看的Listener样板代码。

尽管JavaFX在许多方面都相当失败,但我发现脚本语言的许多功能都非常不错。


1

D中的字符串mixins加上编译时函数评估是一个非常独特的杀手级功能。是的,从技术上讲,这是两个功能,但是真正的力量来自于将它们结合在一起。通过这种组合,您可以编写常规D函数,这些D函数在编译时将生成的代码生成为字符串,然后将该代码混合到任何作用域中,并将其评估为常规D代码。该代码是完全静态编译的,并且完全像手写一样执行。此功能甚至用于解决标准库中的一些棘手情况。


我也喜欢从方法自动推断出的返回类型
。– nawfal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.