对于我来说,使用动态类型语言(对象或查找该对象的键)的参数似乎很常见。例如,当我使用数据库时,我可能有一个方法getMyRelatedStuff(person)
所有我真的需要查找相关的东西是该人的id所以我的方法在python中看起来像这样:
def getMyRelatedStuff(person_or_id):
id = person_or_id.id if isinstance(person,User) else person_or_id
#do some lookup
或走向另一个方向:
def someFileStuff(file_or_name):
file = file_or_name if hasattr(file,'write') else open(file_or_name)
编辑:我正在为此寻找内置语法,我能想到的最接近的是C#中的隐式和显式关键字,允许您在类型之间定义强制转换。
答案 0 :(得分:9)
我以编程语言为生。我从未见过具有该操作的内置语法的语言。我甚至不确定你想要这样的语法,特别是因为你可以为任何这些模式定义一个函数。
喜欢可扩展语法的人倾向于定义Lisp宏: - )
答案 1 :(得分:3)
您在寻找function overloading吗? 例如:
doSomething(Person p);
// these could do lookup and dispatch to doSomething(Person p)...
doSomething(String personName);
doSomething(Integer personId);
任何OO强类型语言都应该能够做到这一点。
对于动态类型语言,虽然我不知道除了手动执行某种类型检查(instanceof)操作之外的任何其他方式,并且该方法可能非常快速地变得令人讨厌。你最好只做我们在OOP之前做的事情:使用不同命名的函数,例如:
doSomethingByName(personName);
doSomethingById(personId);
如果您的代码结构合理,那么大多数这些“重复”函数都会非常小。
答案 2 :(得分:2)
Scheme,LISP,或任何带有宏的语言。
答案 3 :(得分:1)
您可以使用在编译时不检查函数参数类型的任何语言来执行此操作。
JavaScript的:
function doSomething(person)
{
var name;
if(typeof(person) == "string")
name = person;
else
name = person.name;
//you can simplify it to
name = (typeof(person) == "string") ? name : person.name;
}
答案 4 :(得分:1)
我从未在我使用的任何语言中看到内置语法。
请注意,在Python中,这通常由例外处理:
def getMyRelatedStuff(person_or_id):
"The verbose way"
try:
my_id= person_or_id.id
except AttributeError:
my_id= person_or_id
但最好是:
def getMyRelatedStuff(person_or_id):
"The terse way"
my_id= getattr(person_or_id, "id", person_or_id)
和someFileStuff
:
def someFileStuff(file_or_name):
try:
fobj= open(file_or_name)
except TypeError:
fobj= file_or_name
尽量避免在代码中使用id
和file
等内置名称;它们会为您的程序带来微妙的错误。
答案 5 :(得分:0)
<强> Lisp的强>
这可以使用Lisp宏轻松实现:
(defmacro get-if-not [func val alt]
`(if (~func ~val)
~val
~alt))
您可以像这样使用该表达式:
(get-if-not file? file_or_name (open file_or_name))
那将扩展为:
(if (file? file_or_name) file_or_name (open file_or_name))
宏令人难以置信。我个人拒绝使用任何没有它们的语言。